diff options
Diffstat (limited to 'source/blender/editors/interface')
12 files changed, 266 insertions, 129 deletions
diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_depth.c b/source/blender/editors/interface/eyedroppers/eyedropper_depth.c index 3fb5a74944b..c6d950112b9 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_depth.c +++ b/source/blender/editors/interface/eyedroppers/eyedropper_depth.c @@ -162,7 +162,7 @@ static void depthdropper_depth_sample_pt(bContext *C, View3D *v3d = area->spacedata.first; RegionView3D *rv3d = region->regiondata; /* weak, we could pass in some reference point */ - const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3]; + const float *view_co = v3d->camera ? v3d->camera->object_to_world[3] : rv3d->viewinv[3]; const int mval[2] = {m_xy[0] - region->winrct.xmin, m_xy[1] - region->winrct.ymin}; copy_v2_v2_int(ddr->name_pos, mval); diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 1f88d25af2b..331d1581db5 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -3474,6 +3474,7 @@ void UI_block_free(const bContext *C, uiBlock *block) BLI_freelistN(&block->saferct); BLI_freelistN(&block->color_pickers.list); + BLI_freelistN(&block->dynamic_listeners); ui_block_free_button_groups(block); ui_block_free_views(block); @@ -3481,6 +3482,20 @@ void UI_block_free(const bContext *C, uiBlock *block) MEM_freeN(block); } +void UI_block_listen(const uiBlock *block, const wmRegionListenerParams *listener_params) +{ + /* Don't need to let invisible blocks (old blocks from previous redraw) listen. */ + if (!block->active) { + return; + } + + LISTBASE_FOREACH (uiBlockDynamicListener *, listener, &block->dynamic_listeners) { + listener->listener_func(listener_params); + } + + ui_block_views_listen(block, listener_params); +} + void UI_blocklist_update_window_matrix(const bContext *C, const ListBase *lb) { ARegion *region = CTX_wm_region(C); diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc index 91b2f9613de..74a07d6edc8 100644 --- a/source/blender/editors/interface/interface_context_path.cc +++ b/source/blender/editors/interface/interface_context_path.cc @@ -45,7 +45,7 @@ void context_path_add_generic(Vector<ContextPathItem> &path, if (&rna_type == &RNA_NodeTree) { ID *id = (ID *)ptr; - path.append({name, int(icon), id->us}); + path.append({name, int(icon), ID_REAL_USERS(id)}); } else { path.append({name, int(icon), 1}); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 34f33b71fb8..ac16d41dabe 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3519,7 +3519,7 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data) static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data) { - /* label and roundbox can overlap real buttons (backdrops...) */ + /* Label and round-box can overlap real buttons (backdrops...). */ if (ELEM(actbut->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, @@ -3551,7 +3551,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data) { - /* label and roundbox can overlap real buttons (backdrops...) */ + /* Label and round-box can overlap real buttons (backdrops...). */ if (ELEM(actbut->type, UI_BTYPE_LABEL, UI_BTYPE_SEPR, @@ -3894,7 +3894,7 @@ static void ui_do_but_textedit( } if (event->type == WM_IME_COMPOSITE_EVENT && ime_data->result_len) { if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) && - strcmp(ime_data->str_result, "\xE3\x80\x82") == 0) { + STREQ(ime_data->str_result, "\xE3\x80\x82")) { /* Convert Ideographic Full Stop (U+3002) to decimal point when entering numbers. */ ui_textedit_insert_ascii(but, data, '.'); } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 9a4f98ebcd6..a5e2cd02f3b 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1309,8 +1309,8 @@ static void ui_id_preview_image_render_size( const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job); static void ui_studiolight_icon_job_exec(void *customdata, - short *UNUSED(stop), - short *UNUSED(do_update), + bool *UNUSED(stop), + bool *UNUSED(do_update), float *UNUSED(progress)) { Icon **tmp = (Icon **)customdata; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6ef81ad897e..982ac1753e1 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -477,6 +477,12 @@ typedef enum uiButtonGroupFlag { } uiButtonGroupFlag; ENUM_OPERATORS(uiButtonGroupFlag, UI_BUTTON_GROUP_PANEL_HEADER); +typedef struct uiBlockDynamicListener { + struct uiBlockDynamicListener *next, *prev; + + void (*listener_func)(const struct wmRegionListenerParams *params); +} uiBlockDynamicListener; + struct uiBlock { uiBlock *next, *prev; @@ -499,6 +505,8 @@ struct uiBlock { * state that is persistent over redraws (e.g. collapsed tree-view items). */ ListBase views; + ListBase dynamic_listeners; /* #uiBlockDynamicListener */ + char name[UI_MAX_NAME_STR]; float winmat[4][4]; @@ -1540,6 +1548,8 @@ void ui_interface_tag_script_reload_queries(void); /* interface_view.cc */ void ui_block_free_views(struct uiBlock *block); +void ui_block_views_listen(const uiBlock *block, + const struct wmRegionListenerParams *listener_params); uiViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_block, const uiViewHandle *new_view); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 496f72c089a..a456cef7be6 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5814,6 +5814,14 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout) printf("%s: opening menu \"%s\"\n", __func__, mt->idname); } + if (mt->listener) { + /* Forward the menu type listener to the block we're drawing in. */ + uiBlock *block = uiLayoutGetBlock(layout); + uiBlockDynamicListener *listener = MEM_mallocN(sizeof(*listener), "uiBlockDynamicListener"); + listener->listener_func = mt->listener; + BLI_addtail(&block->dynamic_listeners, listener); + } + if (layout->context) { CTX_store_set(C, layout->context); } diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc index e089642963d..2d06dd2c465 100644 --- a/source/blender/editors/interface/interface_ops.cc +++ b/source/blender/editors/interface/interface_ops.cc @@ -1859,8 +1859,7 @@ static void edittranslation_find_po_file(const char *root, /* First, full lang code. */ BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng); - BLI_path_join(path, maxlen, root, uilng); - BLI_path_append(path, maxlen, tstr); + BLI_path_join(path, maxlen, root, uilng, tstr); if (BLI_is_file(path)) { return; } diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc index 24d8281aad8..05b6ecf29d5 100644 --- a/source/blender/editors/interface/interface_panel.cc +++ b/source/blender/editors/interface/interface_panel.cc @@ -2026,7 +2026,7 @@ static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was ui_panel_drag_collapse_handler, ui_panel_drag_collapse_handler_remove, dragcol_data, - 0); + eWM_EventHandlerFlag(0)); } /** @@ -2510,8 +2510,12 @@ static void panel_handle_data_ensure(const bContext *C, { if (panel->activedata == nullptr) { panel->activedata = MEM_callocN(sizeof(uiHandlePanelData), __func__); - WM_event_add_ui_handler( - C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, panel, 0); + WM_event_add_ui_handler(C, + &win->modalhandlers, + ui_handler_panel, + ui_handler_remove_panel, + panel, + eWM_EventHandlerFlag(0)); } uiHandlePanelData *data = static_cast<uiHandlePanelData *>(panel->activedata); diff --git a/source/blender/editors/interface/interface_region_menu_popup.cc b/source/blender/editors/interface/interface_region_menu_popup.cc index 569f657a544..8fd6731d2ec 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.cc +++ b/source/blender/editors/interface/interface_region_menu_popup.cc @@ -10,6 +10,7 @@ #include <cstdarg> #include <cstdlib> #include <cstring> +#include <functional> #include "MEM_guardedalloc.h" @@ -166,28 +167,80 @@ struct uiPopupMenu { uiBut *but; ARegion *butregion; + /* Menu hash is created from this, to keep a memory of recently opened menus. */ + const char *title; + int mx, my; bool popup, slideout; - uiMenuCreateFunc menu_func; - void *menu_arg; + std::function<void(bContext *C, uiLayout *layout)> menu_func; }; +/** + * \param title: Optional. If set, it will be used to store recently opened menus so they can be + * opened with the mouse over the last chosen entry again. + */ +static void ui_popup_menu_create_block(bContext *C, + uiPopupMenu *pup, + const char *title, + const char *block_name) +{ + const uiStyle *style = UI_style_get_dpi(); + + pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN); + if (!pup->but) { + pup->block->flag |= UI_BLOCK_NO_FLIP; + } + if (title && title[0]) { + pup->block->flag |= UI_BLOCK_POPUP_MEMORY; + pup->block->puphash = ui_popup_menu_hash(title); + } + pup->layout = UI_block_layout( + pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + + /* NOTE: this intentionally differs from the menu & sub-menu default because many operators + * use popups like this to select one of their options - + * where having invoke doesn't make sense. + * When the menu was opened from a button, use invoke still for compatibility. This used to be + * the default and changing now could cause issues. */ + const wmOperatorCallContext opcontext = pup->but ? WM_OP_INVOKE_REGION_WIN : + WM_OP_EXEC_REGION_WIN; + + uiLayoutSetOperatorContext(pup->layout, opcontext); + + if (pup->but) { + if (pup->but->context) { + uiLayoutContextCopy(pup->layout, pup->but->context); + } + } +} + static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup) { uiPopupMenu *pup = static_cast<uiPopupMenu *>(arg_pup); - if (pup->menu_func) { - pup->block->handle = handle; - pup->menu_func(C, pup->layout, pup->menu_arg); - pup->block->handle = nullptr; + int minwidth = 0; + + if (!pup->layout) { + ui_popup_menu_create_block(C, pup, pup->title, __func__); + + if (pup->menu_func) { + pup->block->handle = handle; + pup->menu_func(C, pup->layout); + pup->block->handle = nullptr; + } + + if (uiLayoutGetUnitsX(pup->layout) != 0.0f) { + /* Use the minimum width from the layout if it's set. */ + minwidth = uiLayoutGetUnitsX(pup->layout) * UI_UNIT_X; + } + + pup->layout = nullptr; } /* Find block minimum width. */ - int minwidth; - if (uiLayoutGetUnitsX(pup->layout) != 0.0f) { - /* Use the minimum width from the layout if it's set. */ - minwidth = uiLayoutGetUnitsX(pup->layout) * UI_UNIT_X; + if (minwidth) { + /* Skip. */ } else if (pup->but) { /* Minimum width to enforce. */ @@ -233,47 +286,53 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi int width, height; UI_block_layout_resolve(block, &width, &height); - UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); + UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_NUMSELECT); if (pup->popup) { - int offset[2]; + int offset[2] = {0, 0}; uiBut *but_activate = nullptr; - UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT); + UI_block_flag_enable(block, UI_BLOCK_LOOP); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); UI_block_direction_set(block, direction); /* offset the mouse position, possibly based on earlier selection */ - uiBut *bt; - if ((block->flag & UI_BLOCK_POPUP_MEMORY) && (bt = ui_popup_menu_memory_get(block))) { - /* position mouse on last clicked item, at 0.8*width of the - * button, so it doesn't overlap the text too much, also note - * the offset is negative because we are inverse moving the - * block to be under the mouse */ - offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)); - offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y); - - if (ui_but_is_editable(bt)) { - but_activate = bt; - } - } - else { - /* position mouse at 0.8*width of the button and below the tile - * on the first item */ - offset[0] = 0; - LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { - offset[0] = min_ii(offset[0], - -(but_iter->rect.xmin + 0.8f * BLI_rctf_size_x(&but_iter->rect))); + if (!handle->refresh) { + uiBut *bt; + if ((block->flag & UI_BLOCK_POPUP_MEMORY) && (bt = ui_popup_menu_memory_get(block))) { + /* position mouse on last clicked item, at 0.8*width of the + * button, so it doesn't overlap the text too much, also note + * the offset is negative because we are inverse moving the + * block to be under the mouse */ + offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)); + offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y); + + if (ui_but_is_editable(bt)) { + but_activate = bt; + } } + else { + /* position mouse at 0.8*width of the button and below the tile + * on the first item */ + offset[0] = 0; + LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { + offset[0] = min_ii(offset[0], + -(but_iter->rect.xmin + 0.8f * BLI_rctf_size_x(&but_iter->rect))); + } - offset[1] = 2.1 * UI_UNIT_Y; + offset[1] = 2.1 * UI_UNIT_Y; - LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { - if (ui_but_is_editable(but_iter)) { - but_activate = but_iter; - break; + LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) { + if (ui_but_is_editable(but_iter)) { + but_activate = but_iter; + break; + } } } + copy_v2_v2_int(handle->prev_bounds_offset, offset); + } + else { + copy_v2_v2_int(offset, handle->prev_bounds_offset); } /* in rare cases this is needed since moving the popup @@ -312,27 +371,35 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi return pup->block; } -uiPopupBlockHandle *ui_popup_menu_create( - bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg) +static void ui_block_free_func_POPUP(void *arg_pup) +{ + uiPopupMenu *pup = static_cast<uiPopupMenu *>(arg_pup); + MEM_delete(pup); +} + +static uiPopupBlockHandle *ui_popup_menu_create( + bContext *C, + ARegion *butregion, + uiBut *but, + const char *title, + std::function<void(bContext *, uiLayout *)> menu_func) { wmWindow *window = CTX_wm_window(C); - const uiStyle *style = UI_style_get_dpi(); - uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__); - pup->block = UI_block_begin(C, nullptr, __func__, UI_EMBOSS_PULLDOWN); - pup->block->flag |= UI_BLOCK_NUMSELECT; /* Default menus to numeric-selection. */ - pup->layout = UI_block_layout( - pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - pup->slideout = but ? ui_block_is_menu(but->block) : false; - pup->but = but; - uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN); + uiPopupMenu *pup = MEM_new<uiPopupMenu>(__func__); + pup->title = title; + /* menu is created from a callback */ + pup->menu_func = menu_func; + if (but) { + pup->slideout = ui_block_is_menu(but->block); + pup->but = but; + } if (!but) { /* no button to start from, means we are a popup */ pup->mx = window->eventstate->xy[0]; pup->my = window->eventstate->xy[1]; pup->popup = true; - pup->block->flag |= UI_BLOCK_NO_FLIP; } /* some enums reversing is strange, currently we have no good way to * reverse some enum's but not others, so reverse all so the first menu @@ -346,17 +413,10 @@ uiPopupBlockHandle *ui_popup_menu_create( pup->block->flag |= UI_BLOCK_NO_FLIP; } #endif - if (but->context) { - uiLayoutContextCopy(pup->layout, but->context); - } } - /* menu is created from a callback */ - pup->menu_func = menu_func; - pup->menu_arg = arg; - uiPopupBlockHandle *handle = ui_popup_block_create( - C, butregion, but, nullptr, ui_block_func_POPUP, pup, nullptr); + C, butregion, but, nullptr, ui_block_func_POPUP, pup, ui_block_free_func_POPUP); if (!but) { handle->popup = true; @@ -365,68 +425,75 @@ uiPopupBlockHandle *ui_popup_menu_create( WM_event_add_mousemove(window); } - MEM_freeN(pup); - return handle; } +uiPopupBlockHandle *ui_popup_menu_create( + bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg) +{ + return ui_popup_menu_create( + C, butregion, but, nullptr, [menu_func, arg](bContext *C, uiLayout *layout) { + menu_func(C, layout, arg); + }); +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name Popup Menu API with begin & end * \{ */ +static void create_title_button(uiLayout *layout, const char *title, int icon) +{ + uiBlock *block = uiLayoutGetBlock(layout); + char titlestr[256]; + + if (icon) { + BLI_snprintf(titlestr, sizeof(titlestr), " %s", title); + uiDefIconTextBut(block, + UI_BTYPE_LABEL, + 0, + icon, + titlestr, + 0, + 0, + 200, + UI_UNIT_Y, + nullptr, + 0.0, + 0.0, + 0, + 0, + ""); + } + else { + uiBut *but = uiDefBut( + block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, nullptr, 0.0, 0.0, 0, 0, ""); + but->drawflag = UI_BUT_TEXT_LEFT; + } + + uiItemS(layout); +} + +/* Used to directly create a popup menu that is not refreshed on redraw. */ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C, const char *title, const char *block_name, int icon) { - const uiStyle *style = UI_style_get_dpi(); - uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__); + uiPopupMenu *pup = MEM_new<uiPopupMenu>(__func__); - pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN); - pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP; - pup->block->puphash = ui_popup_menu_hash(title); - pup->layout = UI_block_layout( - pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + pup->title = title; - /* NOTE: this intentionally differs from the menu & sub-menu default because many operators - * use popups like this to select one of their options - - * where having invoke doesn't make sense */ - uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN); + ui_popup_menu_create_block(C, pup, title, block_name); + /* Further buttons will be laid out top to bottom by default. */ + pup->block->flag |= UI_BLOCK_IS_FLIP; /* create in advance so we can let buttons point to retval already */ pup->block->handle = MEM_cnew<uiPopupBlockHandle>(__func__); - /* create title button */ if (title[0]) { - char titlestr[256]; - - if (icon) { - BLI_snprintf(titlestr, sizeof(titlestr), " %s", title); - uiDefIconTextBut(pup->block, - UI_BTYPE_LABEL, - 0, - icon, - titlestr, - 0, - 0, - 200, - UI_UNIT_Y, - nullptr, - 0.0, - 0.0, - 0, - 0, - ""); - } - else { - uiBut *but = uiDefBut( - pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, nullptr, 0.0, 0.0, 0, 0, ""); - but->drawflag = UI_BUT_TEXT_LEFT; - } - - uiItemS(pup->layout); + create_title_button(pup->layout, title, icon); } return pup; @@ -465,7 +532,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup) UI_popup_handlers_add(C, &window->modalhandlers, menu, 0); WM_event_add_mousemove(window); - MEM_freeN(pup); + MEM_delete(pup); } bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup) @@ -477,7 +544,7 @@ bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup) UI_block_layout_resolve(pup->block, nullptr, nullptr); MEM_freeN(pup->block->handle); UI_block_free(C, pup->block); - MEM_freeN(pup); + MEM_delete(pup); return false; } @@ -541,6 +608,22 @@ void UI_popup_menu_reports(bContext *C, ReportList *reports) } } +static void ui_popup_menu_create_from_menutype(bContext *C, + MenuType *mt, + const char *title, + const int icon) +{ + uiPopupBlockHandle *handle = ui_popup_menu_create( + C, nullptr, nullptr, title, [mt, title, icon](bContext *C, uiLayout *layout) -> void { + if (title && title[0]) { + create_title_button(layout, title, icon); + } + ui_item_menutype_func(C, layout, mt); + }); + + handle->can_refresh = true; +} + int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) { MenuType *mt = WM_menutype_find(idname, true); @@ -554,14 +637,21 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) /* cancel but allow event to pass through, just like operators do */ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } + /* For now always recreate menus on redraw that were invoked with this function. Maybe we want to + * make that optional somehow. */ + const bool allow_refresh = true; - uiPopupMenu *pup = UI_popup_menu_begin( - C, CTX_IFACE_(mt->translation_context, mt->label), ICON_NONE); - uiLayout *layout = UI_popup_menu_layout(pup); - - UI_menutype_draw(C, mt, layout); - - UI_popup_menu_end(C, pup); + const char *title = CTX_IFACE_(mt->translation_context, mt->label); + if (allow_refresh) { + ui_popup_menu_create_from_menutype(C, mt, title, ICON_NONE); + } + else { + /* If no refresh is needed, create the block directly. */ + uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_NONE); + uiLayout *layout = UI_popup_menu_layout(pup); + UI_menutype_draw(C, mt, layout); + UI_popup_menu_end(C, pup); + } return OPERATOR_INTERFACE; } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a3259831c9f..b32aa82ad9e 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -3673,13 +3673,9 @@ static void colorband_buttons_layout(uiLayout *layout, row = uiLayoutRow(split, false); uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE); - bt = block->buttons.last; - UI_but_func_set(bt, colorband_update_cb, bt, coba); row = uiLayoutRow(layout, false); uiItemR(row, &ptr, "color", 0, "", ICON_NONE); - bt = block->buttons.last; - UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL); } else { split = uiLayoutSplit(layout, 0.5f, false); @@ -3704,13 +3700,28 @@ static void colorband_buttons_layout(uiLayout *layout, row = uiLayoutRow(subsplit, false); uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE); - bt = block->buttons.last; - UI_but_func_set(bt, colorband_update_cb, bt, coba); row = uiLayoutRow(split, false); uiItemR(row, &ptr, "color", 0, "", ICON_NONE); - bt = block->buttons.last; - UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + } + + /* Some special (rather awkward) treatment to update UI state on certain property changes. */ + LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block->buttons) { + if (but->rnapoin.data != ptr.data) { + continue; + } + if (!but->rnaprop) { + continue; + } + + const char *prop_identifier = RNA_property_identifier(but->rnaprop); + if (STREQ(prop_identifier, "position")) { + UI_but_func_set(but, colorband_update_cb, but, coba); + } + + if (STREQ(prop_identifier, "color")) { + UI_but_funcN_set(but, rna_update_cb, MEM_dupallocN(cb), NULL); + } } } } diff --git a/source/blender/editors/interface/views/interface_view.cc b/source/blender/editors/interface/views/interface_view.cc index c568a8cab74..71974b4d2f9 100644 --- a/source/blender/editors/interface/views/interface_view.cc +++ b/source/blender/editors/interface/views/interface_view.cc @@ -81,7 +81,7 @@ void ui_block_free_views(uiBlock *block) } } -void UI_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params) +void ui_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params) { ARegion *region = listener_params->region; |