diff options
Diffstat (limited to 'source/blender/editors/interface/interface.c')
-rw-r--r-- | source/blender/editors/interface/interface.c | 267 |
1 files changed, 160 insertions, 107 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index e70b793cfb0..8aed0d58a07 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -74,6 +74,13 @@ #define MENU_ITEM_HEIGHT 20 #define MENU_SEP_HEIGHT 6 +#define PRECISION_FLOAT_MAX 6 +#define PRECISION_FLOAT_MAX_POW 1000000 /* pow(10, PRECISION_FLOAT_MAX) */ + +/* avoid unneeded calls to ui_get_but_val */ +#define UI_BUT_VALUE_UNSET DBL_MAX +#define UI_GET_BUT_VALUE_INIT(_but, _value) if(_value == DBL_MAX) { (_value)= ui_get_but_val(_but); } + /* * a full doc with API notes can be found in bf-blender/trunk/blender/doc/guides/interface_API.txt * @@ -449,6 +456,57 @@ void uiCenteredBoundsBlock(uiBlock *block, int addval) /* link line drawing is not part of buttons or theme.. so we stick with it here */ +static int ui_but_float_precision(uiBut *but, double value) +{ + int prec; + + /* first check if prec is 0 and fallback to a simple default */ + if((prec= (int)but->a2) == 0) { + prec= (but->hardmax < 10.001f) ? 3 : 2; + } + + /* check on the number of decimal places neede to display + * the number, this is so 0.00001 is not displayed as 0.00, + * _but_, this is only for small values si 10.0001 will not get + * the same treatment */ + if(value != 0.0 && (value= ABS(value)) < 0.1) { + int value_i= (int)((value * PRECISION_FLOAT_MAX_POW) + 0.5); + if(value_i != 0) { + const int prec_span= 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */ + int test_prec; + int prec_min= -1; + int dec_flag= 0; + int i= PRECISION_FLOAT_MAX; + while(i && value_i) { + if(value_i % 10) { + dec_flag |= 1<<i; + prec_min= i; + } + value_i /= 10; + i--; + } + + /* even though its a small value, if the second last digit is not 0, use it */ + test_prec = prec_min; + + dec_flag= (dec_flag >> (prec_min + 1)) & ((1 << prec_span) - 1); + + while(dec_flag) { + test_prec++; + dec_flag = dec_flag >> 1; + } + + if(test_prec > prec) { + prec= test_prec; + } + } + } + + CLAMP(prec, 1, PRECISION_FLOAT_MAX); + + return prec; +} + static void ui_draw_linkline(uiLinkLine *line) { rcti rect; @@ -556,7 +614,7 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut // but->flag= oldbut->flag; #else /* exception! redalert flag can't be update from old button. - * perhaps it should only copy spesific flags rather then all. */ + * perhaps it should only copy spesific flags rather than all. */ // but->flag= (oldbut->flag & ~UI_BUT_REDALERT) | (but->flag & UI_BUT_REDALERT); #endif // but->active= oldbut->active; @@ -892,13 +950,14 @@ void uiDrawBlock(const bContext *C, uiBlock *block) /* widgets */ for(but= block->buttons.first; but; but= but->next) { - ui_but_to_pixelrect(&rect, ar, block, but); + if(!(but->flag & (UI_HIDDEN|UI_SCROLLED))) { + ui_but_to_pixelrect(&rect, ar, block, but); - if(!(but->flag & UI_HIDDEN) && /* XXX: figure out why invalid coordinates happen when closing render window */ /* and material preview is redrawn in main window (temp fix for bug #23848) */ - rect.xmin < rect.xmax && rect.ymin < rect.ymax) - ui_draw_but(C, ar, &style, but, &rect); + if(rect.xmin < rect.xmax && rect.ymin < rect.ymax) + ui_draw_but(C, ar, &style, but, &rect); + } } /* restore matrix */ @@ -912,17 +971,16 @@ void uiDrawBlock(const bContext *C, uiBlock *block) /* ************* EVENTS ************* */ -static void ui_is_but_sel(uiBut *but) +static void ui_is_but_sel(uiBut *but, double *value) { - double value; /* only initialized when needed, to avoid calling when not used */ short push=0, true=1; if(ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) true= 0; if( but->bit ) { int lvalue; - value= ui_get_but_val(but); - lvalue= (int)value; + UI_GET_BUT_VALUE_INIT(but, *value) + lvalue= (int)*value; if( BTST(lvalue, (but->bitnr)) ) push= true; else push= !true; } @@ -942,24 +1000,24 @@ static void ui_is_but_sel(uiBut *but) case BUT_TOGDUAL: case ICONTOG: case OPTION: - value= ui_get_but_val(but); - if(value != (double)but->hardmin) push= 1; + UI_GET_BUT_VALUE_INIT(but, *value) + if(*value != (double)but->hardmin) push= 1; break; case ICONTOGN: case TOGN: case OPTIONN: - value= ui_get_but_val(but); - if(value==0.0) push= 1; + UI_GET_BUT_VALUE_INIT(but, *value) + if(*value==0.0) push= 1; break; case ROW: case LISTROW: - value= ui_get_but_val(but); + UI_GET_BUT_VALUE_INIT(but, *value) /* support for rna enum buts */ if(but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) { - if((int)value & (int)but->hardmax) push= 1; + if((int)*value & (int)but->hardmax) push= 1; } else { - if(value == (double)but->hardmax) push= 1; + if(*value == (double)but->hardmax) push= 1; } break; case COL: @@ -1330,6 +1388,10 @@ void ui_set_but_val(uiBut *but, double value) break; } } + + /* we can't be sure what RNA set functions actually do, + * so leave this unset */ + value= UI_BUT_VALUE_UNSET; } else if(but->pointype==0); else if(but->type==HSVSLI ) { @@ -1370,19 +1432,19 @@ void ui_set_but_val(uiBut *but, double value) /* then set value with possible edit override */ if(but->editval) - *but->editval= value; + value= *but->editval= value; else if(but->pointype==CHA) - *((char *)but->poin)= (char)value; + value= *((char *)but->poin)= (char)value; else if(but->pointype==SHO) - *((short *)but->poin)= (short)value; + value= *((short *)but->poin)= (short)value; else if(but->pointype==INT) - *((int *)but->poin)= (int)value; + value= *((int *)but->poin)= (int)value; else if(but->pointype==FLO) - *((float *)but->poin)= (float)value; + value= *((float *)but->poin)= (float)value; } /* update select flag */ - ui_is_but_sel(but); + ui_is_but_sel(but, &value); } int ui_get_but_string_max_length(uiBut *but) @@ -1444,8 +1506,8 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va if(scene->unit.scale_length<0.0001f) scene->unit.scale_length= 1.0f; // XXX do_versions /* Sanity checks */ - if(precision>7) precision= 7; - else if(precision==0) precision= 2; + if(precision > PRECISION_FLOAT_MAX) precision= PRECISION_FLOAT_MAX; + else if(precision==0) precision= 2; bUnit_AsString(str, len_max, ui_get_but_scale_unit(but, value), precision, scene->unit.system, unit_type>>16, do_split, pad); } @@ -1529,10 +1591,7 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen) ui_get_but_string_unit(but, str, maxlen, value, 0); } else { - int prec= (int)but->a2; - if(prec==0) prec= 3; - else CLAMP(prec, 1, 7); - + const int prec= ui_but_float_precision(but, value); BLI_snprintf(str, maxlen, "%.*f", prec, value); } } @@ -1668,23 +1727,20 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) return 0; } -void ui_set_but_default(bContext *C, uiBut *but, short all) +void ui_set_but_default(bContext *C, short all) { - /* if there is a valid property that is editable... */ - if (but->rnapoin.data && but->rnaprop && RNA_property_editable(&but->rnapoin, but->rnaprop)) { - int index = (all)? -1 : but->rnaindex; - - if(RNA_property_reset(&but->rnapoin, but->rnaprop, index)) { - /* perform updates required for this property */ - RNA_property_update(C, &but->rnapoin, but->rnaprop); - } - } + PointerRNA ptr; + + WM_operator_properties_create(&ptr, "UI_OT_reset_default_button"); + RNA_boolean_set(&ptr, "all", all); + WM_operator_name_call(C, "UI_OT_reset_default_button", WM_OP_EXEC_DEFAULT, &ptr); + WM_operator_properties_free(&ptr); } static double soft_range_round_up(double value, double max) { /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */ - double newmax= pow(10.0, ceil(log(value)/log(10.0))); + double newmax= pow(10.0, ceil(log(value)/M_LN10)); if(newmax*0.2 >= max && newmax*0.2 >= value) return newmax*0.2; @@ -1697,7 +1753,7 @@ static double soft_range_round_up(double value, double max) static double soft_range_round_down(double value, double max) { /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */ - double newmax= pow(10.0, floor(log(value)/log(10.0))); + double newmax= pow(10.0, floor(log(value)/M_LN10)); if(newmax*5.0 <= max && newmax*5.0 <= value) return newmax*5.0; @@ -1709,50 +1765,70 @@ static double soft_range_round_down(double value, double max) void ui_set_but_soft_range(uiBut *but, double value) { - PropertyType type; - double softmin, softmax /*, step, precision*/; - + /* ideally we would not limit this but practially, its more then + * enough worst case is very long vectors wont use a smart soft-range + * which isnt so bad. */ + if(but->rnaprop) { - type= RNA_property_type(but->rnaprop); + const PropertyType type= RNA_property_type(but->rnaprop); + double softmin, softmax /*, step, precision*/; + double value_min= value; + double value_max= value; /* clamp button range to something reasonable in case * we get -inf/inf from RNA properties */ if(type == PROP_INT) { int imin, imax, istep; + const int array_len= RNA_property_array_length(&but->rnapoin, but->rnaprop); RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep); softmin= (imin == INT_MIN)? -1e4: imin; softmax= (imin == INT_MAX)? 1e4: imax; /*step= istep;*/ /*UNUSED*/ /*precision= 1;*/ /*UNUSED*/ + + if(array_len >= 2) { + int value_range[2]; + RNA_property_int_get_array_range(&but->rnapoin, but->rnaprop, value_range); + value_min= (double)value_range[0]; + value_max= (double)value_range[1]; + } } else if(type == PROP_FLOAT) { float fmin, fmax, fstep, fprecision; + const int array_len= RNA_property_array_length(&but->rnapoin, but->rnaprop); RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision); softmin= (fmin == -FLT_MAX)? (float)-1e4: fmin; softmax= (fmax == FLT_MAX)? (float)1e4: fmax; /*step= fstep;*/ /*UNUSED*/ /*precision= fprecision;*/ /*UNUSED*/ + + if(array_len >= 2) { + float value_range[2]; + RNA_property_float_get_array_range(&but->rnapoin, but->rnaprop, value_range); + value_min= (double)value_range[0]; + value_max= (double)value_range[1]; + } } else return; /* if the value goes out of the soft/max range, adapt the range */ - if(value+1e-10 < softmin) { - if(value < 0.0) - softmin= -soft_range_round_up(-value, -softmin); + if(value_min+1e-10 < softmin) { + if(value_min < 0.0) + softmin= -soft_range_round_up(-value_min, -softmin); else - softmin= soft_range_round_down(value, softmin); + softmin= soft_range_round_down(value_min, softmin); if(softmin < (double)but->hardmin) softmin= (double)but->hardmin; } - else if(value-1e-10 > softmax) { - if(value < 0.0) - softmax= -soft_range_round_down(-value, -softmax); + else if(value_max-1e-10 > softmax) { + if(value_max < 0.0) + softmax= -soft_range_round_down(-value_max, -softmax); else - softmax= soft_range_round_up(value, softmax); + softmax= soft_range_round_up(value_max, softmax); if(softmax > (double)but->hardmax) softmax= but->hardmax; @@ -1848,29 +1924,24 @@ void uiFreeInactiveBlocks(const bContext *C, ListBase *lb) void uiBlockSetRegion(uiBlock *block, ARegion *region) { - ListBase *lb; + ListBase *lb= ®ion->uiblocks; uiBlock *oldblock= NULL; - lb= ®ion->uiblocks; - /* each listbase only has one block with this name, free block * if is already there so it can be rebuilt from scratch */ if(lb) { - for (oldblock= lb->first; oldblock; oldblock= oldblock->next) - if (BLI_streq(oldblock->name, block->name)) - break; + oldblock= BLI_findstring(lb, block->name, offsetof(uiBlock, name)); if (oldblock) { oldblock->active= 0; oldblock->panel= NULL; } + + /* at the beginning of the list! for dynamical menus/blocks */ + BLI_addhead(lb, block); } block->oldblock= oldblock; - - /* at the beginning of the list! for dynamical menus/blocks */ - if(lb) - BLI_addhead(lb, block); } uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, short dt) @@ -1930,17 +2001,19 @@ void uiBlockSetEmboss(uiBlock *block, char dt) void ui_check_but(uiBut *but) { /* if something changed in the button */ - double value; + double value= UI_BUT_VALUE_UNSET; // float okwidth; // UNUSED // int transopts= ui_translate_buttons(); - ui_is_but_sel(but); + ui_is_but_sel(but, &value); // if(but->type==TEX || but->type==IDPOIN) transopts= 0; /* only update soft range while not editing */ - if(but->rnaprop && !(but->editval || but->editstr || but->editvec)) - ui_set_but_soft_range(but, ui_get_but_val(but)); + if(but->rnaprop && !(but->editval || but->editstr || but->editvec)) { + UI_GET_BUT_VALUE_INIT(but, value) + ui_set_but_soft_range(but, value); + } /* test for min and max, icon sliders, etc */ switch( but->type ) { @@ -1949,17 +2022,20 @@ void ui_check_but(uiBut *but) case SCROLL: case NUMSLI: case HSVSLI: - value= ui_get_but_val(but); + UI_GET_BUT_VALUE_INIT(but, value) if(value < (double)but->hardmin) ui_set_but_val(but, but->hardmin); else if(value > (double)but->hardmax) ui_set_but_val(but, but->hardmax); break; case NUMABS: - value= fabs( ui_get_but_val(but) ); - if(value < (double)but->hardmin) ui_set_but_val(but, but->hardmin); - else if(value > (double)but->hardmax) ui_set_but_val(but, but->hardmax); + { + double value_abs; + UI_GET_BUT_VALUE_INIT(but, value) + value_abs= fabs(value); + if(value_abs < (double)but->hardmin) ui_set_but_val(but, but->hardmin); + else if(value_abs > (double)but->hardmax) ui_set_but_val(but, but->hardmax); break; - + } case ICONTOG: case ICONTOGN: if(!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) { @@ -1970,14 +2046,14 @@ void ui_check_but(uiBut *but) case ICONROW: if(!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) { - value= ui_get_but_val(but); + UI_GET_BUT_VALUE_INIT(but, value) but->iconadd= (int)value- (int)(but->hardmin); } break; case ICONTEXTROW: if(!but->rnaprop || (RNA_property_flag(but->rnaprop) & PROP_ICONS_CONSECUTIVE)) { - value= ui_get_but_val(but); + UI_GET_BUT_VALUE_INIT(but, value) but->iconadd= (int)value- (int)(but->hardmin); } break; @@ -1994,7 +2070,7 @@ void ui_check_but(uiBut *but) case ICONTEXTROW: if(but->x2 - but->x1 > 24) { - value= ui_get_but_val(but); + UI_GET_BUT_VALUE_INIT(but, value) ui_set_name_menu(but, (int)value); } break; @@ -2004,7 +2080,7 @@ void ui_check_but(uiBut *but) case HSVSLI: case NUMABS: - value= ui_get_but_val(but); + UI_GET_BUT_VALUE_INIT(but, value) if(ui_is_but_float(but)) { if(value == (double) FLT_MAX) sprintf(but->drawstr, "%sinf", but->str); @@ -2016,10 +2092,7 @@ void ui_check_but(uiBut *but) BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, new_str); } else { - int prec= (int)but->a2; - if(prec==0) prec= (but->hardmax < 10.001f) ? 3 : 2; - else CLAMP(prec, 1, 7); - + const int prec= ui_but_float_precision(but, value); BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value); } } @@ -2037,11 +2110,9 @@ void ui_check_but(uiBut *but) case LABEL: if(ui_is_but_float(but)) { - int prec= (int)but->a2; - value= ui_get_but_val(but); - if(prec==0) prec= 3; - else CLAMP(prec, 1, 7); - + int prec; + UI_GET_BUT_VALUE_INIT(but, value) + prec= ui_but_float_precision(but, value); BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value); } else { @@ -2066,8 +2137,10 @@ void ui_check_but(uiBut *but) strncpy(but->drawstr, but->str, UI_MAX_DRAW_STR); if (but->flag & UI_SELECT) { strcat(but->drawstr, "Press a key"); - } else { - strcat(but->drawstr, WM_key_event_string((short) ui_get_but_val(but))); + } + else { + UI_GET_BUT_VALUE_INIT(but, value) + strcat(but->drawstr, WM_key_event_string((short)value)); } break; @@ -2489,28 +2562,8 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s icon= RNA_property_ui_icon(prop); } } - - if(!tip) { - if(type == ROW && proptype == PROP_ENUM) { - EnumPropertyItem *item; - int i, totitem, free; - - RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free); - - for(i=0; i<totitem; i++) { - if(item[i].identifier[0] && item[i].value == (int)max) { - if(item[i].description[0]) - tip= item[i].description; - break; - } - } - - if(free) - MEM_freeN(item); - } - } - if(!tip) + if(!tip && proptype != PROP_ENUM) tip= RNA_property_ui_description(prop); if(min == max || a1 == -1 || a2 == -1) { |