user interface units, off by default.
authorCampbell Barton <ideasman42@gmail.com>
Tue, 11 Aug 2009 18:53:01 +0000 (18:53 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 11 Aug 2009 18:53:01 +0000 (18:53 +0000)
- currently only distances work.
- user preferences, edit section to set the units and scale.
- option to display pairs (nicer for imperial display?)
- support for evaluating multiple comma separated values eg: 2',11" ..or.. 5ft, 4mil
- comma separated expressions/values accumulate 1+1,2**3,4cm/3
- attempted fast conversion from a value to a string so button drawing isn't too slow.

* imperial long/short *
- mile, mi
- yard, yd
- foot, '
- inch, "
- thou, mil

* metric long/short *
kilometer, km
meter, m
centimeter, cm
millimeter, mm
micrometer, um
nanometer, nm
picometer, pm

16 files changed:
release/ui/bpy_ops.py
release/ui/space_info.py
source/blender/blenkernel/BKE_unit.h [new file with mode: 0644]
source/blender/blenkernel/intern/unit.c [new file with mode: 0644]
source/blender/editors/interface/interface.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesrna/intern/rna_lamp.c
source/blender/makesrna/intern/rna_material.c
source/blender/makesrna/intern/rna_meta.c
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/makesrna/intern/rna_world.c
source/blender/python/intern/bpy_interface.c

index 1d79f1a331f978186fef2ff849e50ed8d62e057c..aa9bfb460f0b5f0b86c1e94f050ab69daea87916 100644 (file)
@@ -111,48 +111,3 @@ class bpy_ops_submodule_op(object):
 
 import bpy
 bpy.ops = bpy_ops()
-
-
-
-
-# A bit out of place but add button conversion code here
-module_type = type(__builtins__)
-import types
-mod = types.ModuleType('button_convert')
-
-import sys
-sys.modules['button_convert'] = mod
-
-def convert(expr):
-       
-       def replace(string, unit, scaler):
-               # in need of regex
-               change = True
-               while change:
-                       change = False
-                       i = string.find(unit)
-                       if i != -1:
-                               if i>0 and not string[i-1].isalpha():
-                                       i_end = i+len(unit)
-                                       if i_end+1 >= len(string) or (not string[i_end+1].isalpha()):
-                                               string = string.replace(unit, scaler)
-                                               change = True
-               # print(string)
-               return string
-       
-       #imperial
-       expr = replace(expr, 'mi', '*1609.344')
-       expr = replace(expr, 'yd', '*0.9144')
-       expr = replace(expr, 'ft', '*0.3048')
-       expr = replace(expr, 'in', '*0.0254')
-       
-       # metric
-       expr = replace(expr, 'km', '*1000')
-       expr = replace(expr, 'm', '')
-       expr = replace(expr, 'cm', '*0.01')
-       expr = replace(expr, 'mm', '*0.001')
-       
-       return expr
-
-mod.convert = convert
-
index 366d5f5740c098dd086ef06d4419ef29d4cde38e..9ebbc68c2190168d4289b940c766c1b5fc31fa53 100644 (file)
@@ -320,7 +320,18 @@ class INFO_PT_edit(bpy.types.Panel):
                sub1.itemS()
                sub1.itemL(text="Transform:")
                sub1.itemR(edit, "drag_immediately")
+               sub1.itemS()
+               sub1.itemS()
+               sub1.itemS()
                
+               sub1.itemL(text="Units:")
+               sub1.itemR(edit, "unit_type")
+               
+               sub2 = sub1.column()
+               sub2.active = (edit.unit_type != 'NONE')
+               sub2.itemR(edit, "unit_scale_length")
+               sub2.itemR(edit, "use_unit_split")
+
                col = split.column()
                sub = col.split(percentage=0.85)
                
diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h
new file mode 100644 (file)
index 0000000..14b805c
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_UNIT_H
+#define BKE_UNIT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* in all cases the value is assumed to be scaled by the user preference */
+
+/* humanly readable representation of a value in units (used for button drawing) */
+void   bUnit_AsString(char *str, double value, int prec, int system, int type, int split, int pad);
+
+/* replace units with values, used before python button evaluation */
+int            bUnit_ReplaceString(char *str, char *str_orig, double scale_pref, int system, int type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BKE_UNIT_H */
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
new file mode 100644 (file)
index 0000000..04b0530
--- /dev/null
@@ -0,0 +1,267 @@
+/**
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+
+/* define a single unit */
+typedef struct bUnitDef {
+       char *name;
+
+       /* optional, can be null */
+       char *name_plural;
+       char *name_short;       /* this is used for display*/
+       char *name_alt;         /* alternative name */
+       
+       double mul;
+       double bias;
+} bUnitDef;
+
+/* define a single unit */
+typedef struct bUnitCollection {
+       struct bUnitDef *units;
+       int def;                                        /* default unit, use for 0.0, or none given */
+       int flag;                                       /* options for this system */
+} bUnitCollection;
+
+static struct bUnitDef buMetricLenDef[] = {
+       {"kilometer", "kilometers",             "km", NULL,     1000.0, 0.0},
+       {"meter", "meters",                             "m",  NULL,     1.0, 0.0},
+       {"centimeter", "centimeters",   "cm", NULL,     0.01, 0.0},
+       {"millimeter", "millimeters",   "mm", NULL,     0.001, 0.0},
+       {"micrometer", "micrometers",   "um", "┬Ám",    0.000001, 0.0}, // micron too?
+       {"nanometer", "nanometers",             "nm", NULL,     0.000000001, 0.0},
+       {"picometer", "picometers",             "pm", NULL,     0.000000000001, 0.0},
+       {NULL, NULL, NULL,      NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buMetricLenCollecton = {buMetricLenDef, 1, 0};
+
+#define IMPERIAL_DEFAULT 3 /* inch */
+static struct bUnitDef buImperialLenDef[] = {
+       {"mile", "miles",                               "mi", "m",      1609.344, 0.0},
+       {"yard", "yards",                               "yd", NULL,     0.9144, 0.0},
+       {"foot", "feet",                                "'", "ft",      0.3048, 0.0},
+       {"inch", "inches",                              "\"", "in",     0.0254, 0.0},
+       {"thou", "thous",                               "mil", NULL,0.0000254, 0.0},
+       {NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 2, 0};
+
+static struct bUnitCollection *bUnitSystems[][8] = {
+       {0,&buMetricLenCollecton, 0,0,0,0,0,0}, /* metric */
+       {0,&buImperialLenCollecton, 0,0,0,0,0,0}, /* imperial */
+       {0,0,0,0,0,0,0,0}
+};
+
+/* internal, has some option not exposed */
+static bUnitCollection *unit_get_system(int system, int type)
+{
+       return bUnitSystems[system-1][type];
+}
+
+static bUnitDef *unit_best_fit(double value, bUnitCollection *usys, bUnitDef *unit_start)
+{
+       bUnitDef *unit;
+       double value_abs= value>0.0?value:-value;
+
+       for(unit= unit_start ? unit_start:usys->units; unit->name; unit++)
+               if (value_abs >= unit->mul)
+                       return unit;
+
+       return &usys->units[usys->def];
+}
+
+/* convert into 2 units and 2 values for "2ft, 3inch" syntax */
+static void unit_dual_convert(double value, bUnitCollection *usys,
+               bUnitDef **unit_a, bUnitDef **unit_b, double *value_a, double *value_b)
+{
+       bUnitDef *unit= unit_best_fit(value, usys, NULL);
+
+       *value_a= floor(value/unit->mul) * unit->mul;
+       *value_b= value - (*value_a);
+
+       *unit_a=        unit;
+       *unit_b=        unit_best_fit(*value_b, usys, *unit_a);
+}
+
+static int unit_as_string(char *str, double value, int prec, bUnitCollection *usys,
+               /* non exposed options */
+               bUnitDef *unit, char pad)
+{
+       double value_conv;
+       int len, i;
+       
+       if(unit) {
+               /* use unit without finding the best one */
+       }
+       else if(value == 0.0) {
+               /* use the default units since there is no way to convert */
+               unit= &usys->units[usys->def];
+       }
+       else {
+               unit= unit_best_fit(value, usys, NULL);
+       }
+
+       value_conv= value/unit->mul;
+
+       /* Convert to a string */
+       {
+               char conv_str[5] = {'%', '.', '0'+prec, 'f', '\0'}; /* "%.2f" when prec is 2, must be under 10 */
+               len= sprintf(str, conv_str, (float)value_conv);
+       }
+       
+       
+       /* Add unit prefix and strip zeros */
+       {
+               /* replace trailing zero's with spaces 
+                * so the number is less complicated but allignment in a button wont
+                * jump about while dragging */
+               int j;
+               i= len-1;
+
+       
+               while(i>0 && str[i]=='0') { /* 4.300 -> 4.3 */
+                       str[i--]= pad;
+               }
+               
+               if(i>0 && str[i]=='.') { /* 10. -> 10 */
+                       str[i--]= pad;
+               }
+               
+               /* Now add the suffix */
+               i++;
+               j=0;
+               while(unit->name_short[j]) {
+                       str[i++]= unit->name_short[j++];
+               }
+
+               if(pad) {
+                       /* this loop only runs if so many zeros were removed that
+                        * the unit name only used padded chars,
+                        * In that case add padding for the name. */
+
+                       while(i<=len+j) {
+                               str[i++]= pad;
+                       }
+               }
+               
+               /* terminate no matter whats done with padding above */
+               str[i] = '\0';
+       }
+
+       return i;
+}
+
+/* Used for drawing number buttons, try keep fast */
+void bUnit_AsString(char *str, double value, int prec, int system, int type, int split, int pad)
+{
+       bUnitCollection *usys = unit_get_system(system, type);
+
+       if(split) {
+               int i;
+               bUnitDef *unit_a, *unit_b;
+               double value_a, value_b;
+
+               unit_dual_convert(value, usys,          &unit_a, &unit_b, &value_a, &value_b);
+
+               /* check the 2 is a smaller unit */
+               if(unit_b > unit_a) {
+                       i= unit_as_string(str, value_a, prec, usys,    unit_a, '\0');
+                       i= strlen(str);
+                       str[i++]= ',';
+                       str[i++]= ' ';
+
+                       /* use low precision since this is a smaller unit */
+                       unit_as_string(str+i, value_b, prec?1:0, usys, unit_b, '\0');
+                       return;
+               }
+       }
+
+       unit_as_string(str, value, prec, usys,    NULL, pad?' ':'\0');
+}
+
+
+static int unit_scale_str(char *str, char *str_tmp, double scale_pref, bUnitDef *unit, char *replace_str)
+{
+       char *str_found;
+       int change= 0;
+
+       if(replace_str && (str_found= strstr(str, replace_str))) {
+               /* previous char cannot be a letter */
+               if (str_found == str || isalpha(*(str_found-1))==0) {
+                       int len_name = strlen(replace_str);
+
+                       /* next char cannot be alphanum */
+                       if (!isalpha(*(str_found+len_name))) {
+                               int len= strlen(str);
+                               int len_num= sprintf(str_tmp, "*%g", scale_pref*unit->mul);
+                               memmove(str_found+len_num, str_found+len_name, (len+1)-(int)((str_found+len_name)-str)); /* may grow or shrink the string, 1+ to copy the string terminator */
+                               memcpy(str_found, str_tmp, len_num); /* without the string terminator */
+                               change= 1;
+                       }
+               }
+       }
+       return change;
+}
+
+static int unit_replace(char *str, char *str_tmp, double scale_pref, bUnitDef *unit)
+{      
+       //unit_replace_delimit(str, str_tmp);
+       int change= 0;
+       change |= unit_scale_str(str, str_tmp, scale_pref, unit, unit->name_short);
+       change |= unit_scale_str(str, str_tmp, scale_pref, unit, unit->name_plural);
+       change |= unit_scale_str(str, str_tmp, scale_pref, unit, unit->name_alt);
+       change |= unit_scale_str(str, str_tmp, scale_pref, unit, unit->name);
+       return change;
+}
+
+/* make a copy of the string that replaces the units with numbers
+ * this is used before parsing
+ * This is only used when evaluating user input and can afford to be a bit slower
+ * 
+ * This is to be used before python evaluation so..
+ * 10.1km -> 10.1*1000.0
+ * ...will be resolved by python.
+ * 
+ * return true of a change was made.
+ */
+int bUnit_ReplaceString(char *str, char *str_orig, double scale_pref, int system, int type)
+{
+       bUnitCollection *usys = unit_get_system(system, type);
+       bUnitDef *unit;
+       char str_tmp[256];
+       int change= 0;
+       
+       strcpy(str, str_orig);
+       
+       for(unit= usys->units; unit->name; unit++) {
+               /* incase there are multiple instances */
+               while(unit_replace(str, str_tmp, scale_pref, unit))
+                       change= 1;
+       }
+
+       return change;
+}
index 1c58d087ec43b1b8aaeea7470bb14150036516af..26984e954e16efa09231425954d55883307bc228 100644 (file)
@@ -48,6 +48,7 @@
 #include "BKE_screen.h"
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
+#include "BKE_unit.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
@@ -1362,7 +1363,15 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen)
                value= ui_get_but_val(but);
 
                if(ui_is_but_float(but)) {
-                       if(but->a2) { /* amount of digits defined */
+
+                       if(but->rnaprop && (RNA_property_subtype(but->rnaprop) & PROP_UNIT_LENGTH && U.unit_type != USER_UNIT_NONE)) {
+                               int prec = but->a2;
+                               if(prec>4)                      prec= 4;
+                               else if(prec==0)        prec= 2;
+
+                               bUnit_AsString(str, value*U.unit_scale_length, prec, U.unit_type, PROP_UNIT_LENGTH>>16, U.unit_flag&USER_UNIT_OPT_SPLIT, 0);
+                       }
+                       else if(but->a2) { /* amount of digits defined */
                                if(but->a2==1) BLI_snprintf(str, maxlen, "%.1f", value);
                                else if(but->a2==2) BLI_snprintf(str, maxlen, "%.2f", value);
                                else if(but->a2==3) BLI_snprintf(str, maxlen, "%.3f", value);
@@ -1437,11 +1446,17 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
 
                /* XXX 2.50 missing python api */
 #ifndef DISABLE_PYTHON
-               if(BPY_button_eval(C, str, &value)) {
-                       value = ui_get_but_val(but); /* use its original value */
+               {
+                       char str_unit_convert[256];
                        
-                       if(str[0])
-                               return 0;
+                       bUnit_ReplaceString(str_unit_convert, str, U.unit_scale_length, U.unit_type, PROP_UNIT_LENGTH>>16);
+
+                       if(BPY_button_eval(C, str_unit_convert, &value)) {
+                               value = ui_get_but_val(but); /* use its original value */
+
+                               if(str[0])
+                                       return 0;
+                       }
                }
 #else
                value= atof(str);
@@ -1787,6 +1802,19 @@ void ui_check_but(uiBut *but)
                if(ui_is_but_float(but)) {
                        if(value == FLT_MAX) sprintf(but->drawstr, "%sinf", but->str);
                        else if(value == -FLT_MAX) sprintf(but->drawstr, "%s-inf", but->str);
+                       /* support length type buttons */
+                       else if(but->rnaprop && (RNA_property_subtype(but->rnaprop) & PROP_UNIT_LENGTH && U.unit_type != USER_UNIT_NONE)) {
+                               char new_str[256];
+                               int prec = but->a2;
+                               if(prec>4)                      prec= 4;
+                               else if(prec==0)        prec= 2;
+
+                               if(U.unit_scale_length==0.0) U.unit_scale_length= 1.0; // XXX do_versions
+
+                               bUnit_AsString(new_str, value*U.unit_scale_length, prec, U.unit_type, PROP_UNIT_LENGTH>>16, U.unit_flag&USER_UNIT_OPT_SPLIT, 1);
+
+                               sprintf(but->drawstr, "%s%s", but->str, new_str);
+                       }
                        else if(but->a2) { /* amount of digits defined */
                                if(but->a2==1) sprintf(but->drawstr, "%s%.1f", but->str, value);
                                else if(but->a2==2) sprintf(but->drawstr, "%s%.2f", but->str, value);
index 36cd0c6ffdf36f86c35eccf07deb10bc7f6851f0..cf32e4e2980e64f3ed0ba1521846b51f5eb917d8 100644 (file)
@@ -642,7 +642,7 @@ typedef struct Scene {
        float twmin[3], twmax[3];       /* boundbox of selection for transform widget */
        unsigned int lay;
        
-       
+
        short flag;                                                             /* various settings */
        
        short use_nodes;
index 4a317dfb3694bceff89f5ff4802ada3b38710aef..6b9b1086c7f522ff1006b7979ddce13829a43d39 100644 (file)
@@ -299,7 +299,9 @@ typedef struct UserDef {
        int audiochannels;
 
        int scrollback; /* console scrollback limit */
-       int dpi;                /* range 48-128? */
+       float unit_scale_length, pad1; /* maybe have other unit conversions? */
+       char unit_type, unit_flag; /* imperial, metric etc */
+       short dpi;              /* range 48-128? */
        short encoding;
        short transopts;
        short menuthreshold1, menuthreshold2;
@@ -416,6 +418,12 @@ extern UserDef U; /* from blenkernel blender.c */
        /* toolsettings->autokey_flag */
 #define        ANIMRECORD_FLAG_WITHNLA         (1<<10)
 
+/* unit_type */
+#define        USER_UNIT_NONE                  0
+#define        USER_UNIT_METRIC                1
+#define        USER_UNIT_IMPERIAL              2
+/* unit_flag */
+#define        USER_UNIT_OPT_SPLIT             1
 
 /* transopts */
 #define        USER_TR_TOOLTIPS                (1 << 0)
index 16dc4fbc8cbd52b79df3547ef66f1e5c1e81cfff..57aa1ba2736489d672283fbad11237644641152e 100644 (file)
@@ -314,7 +314,7 @@ static void rna_def_lamp(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Type", "Type of Lamp.");
        RNA_def_property_update(prop, NC_LAMP|ND_LIGHTING_DRAW, NULL);
 
-       prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "dist");
        RNA_def_property_ui_range(prop, 0, 1000, 1.0, 2);
        RNA_def_property_ui_text(prop, "Distance", "Falloff distance - the light is at half the original intensity at this point.");
@@ -465,7 +465,7 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
        RNA_def_property_ui_text(prop, "Shadow Adaptive Threshold", "Threshold for Adaptive Sampling (Raytraced shadows).");
        RNA_def_property_update(prop, NC_LAMP|ND_LIGHTING, NULL);
 
-       prop= RNA_def_property(srna, "shadow_soft_size", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "shadow_soft_size", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "soft");
        RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
        RNA_def_property_ui_text(prop, "Shadow Soft Size", "Light size for ray shadow sampling (Raytraced shadows).");
@@ -526,13 +526,13 @@ static void rna_def_area_lamp(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Shape", "Shape of the area lamp.");
        RNA_def_property_update(prop, NC_LAMP|ND_LIGHTING_DRAW, NULL);
 
-       prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "area_size");
        RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
        RNA_def_property_ui_text(prop, "Size", "Size of the area of the area Lamp, X direction size for Rectangle shapes.");
        RNA_def_property_update(prop, NC_LAMP|ND_LIGHTING_DRAW, NULL);
 
-       prop= RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "area_sizey");
        RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
        RNA_def_property_ui_text(prop, "Size Y", "Size of the area of the area Lamp in the Y direction for Rectangle shapes.");
@@ -628,13 +628,13 @@ static void rna_def_spot_lamp(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Spot Size", "Angle of the spotlight beam in degrees.");
        RNA_def_property_update(prop, NC_LAMP|ND_LIGHTING_DRAW, NULL);
 
-       prop= RNA_def_property(srna, "shadow_buffer_clip_start", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "shadow_buffer_clip_start", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "clipsta");
        RNA_def_property_range(prop, 0.0f, 9999.0f);
        RNA_def_property_ui_text(prop, "Shadow Buffer Clip Start", "Shadow map clip start: objects closer will not generate shadows");
        RNA_def_property_update(prop, NC_LAMP|ND_LIGHTING_DRAW, NULL);
 
-       prop= RNA_def_property(srna, "shadow_buffer_clip_end", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "shadow_buffer_clip_end", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "clipend");
        RNA_def_property_range(prop, 0.0f, 9999.0f);
        RNA_def_property_ui_text(prop, "Shadow Buffer Clip End", "Shadow map clip end beyond which objects will not generate shadows.");
index e6de6a46c8e206b7227f46b9d611b7c331424c88..4ac3996d0a57b78abdf04d2e57e74114f7427e5d 100644 (file)
@@ -708,7 +708,7 @@ static void rna_def_material_raymirror(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Depth", "Maximum allowed number of light inter-reflections.");
        RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);
        
-       prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "dist_mir");
        RNA_def_property_range(prop, 0.0f, 10000.0f);
        RNA_def_property_ui_text(prop, "Maximum Distance", "Maximum distance of reflected rays. Reflections further than this range fade to sky color or material color.");
@@ -784,7 +784,7 @@ static void rna_def_material_raytra(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Filter", "Amount to blend in the material's diffuse color in raytraced transparency (simulating absorption).");
        RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);
        
-       prop= RNA_def_property(srna, "limit", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "limit", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "tx_limit");
        RNA_def_property_range(prop, 0.0f, 100.0f);
        RNA_def_property_ui_text(prop, "Limit", "Maximum depth for light to travel through the transparent material before becoming fully filtered (0.0 is disabled).");
@@ -941,7 +941,7 @@ static void rna_def_material_sss(BlenderRNA *brna)
        RNA_def_struct_nested(brna, srna, "Material");
        RNA_def_struct_ui_text(srna, "Material Subsurface Scattering", "Diffuse subsurface scattering settings for a Material datablock.");
 
-       prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_RGB);
+       prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_RGB|PROP_UNIT_LENGTH);
        RNA_def_property_float_sdna(prop, NULL, "sss_radius");
        RNA_def_property_range(prop, 0.001, FLT_MAX);
        RNA_def_property_ui_range(prop, 0.001, 10000, 1, 3);
@@ -1081,10 +1081,10 @@ void rna_def_material_strand(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Surface Diffuse", "Make diffuse shading more similar to shading the surface.");
        RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);
 
-       prop= RNA_def_property(srna, "blend_distance", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "blend_distance", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "strand_surfnor");
        RNA_def_property_range(prop, 0, 10);
-       RNA_def_property_ui_text(prop, "Blend Distance", "Distance in Blender units over which to blend in the surface normal.");
+       RNA_def_property_ui_text(prop, "Blend Distance", "Worldspace distance over which to blend in the surface normal.");
        RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);
 
        prop= RNA_def_property(srna, "blender_units", PROP_BOOLEAN, PROP_NONE);
index a5f4ef73f7bc8bc97129cb3665ea7f98dc832462..7b14a7a4712e90ba6d32022ffe472d8e3d295a88 100644 (file)
@@ -104,24 +104,24 @@ void rna_def_metaelement(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Rotation", "");
        RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
 
-       prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_UNSIGNED);
+       prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_UNSIGNED|PROP_UNIT_LENGTH);
        RNA_def_property_float_sdna(prop, NULL, "rad");
        RNA_def_property_ui_text(prop, "Radius", "");
        RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
 
-       prop= RNA_def_property(srna, "size_x", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "size_x", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "expx");
        RNA_def_property_range(prop, 0.0f, 20.0f);
        RNA_def_property_ui_text(prop, "Size X", "Size of element, use of components depends on element type.");
        RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
 
-       prop= RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "expy");
        RNA_def_property_range(prop, 0.0f, 20.0f);
        RNA_def_property_ui_text(prop, "Size Y", "Size of element, use of components depends on element type.");
        RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
 
-       prop= RNA_def_property(srna, "size_z", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "size_z", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "expz");
        RNA_def_property_range(prop, 0.0f, 20.0f);
        RNA_def_property_ui_text(prop, "Size Z", "Size of element, use of components depends on element type.");
@@ -176,13 +176,13 @@ void rna_def_metaball(BlenderRNA *brna)
        RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
        
        /* number values */
-       prop= RNA_def_property(srna, "wire_size", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "wire_size", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "wiresize");
        RNA_def_property_range(prop, 0.050f, 1.0f);
        RNA_def_property_ui_text(prop, "Wire Size", "Polygonization resolution in the 3D viewport.");
        RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
        
-       prop= RNA_def_property(srna, "render_size", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "render_size", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "rendersize");
        RNA_def_property_range(prop, 0.050f, 1.0f);
        RNA_def_property_ui_text(prop, "Render Size", "Polygonization resolution in rendering.");
index 87e102a9a54766024c0c899299111400eddf4cff..2833e0da10db4f9d0ce4ddc8647e56d51e372d95 100644 (file)
@@ -824,7 +824,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
        RNA_def_property_range(prop, 0.01, 10000.0);
        RNA_def_property_ui_text(prop, "Mass", "Mass of the object.");
 
-       prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE|PROP_UNIT_LENGTH);
        RNA_def_property_float_sdna(prop, NULL, "inertia");
        RNA_def_property_range(prop, 0.01, 10.0);
        RNA_def_property_ui_text(prop, "Radius", "Radius for Bounding sphere and Fh/Fh Rot.");
@@ -922,7 +922,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "gameflag", OB_CHILD);
        RNA_def_property_ui_text(prop, "Collison Compound", "Add children to form a compound collision object.");
 
-       prop= RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_NONE|PROP_UNIT_LENGTH);
        RNA_def_property_float_sdna(prop, NULL, "margin");
        RNA_def_property_range(prop, 0.0, 1.0);
        RNA_def_property_ui_text(prop, "Collision Margin", "Extra margin around object for collision detection, small amount required for stability.");
@@ -1218,7 +1218,7 @@ static void rna_def_object(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Empty Draw Type", "Viewport display style for empties.");
        RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL);
 
-       prop= RNA_def_property(srna, "empty_draw_size", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "empty_draw_size", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "empty_drawsize");
        RNA_def_property_range(prop, 0.01, 10.0);
        RNA_def_property_ui_text(prop, "Empty Draw Size", "Size of of display for empties in the viewport.");
@@ -1344,25 +1344,25 @@ static void rna_def_object(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Dupli Group", "Instance an existing group.");
        RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_dependency_update");
 
-       prop= RNA_def_property(srna, "dupli_frames_start", PROP_INT, PROP_NONE);
+       prop= RNA_def_property(srna, "dupli_frames_start", PROP_INT, PROP_NONE|PROP_UNIT_TIME);
        RNA_def_property_int_sdna(prop, NULL, "dupsta");
        RNA_def_property_range(prop, 1, 32767);
        RNA_def_property_ui_text(prop, "Dupli Frames Start", "Start frame for DupliFrames.");
        RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_update");
 
-       prop= RNA_def_property(srna, "dupli_frames_end", PROP_INT, PROP_NONE);
+       prop= RNA_def_property(srna, "dupli_frames_end", PROP_INT, PROP_NONE|PROP_UNIT_TIME);
        RNA_def_property_int_sdna(prop, NULL, "dupend");
        RNA_def_property_range(prop, 1, 32767);
        RNA_def_property_ui_text(prop, "Dupli Frames End", "End frame for DupliFrames.");
        RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_update");
 
-       prop= RNA_def_property(srna, "dupli_frames_on", PROP_INT, PROP_NONE);
+       prop= RNA_def_property(srna, "dupli_frames_on", PROP_INT, PROP_NONE|PROP_UNIT_TIME);
        RNA_def_property_int_sdna(prop, NULL, "dupon");
        RNA_def_property_range(prop, 1, 1500);
        RNA_def_property_ui_text(prop, "Dupli Frames On", "Number of frames to use between DupOff frames.");
        RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_update");
 
-       prop= RNA_def_property(srna, "dupli_frames_off", PROP_INT, PROP_NONE);
+       prop= RNA_def_property(srna, "dupli_frames_off", PROP_INT, PROP_NONE|PROP_UNIT_TIME);
        RNA_def_property_int_sdna(prop, NULL, "dupoff");
        RNA_def_property_range(prop, 0, 1500);
        RNA_def_property_ui_text(prop, "Dupli Frames Off", "Recurring frames to exclude from the Dupliframes.");
@@ -1370,7 +1370,7 @@ static void rna_def_object(BlenderRNA *brna)
 
        /* time offset */
 
-       prop= RNA_def_property(srna, "time_offset", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "time_offset", PROP_FLOAT, PROP_NONE|PROP_UNIT_TIME);
        RNA_def_property_float_sdna(prop, NULL, "sf");
        RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
        RNA_def_property_ui_text(prop, "Time Offset", "Animation offset in frames for IPO's and dupligroup instances.");
index 63f9c1b50e9cd5972db0e04ce87c222aa3796328..97320c0f9d4fe2f408a88305b1de31b526c340d0 100644 (file)
@@ -1641,7 +1641,7 @@ void RNA_def_scene(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "World", "World used for rendering the scene.");
        RNA_def_property_update(prop, NC_WORLD, NULL);
 
-       prop= RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ);
+       prop= RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ|PROP_UNIT_LENGTH);
        RNA_def_property_float_sdna(prop, NULL, "cursor");
        RNA_def_property_ui_text(prop, "Cursor Location", "3D cursor location.");
        RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 4);
index 793970dea492a44b01df1e8367145599e0457564..d287261549c8b3a41e3c992180f49fdc04a0f7cb 100644 (file)
@@ -564,19 +564,19 @@ static void rna_def_space_3dview(BlenderRNA *brna)
        RNA_def_property_range(prop, 1.0f, 250.0f);
        RNA_def_property_update(prop, NC_WINDOW, NULL);
        
-       prop= RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "near");
        RNA_def_property_range(prop, 0.0f, FLT_MAX);
        RNA_def_property_ui_text(prop, "Clip Start", "3D View near clipping distance.");
        RNA_def_property_update(prop, NC_WINDOW, NULL);
 
