added time units, currently only used when metric or imperial are enabled.

long/short units...
day,d,  hour,hr,h,  minute,min,m, second,sec,s,  millisecond,ms,  microsecond,us

Also may fix some bugs that were reported.

Note, to convert fps to time evil_C needs to be used to get the scene.
This commit is contained in:
Campbell Barton 2009-08-12 05:20:16 +00:00
parent c77e556b23
commit 23e0571853
6 changed files with 88 additions and 35 deletions

View File

@ -325,10 +325,10 @@ class INFO_PT_edit(bpy.types.Panel):
sub1.itemS()
sub1.itemL(text="Units:")
sub1.itemR(edit, "unit_type")
sub1.itemR(edit, "unit_system")
sub2 = sub1.column()
sub2.active = (edit.unit_type != 'NONE')
sub2.active = (edit.unit_system != 'NONE')
sub2.itemR(edit, "unit_scale_length")
sub2.itemR(edit, "use_unit_split")

View File

@ -30,11 +30,9 @@
/* define a single unit */
typedef struct bUnitDef {
char *name;
/* optional, can be null */
char *name_plural;
char *name_plural; /* can be NULL */
char *name_short; /* this is used for display*/
char *name_alt; /* alternative name */
char *name_alt; /* can be NULL */
double mul;
double bias; /* not used yet, needed for converting temperature */
@ -43,13 +41,22 @@ typedef struct bUnitDef {
/* define a single unit */
typedef struct bUnitCollection {
struct bUnitDef *units;
int def; /* default unit, use for 0.0, or none given */
int base_unit; /* use for 0.0, or none given */
int flag; /* options for this system */
} bUnitCollection;
/* Dummy */
static struct bUnitDef buDummyDef[] = {
{"", NULL, "", NULL, 1.0, 0.0},
{NULL, NULL, NULL, NULL, 0.0, 0.0}
};
static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0};
/* Lengths */
static struct bUnitDef buMetricLenDef[] = {
{"kilometer", "kilometers", "km", NULL, 1000.0, 0.0},
{"meter", "meters", "m", NULL, 1.0, 0.0},
{"meter", "meters", "m", NULL, 1.0, 0.0}, /* base unit */
{"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?
@ -59,27 +66,41 @@ static struct bUnitDef buMetricLenDef[] = {
};
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},
{"inch", "inches", "\"", "in", 0.0254, 0.0}, /* base unit */
{"thou", "thous", "mil", NULL,0.0000254, 0.0},
{NULL, NULL, NULL, NULL, 0.0, 0.0}
};
static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 2, 0};
/* Time */
static struct bUnitDef buNaturalTimeDef[] = {
/* weeks? - probably not needed for blender */
{"day", "days", "d", NULL, 90000.0, 0.0},
{"hour", "hours", "hr", "h", 3600.0, 0.0},
{"minute", "minutes", "min", "m", 60.0, 0.0},
{"second", "seconds", "sec", "s", 1.0, 0.0}, /* base unit */
{"millisecond", "milliseconds", "ms", NULL, 0.001, 0.0},
{"microsecond", "microseconds", "us", NULL, 0.000001, 0.0},
{NULL, NULL, NULL, NULL, 0.0, 0.0}
};
static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 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},
{0,&buMetricLenCollecton, 0,0,0,0, &buNaturalTimeCollecton,0}, /* metric */
{0,&buImperialLenCollecton, 0,0,0,0, &buNaturalTimeCollecton,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];
return bUnitSystems[system][type]; /* select system to use, metric/imperial/other? */
}
static bUnitDef *unit_best_fit(double value, bUnitCollection *usys, bUnitDef *unit_start)
@ -91,7 +112,7 @@ static bUnitDef *unit_best_fit(double value, bUnitCollection *usys, bUnitDef *un
if (value_abs >= unit->mul)
return unit;
return &usys->units[usys->def];
return &usys->units[usys->base_unit];
}
/* convert into 2 units and 2 values for "2ft, 3inch" syntax */
@ -119,7 +140,7 @@ static int unit_as_string(char *str, double value, int prec, bUnitCollection *us
}
else if(value == 0.0) {
/* use the default units since there is no way to convert */
unit= &usys->units[usys->def];
unit= &usys->units[usys->base_unit];
}
else {
unit= unit_best_fit(value, usys, NULL);
@ -181,6 +202,9 @@ void bUnit_AsString(char *str, double value, int prec, int system, int type, int
{
bUnitCollection *usys = unit_get_system(system, type);
if(usys==NULL || usys->units[0].name==NULL)
usys= &buDummyCollecton;
if(split) {
int i;
bUnitDef *unit_a, *unit_b;
@ -209,7 +233,10 @@ static int unit_scale_str(char *str, char *str_tmp, double scale_pref, bUnitDef
char *str_found;
int change= 0;
if(replace_str && (str_found= strstr(str, replace_str))) {
if(replace_str==NULL || replace_str[0] == '\0')
return 0;
if((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);
@ -255,6 +282,9 @@ int bUnit_ReplaceString(char *str, char *str_orig, double scale_pref, int system
char str_tmp[256];
int change= 0;
if(usys==NULL || usys->units[0].name==NULL)
return 0;
strcpy(str, str_orig);
for(unit= usys->units; unit->name; unit++) {
@ -262,6 +292,6 @@ int bUnit_ReplaceString(char *str, char *str_orig, double scale_pref, int system
while(unit_replace(str, str_tmp, scale_pref, unit))
change= 1;
}
// printf("replace %s\n", str);
return change;
}

View File

@ -1308,6 +1308,36 @@ int ui_get_but_string_max_length(uiBut *but)
return UI_MAX_DRAW_STR;
}
static double ui_get_but_scale_unit(uiBut *but, double value)
{
int subtype= RNA_property_subtype(but->rnaprop);
if(subtype & PROP_UNIT_LENGTH) {
return value * U.unit_scale_length;
}
else if(subtype & PROP_UNIT_TIME) { /* WARNING - using evil_C :| */
Scene *scene= CTX_data_scene((bContext *)but->block->evil_C);
return FRA2TIME(value);
}
else {
return value;
}
}
static void ui_get_but_string_unit(uiBut *but, char *str, double value, int pad)
{
int do_split= U.unit_flag & USER_UNIT_OPT_SPLIT ? 1:0;
int unit_system= RNA_SUBTYPE_UNIT_VALUE(RNA_property_subtype(but->rnaprop));
int precission= but->a2;
/* Sanity checks */
if(precission>4) precission= 4;
else if(precission==0) precission= 2;
bUnit_AsString(str, ui_get_but_scale_unit(but, value), precission, U.unit_system, unit_system, do_split, pad);
}
void ui_get_but_string(uiBut *but, char *str, int maxlen)
{
if(but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
@ -1364,12 +1394,8 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen)
if(ui_is_but_float(but)) {
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);
if(U.unit_system != USER_UNIT_NONE && but->rnaprop && RNA_SUBTYPE_UNIT_VALUE(RNA_property_subtype(but->rnaprop))) {
ui_get_but_string_unit(but, str, value, 0);
}
else if(but->a2) { /* amount of digits defined */
if(but->a2==1) BLI_snprintf(str, maxlen, "%.1f", value);
@ -1449,7 +1475,7 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
{
char str_unit_convert[256];
bUnit_ReplaceString(str_unit_convert, str, U.unit_scale_length, U.unit_type, PROP_UNIT_LENGTH>>16);
bUnit_ReplaceString(str_unit_convert, str, 1.0/ui_get_but_scale_unit(but, 1.0), U.unit_system, RNA_SUBTYPE_UNIT_VALUE(RNA_property_subtype(but->rnaprop)));
if(BPY_button_eval(C, str_unit_convert, &value)) {
value = ui_get_but_val(but); /* use its original value */
@ -1803,16 +1829,12 @@ void ui_check_but(uiBut *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)) {
else if(U.unit_system != USER_UNIT_NONE && but->rnaprop && RNA_SUBTYPE_UNIT_VALUE(RNA_property_subtype(but->rnaprop))) {
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);
ui_get_but_string_unit(but, new_str, value, TRUE);
sprintf(but->drawstr, "%s%s", but->str, new_str);
}
else if(but->a2) { /* amount of digits defined */

View File

@ -300,7 +300,7 @@ typedef struct UserDef {
int scrollback; /* console scrollback limit */
float unit_scale_length, pad1; /* maybe have other unit conversions? */
char unit_type, unit_flag; /* imperial, metric etc */
char unit_system, unit_flag; /* imperial, metric etc */
short dpi; /* range 48-128? */
short encoding;
short transopts;

View File

@ -80,6 +80,7 @@ typedef enum PropertyUnit {
} PropertyUnit;
#define RNA_SUBTYPE_UNIT(subtype) (subtype & 0x00FF0000)
#define RNA_SUBTYPE_UNIT_VALUE(subtype) (subtype>>16)
/* also update rna_property_subtypename when you change this */
typedef enum PropertySubType {

View File

@ -1733,7 +1733,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
{BEZT_IPO_BEZ, "BEZIER", 0, "Bezier", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem unit_types[] = {
static EnumPropertyItem unit_systems[] = {
{USER_UNIT_NONE, "NONE", 0, "None", ""},
{USER_UNIT_METRIC, "METRIC", 0, "Metric", ""},
{USER_UNIT_IMPERIAL, "IMPERIAL", 0, "Imperial", ""},
@ -1780,9 +1780,9 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
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.");
prop= RNA_def_property(srna, "unit_system", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, unit_systems);
RNA_def_property_ui_text(prop, "Unit System", "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);