[Bf-blender-cvs] [1eb90ee519c] master: UI: Use vector instead of linked list for block button groups

Hans Goudey noreply at git.blender.org
Mon Dec 19 06:24:20 CET 2022


Commit: 1eb90ee519c4537be6ecd86b41cb5e7aa092581a
Author: Hans Goudey
Date:   Sun Dec 18 21:45:32 2022 -0600
Branches: master
https://developer.blender.org/rB1eb90ee519c4537be6ecd86b41cb5e7aa092581a

UI: Use vector instead of linked list for block button groups

This simplifies some memory management, ammortizes some of the many
small allocations when building UI layouts, and simplifies the code
that deals with the groups. `uiBlock` is no longer a trivial type.
In my testing this saved a few ms when drawing a large node tree.

===================================================================

M	source/blender/editors/interface/interface.cc
M	source/blender/editors/interface/interface_button_group.cc
M	source/blender/editors/interface/interface_intern.hh
M	source/blender/editors/interface/interface_layout.cc
M	source/blender/editors/interface/interface_panel.cc
M	source/blender/editors/interface/interface_template_search_menu.cc

===================================================================

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<uiBlock>(__func__);
+  uiBlock *block = MEM_new<uiBlock>(__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<const uiBut *>(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<uiButtonGroup *>(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<uiButtonGroup>(__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<uiButtonGroup *>(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(&current_button_group->buttons, button_link);
+  uiButtonGroup &current_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<uiBut *> 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<uiButtonGroup> 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<uiBut *>(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<uiBut *>(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<uiButtonGroup *>(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

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list