-       prop= RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "far");
        RNA_def_property_range(prop, 1.0f, FLT_MAX);
        RNA_def_property_ui_text(prop, "Clip End", "3D View far clipping distance.");
        RNA_def_property_update(prop, NC_WINDOW, NULL);
        
-       prop= RNA_def_property(srna, "grid_spacing", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "grid_spacing", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "grid");
        RNA_def_property_ui_text(prop, "Grid Spacing", "The distance between 3D View grid lines.");
        RNA_def_property_range(prop, 0.0f, FLT_MAX);
index 19b2b5376f7f55961ba5e4da6445fb42dc40c021..69ff1300f83940ce77b8a4ad46120e05e9dcab82 100644 (file)
@@ -1733,6 +1733,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
                {BEZT_IPO_BEZ, "BEZIER", 0, "Bezier", ""},
                {0, NULL, 0, NULL, NULL}};
 
+       static EnumPropertyItem unit_types[] = {
+               {USER_UNIT_NONE, "NONE", 0, "None", ""},
+               {USER_UNIT_METRIC, "METRIC", 0, "Metric", ""},
+               {USER_UNIT_IMPERIAL, "IMPERIAL", 0, "Imperial", ""},
+               {0, NULL, 0, NULL, NULL}};
+
        srna= RNA_def_struct(brna, "UserPreferencesEdit", NULL);
        RNA_def_struct_sdna(srna, "UserDef");
        RNA_def_struct_nested(brna, srna, "UserPreferences");
