[Bf-blender-cvs] [5fc13d11122] modifier-panels-ui: Support multiple panels of the same type

Hans Goudey noreply at git.blender.org
Tue Apr 7 22:59:22 CEST 2020


Commit: 5fc13d111229eeec6a3fd331abceb3f2e2692f10
Author: Hans Goudey
Date:   Tue Apr 7 15:57:37 2020 -0500
Branches: modifier-panels-ui
https://developer.blender.org/rB5fc13d111229eeec6a3fd331abceb3f2e2692f10

Support multiple panels of the same type

The name for the uiBlock associated with a panel was just the panel type's
idname, so the old block found at the start of drawing was the same for
every panel of a certain type.

Panel blocks for list panels are now named with the list index appended
to the end of the name. The panel list is also rebuilt when reordering
panels of the same type.

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface_panel.c
M	source/blender/editors/interface/interface_templates.c
M	source/blender/editors/screen/area.c
M	source/blender/makesdna/DNA_screen_types.h

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 7744a31d518..491e9a1cdce 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1663,15 +1663,18 @@ void UI_panel_end(const struct ScrArea *area,
                   int width,
                   int height,
                   bool open);
+
 struct Panel *UI_panel_add_recreate(struct ScrArea *sa,
                                     struct ARegion *region,
                                     struct ListBase *panels,
                                     struct PanelType *panel_type,
                                     int modifier_index);
 void UI_panel_set_list_index(struct Panel *panel, int i);
-void UI_panel_delete(struct ListBase *panels, struct Panel *panel);
+void UI_panel_delete(struct ARegion *region, struct ListBase *panels, struct Panel *panel);
+void UI_panels_free_recreate(struct ARegion *region);
+#define LIST_PANEL_UNIQUE_STR_LEN 4
+void UI_list_panel_unique_str(struct Panel *panel, char *r_name);
 
-void UI_panels_free_recreate(struct ListBase *panels);
 void UI_panels_scale(struct ARegion *region, float new_width);
 void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y);
 int UI_panel_size_y(const struct Panel *panel);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index eeec0af96c0..73c4c62e186 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -481,6 +481,8 @@ static void ui_offset_panel_block(uiBlock *block)
   block->rect.xmin = block->rect.ymin = 0.0;
 }
 
+/***** Functions for recreate list panels. ***********/
+
 /**
  * Called in situations where panels need to be added dynamically rather than having only one panel
  * corresponding to each PanelType.
@@ -555,17 +557,43 @@ void UI_panel_set_list_index(Panel *panel, int i)
   }
 }
 
-void UI_panel_delete(ListBase *panels, Panel *panel)
+void UI_list_panel_unique_str(Panel *panel, char *r_name)
+{
+  snprintf(r_name, LIST_PANEL_UNIQUE_STR_LEN, "%d", panel->runtime.list_index);
+}
+
+static void panel_free_block(struct ARegion *region, struct Panel *panel)
+{
+  BLI_assert(panel->type);
+
+  char block_name[BKE_ST_MAXNAME + LIST_PANEL_UNIQUE_STR_LEN];
+  strncpy(block_name, panel->type->idname, BKE_ST_MAXNAME);
+  char unique_panel_str[LIST_PANEL_UNIQUE_STR_LEN];
+  UI_list_panel_unique_str(panel, unique_panel_str);
+  strncat(block_name, unique_panel_str, LIST_PANEL_UNIQUE_STR_LEN);
+
+  LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
+    if (STREQ(block->name, block_name)) {
+      // printf("Removing panel block %s\n", block_name);
+      BLI_remlink(&region->uiblocks, block);
+      UI_block_free(NULL, block);
+    }
+  }
+}
+
+void UI_panel_delete(ARegion *region, ListBase *panels, Panel *panel)
 {
   /* Recursively delete children. */
   Panel *child = panel->children.first;
   while (child != NULL) {
     Panel *child_next = child->next;
-    UI_panel_delete(&panel->children, child);
+    UI_panel_delete(region, &panel->children, child);
     child = child_next;
   }
   BLI_freelistN(&panel->children);
 
+  panel_free_block(region, panel);
+
   BLI_remlink(panels, panel);
   if (panel->activedata) {
     MEM_freeN(panel->activedata);
@@ -573,10 +601,10 @@ void UI_panel_delete(ListBase *panels, Panel *panel)
   MEM_freeN(panel);
 }
 
