diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index c16c3068320..6728b1e3a41 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -3478,10 +3478,9 @@ void UI_block_free(const bContext *C, uiBlock *block) BLI_freelistN(&block->color_pickers.list); BLI_freelistN(&block->dynamic_listeners); - ui_block_free_button_groups(block); ui_block_free_views(block); - MEM_freeN(block); + MEM_delete(block); } void UI_block_listen(const uiBlock *block, const wmRegionListenerParams *listener_params) @@ -3597,13 +3596,11 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, eU wmWindow *window = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); - uiBlock *block = MEM_cnew(__func__); + uiBlock *block = MEM_new(__func__); block->active = true; block->emboss = emboss; block->evil_C = (void *)C; /* XXX */ - BLI_listbase_clear(&block->button_groups); - if (scene) { /* store display device name, don't lookup for transformations yet * block could be used for non-color displays where looking up for transformation @@ -4058,7 +4055,7 @@ uiBut *ui_but_change_type(uiBut *but, eButType new_type) ui_but_alloc_info(new_type, &alloc_size, &alloc_str, &new_has_custom_type); if (new_has_custom_type || old_has_custom_type) { - const void *old_but_ptr = but; + const uiBut *old_but_ptr = but; /* Button may have pointer to a member within itself, this will have to be updated. */ const bool has_str_ptr_to_self = but->str == but->strdata; const bool has_poin_ptr_to_self = but->poin == (char *)but; @@ -4082,7 +4079,7 @@ uiBut *ui_but_change_type(uiBut *but, eButType new_type) } #ifdef WITH_PYTHON if (UI_editsource_enable_check()) { - UI_editsource_but_replace(static_cast(old_but_ptr), but); + UI_editsource_but_replace(old_but_ptr, but); } #endif } diff --git a/source/blender/editors/interface/interface_button_group.cc b/source/blender/editors/interface/interface_button_group.cc index ed9065423e4..371cfda47df 100644 --- a/source/blender/editors/interface/interface_button_group.cc +++ b/source/blender/editors/interface/interface_button_group.cc @@ -17,54 +17,35 @@ void ui_block_new_button_group(uiBlock *block, uiButtonGroupFlag flag) { /* Don't create a new group if there is a "lock" on new groups. */ - if (!BLI_listbase_is_empty(&block->button_groups)) { - uiButtonGroup *last_button_group = static_cast(block->button_groups.last); - if (last_button_group->flag & UI_BUTTON_GROUP_LOCK) { + if (!block->button_groups.is_empty()) { + uiButtonGroup &last_group = block->button_groups.last(); + if (last_group.flag & UI_BUTTON_GROUP_LOCK) { return; } } - uiButtonGroup *new_group = MEM_cnew(__func__); - new_group->flag = flag; - BLI_addtail(&block->button_groups, new_group); + block->button_groups.append({}); + block->button_groups.last().flag = flag; } void ui_button_group_add_but(uiBlock *block, uiBut *but) { - if (BLI_listbase_is_empty(&block->button_groups)) { + if (block->button_groups.is_empty()) { ui_block_new_button_group(block, uiButtonGroupFlag(0)); } - uiButtonGroup *current_button_group = static_cast(block->button_groups.last); - - /* We can't use the button directly because adding it to - * this list would mess with its `prev` and `next` pointers. */ - LinkData *button_link = BLI_genericNodeN(but); - BLI_addtail(¤t_button_group->buttons, button_link); + uiButtonGroup ¤t_group = block->button_groups.last(); + current_group.buttons.append(but); } -static void button_group_free(uiButtonGroup *button_group) +void ui_button_group_replace_but_ptr(uiBlock *block, const uiBut *old_but_ptr, uiBut *new_but) { - BLI_freelistN(&button_group->buttons); - MEM_freeN(button_group); -} - -void ui_block_free_button_groups(uiBlock *block) -{ - LISTBASE_FOREACH_MUTABLE (uiButtonGroup *, button_group, &block->button_groups) { - button_group_free(button_group); - } -} - -void ui_button_group_replace_but_ptr(uiBlock *block, const void *old_but_ptr, uiBut *new_but) -{ - LISTBASE_FOREACH (uiButtonGroup *, button_group, &block->button_groups) { - LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) { - if (link->data == old_but_ptr) { - link->data = new_but; - return; - } - } + for (uiButtonGroup &group : block->button_groups) { + std::replace_if( + group.buttons.begin(), + group.buttons.end(), + [&](const uiBut *ptr) { return ptr == old_but_ptr; }, + new_but); } } diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index 1b846a97403..fc64500dbaa 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -9,6 +9,7 @@ #include "BLI_compiler_attrs.h" #include "BLI_rect.h" +#include "BLI_vector.hh" #include "DNA_listBase.h" #include "RNA_types.h" @@ -456,18 +457,6 @@ enum eBlockContentHints { UI_BLOCK_CONTAINS_SUBMENU_BUT = (1 << 0), }; -/** - * A group of button references, used by property search to keep track of sets of buttons that - * should be searched together. For example, in property split layouts number buttons and their - * labels (and even their decorators) are separate buttons, but they must be searched and - * highlighted together. - */ -struct uiButtonGroup { - void *next, *prev; - ListBase buttons; /* #LinkData with #uiBut data field. */ - short flag; -}; - /* #uiButtonGroup.flag. */ enum uiButtonGroupFlag { /** While this flag is set, don't create new button groups for layout item calls. */ @@ -477,6 +466,17 @@ enum uiButtonGroupFlag { }; ENUM_OPERATORS(uiButtonGroupFlag, UI_BUTTON_GROUP_PANEL_HEADER); +/** + * A group of button references, used by property search to keep track of sets of buttons that + * should be searched together. For example, in property split layouts number buttons and their + * labels (and even their decorators) are separate buttons, but they must be searched and + * highlighted together. + */ +struct uiButtonGroup { + blender::Vector buttons; + uiButtonGroupFlag flag; +}; + struct uiBlockDynamicListener { struct uiBlockDynamicListener *next, *prev; @@ -493,7 +493,7 @@ struct uiBlock { /** Used for `UI_butstore_*` runtime function. */ ListBase butstore; - ListBase button_groups; /* #uiButtonGroup. */ + blender::Vector button_groups; ListBase layouts; uiLayout *curlayout; @@ -1273,8 +1273,7 @@ void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt); */ void ui_block_new_button_group(uiBlock *block, uiButtonGroupFlag flag); void ui_button_group_add_but(uiBlock *block, uiBut *but); -void ui_button_group_replace_but_ptr(uiBlock *block, const void *old_but_ptr, uiBut *new_but); -void ui_block_free_button_groups(uiBlock *block); +void ui_button_group_replace_but_ptr(uiBlock *block, const uiBut *old_but_ptr, uiBut *new_but); /* interface_drag.cc */ diff --git a/source/blender/editors/interface/interface_layout.cc b/source/blender/editors/interface/interface_layout.cc index b0d5728c9f9..9d755ac022a 100644 --- a/source/blender/editors/interface/interface_layout.cc +++ b/source/blender/editors/interface/interface_layout.cc @@ -5227,10 +5227,9 @@ static bool button_matches_search_filter(uiBut *but, const char *search_filter) /** * Test for a search result within a specific button group. */ -static bool button_group_has_search_match(uiButtonGroup *button_group, const char *search_filter) +static bool button_group_has_search_match(const uiButtonGroup &group, const char *search_filter) { - LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) { - uiBut *but = static_cast(link->data); + for (uiBut *but : group.buttons) { if (button_matches_search_filter(but, search_filter)) { return true; } @@ -5251,13 +5250,12 @@ static bool button_group_has_search_match(uiButtonGroup *button_group, const cha static bool block_search_filter_tag_buttons(uiBlock *block, const char *search_filter) { bool has_result = false; - LISTBASE_FOREACH (uiButtonGroup *, button_group, &block->button_groups) { - if (button_group_has_search_match(button_group, search_filter)) { + for (const uiButtonGroup &group : block->button_groups) { + if (button_group_has_search_match(group, search_filter)) { has_result = true; } else { - LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) { - uiBut *but = static_cast(link->data); + for (uiBut *but : group.buttons) { but->flag |= UI_SEARCH_FILTER_NO_MATCH; } } diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc index c924d758caa..28aae7d779f 100644 --- a/source/blender/editors/interface/interface_panel.cc +++ b/source/blender/editors/interface/interface_panel.cc @@ -754,18 +754,16 @@ void UI_panel_header_buttons_end(Panel *panel) uiBlock *block = panel->runtime.block; /* A button group should always be created in #UI_panel_header_buttons_begin. */ - BLI_assert(!BLI_listbase_is_empty(&block->button_groups)); + BLI_assert(!block->button_groups.is_empty()); - uiButtonGroup *button_group = static_cast(block->button_groups.last); - - button_group->flag &= ~UI_BUTTON_GROUP_LOCK; + uiButtonGroup &button_group = block->button_groups.last(); + button_group.flag &= ~UI_BUTTON_GROUP_LOCK; /* Repurpose the first header button group if it is empty, in case the first button added to * the panel doesn't add a new group (if the button is created directly rather than through an * interface layout call). */ - if (BLI_listbase_is_single(&block->button_groups) && - BLI_listbase_is_empty(&button_group->buttons)) { - button_group->flag &= ~UI_BUTTON_GROUP_PANEL_HEADER; + if (block->button_groups.size() > 0) { + button_group.flag &= ~UI_BUTTON_GROUP_PANEL_HEADER; } else { /* Always add a new button group. Although this may result in many empty groups, without it, @@ -940,12 +938,11 @@ static void panel_remove_invisible_layouts_recursive(Panel *panel, const Panel * /* If sub-panels have no search results but the parent panel does, then the parent panel open * and the sub-panels will close. In that case there must be a way to hide the buttons in the * panel but keep the header buttons. */ - LISTBASE_FOREACH (uiButtonGroup *, button_group, &block->button_groups) { - if (button_group->flag & UI_BUTTON_GROUP_PANEL_HEADER) { + for (const uiButtonGroup &button_group : block->button_groups) { + if (button_group.flag & UI_BUTTON_GROUP_PANEL_HEADER) { continue; } - LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) { - uiBut *but = static_cast(link->data); + for (uiBut *but : button_group.buttons) { but->flag |= UI_HIDDEN; } } diff --git a/source/blender/editors/interface/interface_template_search_menu.cc b/source/blender/editors/interface/interface_template_search_menu.cc index 54213bdc5c3..e953119dfdc 100644 --- a/source/blender/editors/interface/interface_template_search_menu.cc +++ b/source/blender/editors/interface/interface_template_search_menu.cc @@ -1040,7 +1040,8 @@ static bool ui_search_menu_create_context_menu(struct bContext *C, MenuSearch_Item *item = (MenuSearch_Item *)active; bool has_menu = false; - memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data)); + new (&data->context_menu_data.but) uiBut(); + new (&data->context_menu_data.block) uiBlock(); uiBut *but = &data->context_menu_data.but; uiBlock *block = &data->context_menu_data.block; @@ -1083,7 +1084,8 @@ static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C, MenuSearch_Data *data = (MenuSearch_Data *)arg; MenuSearch_Item *item = (MenuSearch_Item *)active; - memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data)); + new (&data->context_menu_data.but) uiBut(); + new (&data->context_menu_data.block) uiBlock(); uiBut *but = &data->context_menu_data.but; uiBlock *block = &data->context_menu_data.block; unit_m4(block->winmat);