@@ -1773,6 +1779,23 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_GLOBALUNDO);
        RNA_def_property_ui_text(prop, "Global Undo", "Global undo works by keeping a full copy of the file itself in memory, so takes extra memory.");
 
+       /* Units */
+       prop= RNA_def_property(srna, "unit_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, unit_types);
+       RNA_def_property_ui_text(prop, "Unit Type", "The unit system to use for button display.");
+       RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+       prop= RNA_def_property(srna, "unit_scale_length", PROP_FLOAT, PROP_UNSIGNED);
+       RNA_def_property_ui_text(prop, "Unit Scale", "Scale to use when converting between blender units and dimensions.");
+       RNA_def_property_range(prop, 0.00001, 100000.0);
+       RNA_def_property_ui_range(prop, 0.001, 100.0, 0.1, 3);
+       RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+       prop= RNA_def_property(srna, "use_unit_split", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "unit_flag", USER_UNIT_OPT_SPLIT);
+       RNA_def_property_ui_text(prop, "Separate Units", "Display units in pairs.");
+       RNA_def_property_update(prop, NC_WINDOW, NULL);
+
        /* snap to grid */
        prop= RNA_def_property(srna, "snap_translate", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOGRABGRID);
index e999ae5d601f190a62ac272d5c067a38e1e1b90b..525a444693244f6ede896e5faefbd644b7f0998e 100644 (file)
@@ -216,7 +216,7 @@ static void rna_def_ambient_occlusion(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "mode", WO_AMB_OCC);
        RNA_def_property_ui_text(prop, "Enabled", "Use Ambient Occlusion to add light based on distance between elements, creating the illusion of omnipresent light");
 
-       prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "aodist");
        RNA_def_property_ui_text(prop, "Distance", "Length of rays, defines how far away other faces give occlusion effect.");
 