-void UI_panels_free_recreate(ListBase *panels)
+void UI_panels_free_recreate(ARegion *region)
 {
   /* Delete panels with the recreate flag. */
-  // printf("UI_PANELS_FREE_RECREATE\n");
+  ListBase *panels = &region->panels;
   Panel *panel = panels->first;
   Panel *panel_next = NULL;
   while (panel != NULL) {
@@ -589,7 +617,7 @@ void UI_panels_free_recreate(ListBase *panels)
 
     panel_next = panel->next;
     if (remove) {
-      UI_panel_delete(panels, panel);
+      UI_panel_delete(region, panels, panel);
     }
     panel = panel_next;
   }
@@ -1444,6 +1472,11 @@ static void reorder_recreate_panel_list(bContext *C, ARegion *region, Panel *pan
   if (panel->type == NULL || !(panel->type->flag & PANELTYPE_RECREATE)) {
     return;
   }
+  /* Don't reorder if this recreate panel doesn't support drag and drop reordering. */
+  if (panel->type->re_order == NULL) {
+    return;
+  }
+
   char *context = panel->type->context;
 
   /* Find how many recreate panels with this context string. */
@@ -1489,11 +1522,15 @@ static void reorder_recreate_panel_list(bContext *C, ARegion *region, Panel *pan
   }
   MEM_freeN(panel_sort);
 
-  /* Finally, move this panel's list item to the new index in its list. */
+  /* Don't reorder the panel didn't change order after being dropped. */
   if (move_to_index == panel->runtime.list_index) {
     return;
   }
-  BLI_assert(panel->type->re_order != NULL);
+
+  /* Set the bit to tell the interface to recreate the list. */
+  panel->flag |= PNL_RECREATE_ORDER_CHANGED;
+
+  /* Finally, move this panel's list item to the new index in its list. */
   panel->type->re_order(C, panel, move_to_index);
 }
 
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index c42df12b80a..786ae002dc0 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1835,7 +1835,8 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C)
   ARegion *region = CTX_wm_region(C);
   Object *ob = CTX_data_active_object(C);
 
-  /* Check if the type corresponds between each panel consecutive panel and modifier. */
+  /* Check if the current modifier list corresponds to recreate panel list, or if the panels were
+   * reordered. */
   bool modifiers_changed = false;
   int modifiers_len = BLI_listbase_count(&ob->modifiers);
   int i = 0;
@@ -1843,21 +1844,24 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C)
   Panel *panel = region->panels.first;
   while (panel != NULL) {
     if (panel->type != NULL && panel->type->flag & PANELTYPE_RECREATE) {
+      /* The panels were reordered by drag and drop. */
+      if (panel->flag & PNL_RECREATE_ORDER_CHANGED) {
+        modifiers_changed = true;
+        break;
+      }
+
+      /* We reached the last modifier before the last recreate panel. */
       if (md == NULL) {
-        /* We reached the last modifier before the last recreate panel. */
         modifiers_changed = true;
         break;
       }
+
+      /* The types of the corresponding panel and modifier don't match. */
       if (panel_type_from_modifier_type(region, md->type) != panel->type) {
-        /* The types of the corresponding panel and modifier don't match. */
         modifiers_changed = true;
         break;
       }
 
-      /* Set the list index of the panel anyway, two modifiers of the same type might have
-       * switched. */
-      UI_panel_set_list_index(panel, i);
-      panel->runtime.list_index = i;
       md = md->next;
       i++;
     }
@@ -1871,7 +1875,7 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C)
 
   /* If the modifier list has changed at all, clear all of the recreate panels and rebuild them. */
   if (modifiers_changed) {
-    UI_panels_free_recreate(&region->panels);
+    UI_panels_free_recreate(region);
     md = ob->modifiers.first;
     for (i = 0; md; i++, md = md->next) {
       const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index b12560dec28..90dd1b51f32 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2342,6 +2342,15 @@ BLI_INLINE bool streq_array_any(const char *s, const char *arr[])
   return false;
 }
 
+/**
+ * Builds the panel layout for the input \a panel or type \a pt.
+ *
+ * \param panel The panel to draw. Can be null, in which case a panel with the type of \a pt will
+ * be found.
+ * \param unique_panel_str A unique identifier for the name of the \a uiBlock associated with the
+ * panel. Used when the panel is a recreate panel so a unique identifier is needed to find the
+ * correct old \a uiBlock, and NULL otherwise.
+ */
 static void ed_panel_draw(const bContext *C,
                           ScrArea *area,
                           ARegion *region,
@@ -2350,12 +2359,20 @@ static void ed_panel_draw(const bContext *C,
                           Panel *panel,
                           int w,
                           int em,
-                          bool vertical)
+                          bool vertical,
+                          char *unique_panel_str)
 {
   const uiStyle *style = UI_style_get_dpi();
 
-  /* draw panel */
-  uiBlock *block = UI_block_begin(C, region, pt->idname, UI_EMBOSS);
+  /* Draw panel. */
+
+  char block_name[BKE_ST_MAXNAME + LIST_PANEL_UNIQUE_STR_LEN];
+  strncpy(block_name, pt->idname, BKE_ST_MAXNAME);
+  if (unique_panel_str != NULL) {
+    /* Recreate panels should have already been added at this point. */
+    strncat(block_name, unique_panel_str, LIST_PANEL_UNIQUE_STR_LEN);
+  }
+  uiBlock *block = UI_block_begin(C, region, block_name, UI_EMBOSS);
 
   bool open;
   panel = UI_panel_begin(area, region, lb, block, pt, panel, &open);
@@ -2446,7 +2463,16 @@ static void ed_panel_draw(const bContext *C,
       Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt);
 
       if (child_pt->draw && (!child_pt->poll || child_pt->poll(C, child_pt))) {
-        ed_panel_draw(C, area, region, &panel->children, child_pt, child_panel, w, em, vertical);
+        ed_panel_draw(C,
+                      area,
+                      region,
+                      &panel->children,
+                      child_pt,
+                      child_panel,
+                      w,
+                      em,
+                      vertical,
+                      unique_panel_str);
       }
     }
   }
@@ -2591,14 +2617,28 @@ void ED_region_panels_layout_ex(const bContext *C,
       }
     }
 
-    ed_panel_draw(C, area, region, &region->panels, pt, panel, w, em, vertical);
+    ed

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list