diff options
Diffstat (limited to 'source/blender/editors/interface/interface.c')
-rw-r--r-- | source/blender/editors/interface/interface.c | 165 |
1 files changed, 116 insertions, 49 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 682db20af55..5f36c5e21bf 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -366,10 +366,10 @@ static void ui_block_bounds_calc_centered_pie(uiBlock *block) static void ui_block_bounds_calc_popup( wmWindow *window, uiBlock *block, - eBlockBoundsCalc bounds_calc, const int xy[2]) + eBlockBoundsCalc bounds_calc, const int xy[2], int r_xy[2]) { int width, height, oldwidth, oldheight; - int oldbounds, xmax, ymax; + int oldbounds, xmax, ymax, raw_x, raw_y; const int margin = UI_SCREEN_MARGIN; rcti rect, rect_bounds; int ofs_dummy[2]; @@ -407,8 +407,8 @@ static void ui_block_bounds_calc_popup( /* offset block based on mouse position, user offset is scaled * along in case we resized the block in ui_block_bounds_calc_text */ - rect.xmin = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth; - rect.ymin = xy[1] + block->rect.ymin + (block->my * height) / oldheight; + raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth; + raw_y = rect.ymin = xy[1] + block->rect.ymin + (block->my * height) / oldheight; rect.xmax = rect.xmin + width; rect.ymax = rect.ymin + height; @@ -422,6 +422,13 @@ static void ui_block_bounds_calc_popup( /* now recompute bounds and safety */ ui_block_bounds_calc(block); + + /* If given, adjust input coordinates such that they would generate real final popup position. + * Needed to handle correctly floating panels once they have been dragged around, see T52999. */ + if (r_xy) { + r_xy[0] = xy[0] + block->rect.xmin - raw_x; + r_xy[1] = xy[1] + block->rect.ymin - raw_y; + } } /* used for various cases */ @@ -488,6 +495,9 @@ static int ui_but_calc_float_precision(uiBut *but, double value) else if (prec == -1) { prec = (but->hardmax < 10.001f) ? 3 : 2; } + else { + CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX); + } return UI_calc_float_precision(prec, value); } @@ -684,7 +694,7 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBu if (oldbut->active) { /* flags from the buttons we want to refresh, may want to add more here... */ - const int flag_copy = UI_BUT_REDALERT; + const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON; found_active = true; @@ -973,7 +983,9 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str } } -static bool ui_but_event_operator_string(const bContext *C, uiBut *but, char *buf, const size_t buf_len) +static bool ui_but_event_operator_string( + const bContext *C, uiBut *but, + char *buf, const size_t buf_len) { MenuType *mt; bool found = false; @@ -981,7 +993,10 @@ static bool ui_but_event_operator_string(const bContext *C, uiBut *but, char *bu if (but->optype) { IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - if (WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, true, buf_len, buf)) { + if (WM_key_event_operator_string( + C, but->optype->idname, but->opcontext, prop, true, + buf, buf_len)) + { found = true; } } @@ -996,8 +1011,9 @@ static bool ui_but_event_operator_string(const bContext *C, uiBut *but, char *bu IDP_AssignString(prop_menu_name, mt->idname, sizeof(mt->idname)); - if (WM_key_event_operator_string(C, "WM_OT_call_menu", WM_OP_INVOKE_REGION_WIN, prop_menu, - true, buf_len, buf)) + if (WM_key_event_operator_string( + C, "WM_OT_call_menu", WM_OP_INVOKE_REGION_WIN, prop_menu, true, + buf, buf_len)) { found = true; } @@ -1009,8 +1025,10 @@ static bool ui_but_event_operator_string(const bContext *C, uiBut *but, char *bu return found; } -static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but, char *buf, const size_t buf_len) -{ +static bool ui_but_event_property_operator_string( + const bContext *C, uiBut *but, + char *buf, const size_t buf_len) +{ /* context toggle operator names to check... */ const char *ctx_toggle_opnames[] = { "WM_OT_context_toggle", @@ -1104,8 +1122,9 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but, /* check each until one works... */ for (i = 0; (i < num_ops) && (ctx_toggle_opnames[i]); i++) { - if (WM_key_event_operator_string(C, ctx_toggle_opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, - buf_len, buf)) + if (WM_key_event_operator_string( + C, ctx_toggle_opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, + buf, buf_len)) { found = true; break; @@ -1165,6 +1184,8 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block) uiBut *but; char buf[128]; + BLI_assert(block->flag & UI_BLOCK_LOOP); + /* only do it before bounding */ if (block->rect.xmin != block->rect.xmax) return; @@ -1179,6 +1200,9 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block) } else { for (but = block->buttons.first; but; but = but->next) { + if (but->dt != UI_EMBOSS_PULLDOWN) { + continue; + } if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) { ui_but_add_shortcut(but, buf, false); @@ -1223,7 +1247,7 @@ void UI_block_update_from_old(const bContext *C, uiBlock *block) block->oldblock = NULL; } -void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2]) +void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_xy[2]) { wmWindow *window = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); @@ -1291,7 +1315,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2]) /* fallback */ case UI_BLOCK_BOUNDS_POPUP_MOUSE: case UI_BLOCK_BOUNDS_POPUP_MENU: - ui_block_bounds_calc_popup(window, block, block->bounds_type, xy); + ui_block_bounds_calc_popup(window, block, block->bounds_type, xy, r_xy); break; } @@ -1309,7 +1333,7 @@ void UI_block_end(const bContext *C, uiBlock *block) { wmWindow *window = CTX_wm_window(C); - UI_block_end_ex(C, block, &window->eventstate->x); + UI_block_end_ex(C, block, &window->eventstate->x, NULL); } /* ************** BLOCK DRAWING FUNCTION ************* */ @@ -1337,7 +1361,7 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u rctf rectf; ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect); - BLI_rcti_rctf_copy_floor(rect, &rectf); + BLI_rcti_rctf_copy_round(rect, &rectf); BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin); } @@ -1932,13 +1956,14 @@ void ui_but_value_set(uiBut *but, double value) else { /* first do rounding */ if (but->pointype == UI_BUT_POIN_CHAR) { - value = (char)floor(value + 0.5); + value = round_db_to_uchar_clamp(value); } else if (but->pointype == UI_BUT_POIN_SHORT) { - value = (short)floor(value + 0.5); + value = round_db_to_short_clamp(value); + } + else if (but->pointype == UI_BUT_POIN_INT) { + value = round_db_to_int_clamp(value); } - else if (but->pointype == UI_BUT_POIN_INT) - value = (int)floor(value + 0.5); else if (but->pointype == UI_BUT_POIN_FLOAT) { float fval = (float)value; if (fval >= -0.00001f && fval <= 0.00001f) fval = 0.0f; /* prevent negative zero */ @@ -2146,9 +2171,14 @@ static float ui_get_but_step_unit(uiBut *but, float step_default) /** * \param float_precision For number buttons the precision to use or -1 to fallback to the button default. + * \param use_exp_float Use exponent representation of floats when out of reasonable range (outside of 1e3/1e-3). */ -void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) +void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision, const bool use_exp_float, bool *r_use_exp_float) { + if (r_use_exp_float) { + *r_use_exp_float = false; + } + if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { PropertyType type; const char *buf = NULL; @@ -2216,17 +2246,38 @@ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int ui_get_but_string_unit(but, str, maxlen, value, false, float_precision); } else { - const int prec = (float_precision == -1) ? ui_but_calc_float_precision(but, value) : float_precision; - BLI_snprintf(str, maxlen, "%.*f", prec, value); + int prec = (float_precision == -1) ? ui_but_calc_float_precision(but, value) : float_precision; + if (use_exp_float) { + const int int_digits_num = integer_digits_f(value); + if (int_digits_num < -6 || int_digits_num > 12) { + BLI_snprintf(str, maxlen, "%.*g", prec, value); + if (r_use_exp_float) { + *r_use_exp_float = true; + } + } + else { + prec -= int_digits_num; + CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX); + BLI_snprintf(str, maxlen, "%.*f", prec, value); + } + } + else { +#if 0 /* TODO, but will likely break some stuff, so better after 2.79 release. */ + prec -= int_digits_num; + CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX); +#endif + BLI_snprintf(str, maxlen, "%.*f", prec, value); + } } } - else + else { BLI_snprintf(str, maxlen, "%d", (int)value); + } } } void ui_but_string_get(uiBut *but, char *str, const size_t maxlen) { - ui_but_string_get_ex(but, str, maxlen, -1); + ui_but_string_get_ex(but, str, maxlen, -1, false, NULL); } /** @@ -2288,7 +2339,7 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size) #ifdef WITH_PYTHON -static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value) +static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *r_value) { char str_unit_convert[256]; const int unit_type = UI_but_unit_type_get(but); @@ -2300,13 +2351,13 @@ static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), but->drawstr, ui_get_but_scale_unit(but, 1.0), but->block->unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type)); - return BPY_execute_string_as_number(C, str_unit_convert, value, true); + return BPY_execute_string_as_number(C, str_unit_convert, true, r_value); } #endif /* WITH_PYTHON */ -bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *value) +bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *r_value) { bool ok = false; @@ -2315,13 +2366,13 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double if (str[0] != '\0') { bool is_unit_but = (ui_but_is_float(but) && ui_but_is_unit(but)); /* only enable verbose if we won't run again with units */ - if (BPY_execute_string_as_number(C, str, value, is_unit_but == false)) { + if (BPY_execute_string_as_number(C, str, is_unit_but == false, r_value)) { /* if the value parsed ok without unit conversion this button may still need a unit multiplier */ if (is_unit_but) { char str_new[128]; - BLI_snprintf(str_new, sizeof(str_new), "%f", *value); - ok = ui_set_but_string_eval_num_unit(C, but, str_new, value); + BLI_snprintf(str_new, sizeof(str_new), "%f", *r_value); + ok = ui_set_but_string_eval_num_unit(C, but, str_new, r_value); } else { ok = true; /* parse normal string via py (no unit conversion needed) */ @@ -2329,17 +2380,16 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double } else if (is_unit_but) { /* parse failed, this is a unit but so run replacements and parse again */ - ok = ui_set_but_string_eval_num_unit(C, but, str, value); + ok = ui_set_but_string_eval_num_unit(C, but, str, r_value); } } #else /* WITH_PYTHON */ - *value = atof(str); + *r_value = atof(str); ok = true; - (void)C; - (void)but; + UNUSED_VARS(C, but); #endif /* WITH_PYTHON */ @@ -2449,7 +2499,9 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) return false; } - if (!ui_but_is_float(but)) value = (int)floor(value + 0.5); + if (!ui_but_is_float(but)) { + value = floor(value + 0.5); + } /* not that we use hard limits here */ if (value < (double)but->hardmin) value = but->hardmin; @@ -2629,6 +2681,10 @@ static void ui_but_free(const bContext *C, uiBut *but) MEM_freeN(but->tip_argN); } + if (but->hold_argN) { + MEM_freeN(but->hold_argN); + } + if (but->active) { /* XXX solve later, buttons should be free-able without context ideally, * however they may have open tooltips or popup windows, which need to @@ -3168,7 +3224,9 @@ static uiBut *ui_def_but( } if (block->flag & UI_BLOCK_RADIAL) { - but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT); + but->drawflag |= UI_BUT_TEXT_LEFT; + if (but->str && but->str[0]) + but->drawflag |= UI_BUT_ICON_LEFT; } else if ((block->flag & UI_BLOCK_LOOP) || ELEM(but->type, @@ -3245,7 +3303,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu uiBut *but = (uiBut *)but_p; /* see comment in ui_item_enum_expand, re: uiname */ - EnumPropertyItem *item, *item_array; + const EnumPropertyItem *item, *item_array; bool free; uiLayout *split, *column = NULL; @@ -3355,9 +3413,8 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu UI_block_layout_set_current(block, layout); if (free) { - MEM_freeN(item_array); + MEM_freeN((void *)item_array); } - BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0); block->flag |= UI_BLOCK_IS_FLIP; } @@ -3388,7 +3445,7 @@ static uiBut *ui_def_but_rna( /* use rna values if parameters are not specified */ if ((proptype == PROP_ENUM) && ELEM(type, UI_BTYPE_MENU, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { /* UI_BTYPE_MENU is handled a little differently here */ - EnumPropertyItem *item; + const EnumPropertyItem *item; int value; bool free; int i; @@ -3430,7 +3487,7 @@ static uiBut *ui_def_but_rna( } if (free) { - MEM_freeN(item); + MEM_freeN((void *)item); } } else { @@ -3913,6 +3970,8 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int o uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip) { wmOperatorType *ot = WM_operatortype_find(opname, 0); + if (str && str[0] == '\0') + return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip); return uiDefIconTextButO_ptr(block, type, ot, opcontext, icon, str, x, y, width, height, tip); } @@ -4390,7 +4449,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c } else { PointerRNA *ptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */ - EnumPropertyItem *item, *item_array; + const EnumPropertyItem *item, *item_array; bool do_free; RNA_property_enum_items_gettexted((bContext *)C, ptr, prop, &item_array, NULL, &do_free); @@ -4403,8 +4462,9 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c } } - if (do_free) - MEM_freeN(item_array); + if (do_free) { + MEM_freeN((void *)item_array); + } } } @@ -4473,12 +4533,18 @@ void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but) wm_event_add(win, &event); } +void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN) +{ + but->hold_func = func; + but->hold_argN = argN; +} + void UI_but_string_info_get(bContext *C, uiBut *but, ...) { va_list args; uiStringInfo *si; - EnumPropertyItem *items = NULL, *item = NULL; + const EnumPropertyItem *items = NULL, *item = NULL; int totitems; bool free_items = false; @@ -4654,8 +4720,9 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) } va_end(args); - if (free_items && items) - MEM_freeN(items); + if (free_items && items) { + MEM_freeN((void *)items); + } } /* Program Init/Exit */ |