@@ -319,19 +319,19 @@ static void rna_def_world_mist(BlenderRNA *brna)
        RNA_def_property_range(prop, 0, 1);
        RNA_def_property_ui_text(prop, "Intensity", "Intensity of the mist effect.");
 
-       prop= RNA_def_property(srna, "start", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "start", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "miststa");
        RNA_def_property_range(prop, 0, FLT_MAX);
        RNA_def_property_ui_range(prop, 0, 10000, 10, 2);
        RNA_def_property_ui_text(prop, "Start", "Starting distance of the mist, measured from the camera");
 
-       prop= RNA_def_property(srna, "depth", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "depth", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "mistdist");
        RNA_def_property_range(prop, 0, FLT_MAX);
        RNA_def_property_ui_range(prop, 0, 10000, 10, 2);
        RNA_def_property_ui_text(prop, "Depth", "The distance over which the mist effect fades in");
 
-       prop= RNA_def_property(srna, "height", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "height", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "misthi");
        RNA_def_property_range(prop, 0, 100);
        RNA_def_property_ui_text(prop, "Height", "Control how much mist density decreases with height");
@@ -363,7 +363,7 @@ static void rna_def_world_stars(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Size", "Average screen dimension of stars.");
        RNA_def_property_update(prop, NC_WORLD, NULL);
 
-       prop= RNA_def_property(srna, "min_distance", PROP_FLOAT, PROP_NONE);
+       prop= RNA_def_property(srna, "min_distance", PROP_FLOAT, PROP_DISTANCE);
        RNA_def_property_float_sdna(prop, NULL, "starmindist");
        RNA_def_property_range(prop, 0, 1000);
        RNA_def_property_ui_text(prop, "Minimum Distance", "Minimum distance to the camera for stars.");
index f8b2f38961d3069994ee061b80d1c4ab0923c868..eedbe3b224f1580a4d3994d54b9d733260502c8c 100644 (file)
@@ -808,44 +808,35 @@ float BPY_pydriver_eval (ChannelDriver *driver)
 int BPY_button_eval(bContext *C, char *expr, double *value)
 {
        PyGILState_STATE gilstate;
-       PyObject *dict, *retval, *expr_conv= NULL;
+       PyObject *dict, *retval;
        int error_ret = 0;
        
        if (!value || !expr || expr[0]=='\0') return -1;
        
        bpy_context_set(C, &gilstate);
        
-       // experemental, fun. "button_convert.convert" is currently defined in bpy_ops.py
-       {
-               PyObject *mod= PyDict_GetItemString(PySys_GetObject("modules"), "button_convert");
-               if(mod && PyModule_Check(mod))  {
-                       PyObject *mod_dict= PyModule_GetDict(mod);
-                       PyObject *func= PyDict_GetItemString(mod_dict, "convert");
-                       if(func) {
-                               PyObject *expr_conv = PyObject_CallFunction(func, "s", expr);
-                               if(expr_conv==NULL) {
-                                       PyErr_Print();
-                                       PyErr_Clear();
-                               }
-                               else {
-                                       expr= _PyUnicode_AsString(expr_conv); /* TODO, check */
-                               }
-                       }
-               }
-       }
-       
        dict= CreateGlobalDictionary(C);
        retval = PyRun_String(expr, Py_eval_input, dict, dict);
        
-       if(expr_conv) {
-               Py_DECREF(expr_conv); /* invalidates expr */
-       }
-       
        if (retval == NULL) {
                error_ret= -1;
        }
        else {
-               double val = PyFloat_AsDouble(retval);
+               double val;
+
+               if(PyTuple_Check(retval)) {
+                       /* Users my have typed in 10km, 2m
+                        * add up all values */
+                       int i;
+                       val= 0.0;
+
+                       for(i=0; i<PyTuple_GET_SIZE(retval); i++) {
+                               val+= PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i));
+                       }
+               }
+               else {
+                       val = PyFloat_AsDouble(retval);
+               }
                Py_DECREF(retval);
                
                if(val==-1 && PyErr_Occurred()) {