[Bf-blender-cvs] [231078441f0] master: Outliner: Refactor how lazy-building of children is done

Julian Eisel noreply at git.blender.org
Fri Aug 19 22:21:42 CEST 2022


Commit: 231078441f011c13cac8bc06bed02260ca828ce7
Author: Julian Eisel
Date:   Fri Aug 19 21:56:09 2022 +0200
Branches: master
https://developer.blender.org/rB231078441f011c13cac8bc06bed02260ca828ce7

Outliner: Refactor how lazy-building of children is done

Makes the lazy-building (where children are only built when the parent
isn't collapsed) more generic, so more display modes can use it. So far
this was hardcoded for the "Data API" display mode.

This will be used to work around a big performance issue with the
Library Overrides Hierachies view in a complex production file, see
following commit.

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

M	source/blender/editors/space_outliner/outliner_draw.cc
M	source/blender/editors/space_outliner/outliner_edit.cc
M	source/blender/editors/space_outliner/outliner_intern.hh
M	source/blender/editors/space_outliner/outliner_select.cc
M	source/blender/editors/space_outliner/outliner_tree.cc
M	source/blender/editors/space_outliner/outliner_utils.cc
M	source/blender/editors/space_outliner/tree/tree_display.cc
M	source/blender/editors/space_outliner/tree/tree_display.hh
M	source/blender/editors/space_outliner/tree/tree_display_data.cc
M	source/blender/editors/space_outliner/tree/tree_element_rna.cc

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

diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index add9a4df2e6..3201d8bc3a3 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -3336,7 +3336,7 @@ static void outliner_draw_tree_element(bContext *C,
       /* Scene collection in view layer can't expand/collapse. */
     }
     else if (te->subtree.first || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_SCE)) ||
-             (te->flag & TE_LAZY_CLOSED)) {
+             (te->flag & TE_PRETEND_HAS_CHILDREN)) {
       /* Open/close icon, only when sub-levels, except for scene. */
       int icon_x = startx;
 
diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc
index ffae81d6e3f..37008889d06 100644
--- a/source/blender/editors/space_outliner/outliner_edit.cc
+++ b/source/blender/editors/space_outliner/outliner_edit.cc
@@ -144,14 +144,10 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot)
 /** \name Toggle Open/Closed Operator
  * \{ */
 
-void outliner_item_openclose(SpaceOutliner *space_outliner,
-                             TreeElement *te,
-                             bool open,
-                             bool toggle_all)
-{
-  /* Prevent opening leaf elements in the tree unless in the Data API display mode because in that
-   * mode subtrees are empty unless expanded. */
-  if (space_outliner->outlinevis != SO_DATA_API && BLI_listbase_is_empty(&te->subtree)) {
+void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all)
+{
+  /* Only allow opening elements with children.  */
+  if (!(te->flag & TE_PRETEND_HAS_CHILDREN) && BLI_listbase_is_empty(&te->subtree)) {
     return;
   }
 
@@ -198,7 +194,7 @@ static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEv
 
       /* Only toggle openclose on the same level as the first clicked element */
       if (te->xs == data->x_location) {
-        outliner_item_openclose(space_outliner, te, data->open, false);
+        outliner_item_openclose(te, data->open, false);
 
         outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
       }
@@ -242,7 +238,7 @@ static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmE
     const bool open = (tselem->flag & TSE_CLOSED) ||
                       (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1)));
 
-    outliner_item_openclose(space_outliner, te, open, toggle_all);
+    outliner_item_openclose(te, open, toggle_all);
     outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
 
     /* Only toggle once for single click toggling */
diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh
index e89342de698..684d665ff3d 100644
--- a/source/blender/editors/space_outliner/outliner_intern.hh
+++ b/source/blender/editors/space_outliner/outliner_intern.hh
@@ -157,7 +157,10 @@ enum {
   /* Closed items display their children as icon within the row. TE_ICONROW is for
    * these child-items that are visible but only within the row of the closed parent. */
   TE_ICONROW = (1 << 1),
-  TE_LAZY_CLOSED = (1 << 2),
+  /** Treat the element as if it had children, e.g. draw an icon to un-collapse it, even if it
+   * doesn't. Used where children are lazy-built only if the parent isn't collapsed (see
+   * #AbstractTreeDisplay::is_lazy_built()). */
+  TE_PRETEND_HAS_CHILDREN = (1 << 2),
   TE_FREE_NAME = (1 << 3),
   TE_DRAGGING = (1 << 4),
   TE_CHILD_NOT_IN_COLLECTION = (1 << 6),
@@ -280,11 +283,6 @@ struct TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outli
 
 bool outliner_requires_rebuild_on_select_or_active_change(
     const struct SpaceOutliner *space_outliner);
-/**
- * Check if a display mode needs a full rebuild if the open/collapsed state changes.
- * Element types in these modes don't actually add children if collapsed, so the rebuild is needed.
- */
-bool outliner_requires_rebuild_on_open_change(const struct SpaceOutliner *space_outliner);
 
 typedef struct IDsSelectedData {
   struct ListBase selected_array;
@@ -465,10 +463,7 @@ void outliner_set_coordinates(const struct ARegion *region,
 /**
  * Open or close a tree element, optionally toggling all children recursively.
  */
-void outliner_item_openclose(struct SpaceOutliner *space_outliner,
-                             TreeElement *te,
-                             bool open,
-                             bool toggle_all);
+void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all);
 
 /* outliner_dragdrop.c */
 
diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc
index 31ae4aef7ff..088758c7583 100644
--- a/source/blender/editors/space_outliner/outliner_select.cc
+++ b/source/blender/editors/space_outliner/outliner_select.cc
@@ -1885,7 +1885,7 @@ static TreeElement *outliner_walk_left(SpaceOutliner *space_outliner,
   TreeStoreElem *tselem = TREESTORE(te);
 
   if (TSELEM_OPEN(tselem, space_outliner)) {
-    outliner_item_openclose(space_outliner, te, false, toggle_all);
+    outliner_item_openclose(te, false, toggle_all);
   }
   /* Only walk up a level if the element is closed and not toggling expand */
   else if (!toggle_all && te->parent) {
@@ -1906,7 +1906,7 @@ static TreeElement *outliner_walk_right(SpaceOutliner *space_outliner,
     te = static_cast<TreeElement *>(te->subtree.first);
   }
   else {
-    outliner_item_openclose(space_outliner, te, true, toggle_all);
+    outliner_item_openclose(te, true, toggle_all);
   }
 
   return te;
diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc
index 05df3f9cb8f..86195d30dc3 100644
--- a/source/blender/editors/space_outliner/outliner_tree.cc
+++ b/source/blender/editors/space_outliner/outliner_tree.cc
@@ -217,11 +217,6 @@ bool outliner_requires_rebuild_on_select_or_active_change(const SpaceOutliner *s
   return exclude_flags & (SO_FILTER_OB_STATE_SELECTED | SO_FILTER_OB_STATE_ACTIVE);
 }
 
-bool outliner_requires_rebuild_on_open_change(const SpaceOutliner *space_outliner)
-{
-  return ELEM(space_outliner->outlinevis, SO_DATA_API);
-}
-
 /* special handling of hierarchical non-lib data */
 static void outliner_add_bone(SpaceOutliner *space_outliner,
                               ListBase *lb,
diff --git a/source/blender/editors/space_outliner/outliner_utils.cc b/source/blender/editors/space_outliner/outliner_utils.cc
index 2ab9e146bc1..a077fd66f8c 100644
--- a/source/blender/editors/space_outliner/outliner_utils.cc
+++ b/source/blender/editors/space_outliner/outliner_utils.cc
@@ -27,6 +27,7 @@
 #include "UI_view2d.h"
 
 #include "outliner_intern.hh"
+#include "tree/tree_display.hh"
 #include "tree/tree_iterator.hh"
 
 using namespace blender::ed::outliner;
@@ -436,7 +437,7 @@ void outliner_tag_redraw_avoid_rebuild_on_open_change(const SpaceOutliner *space
                                                       ARegion *region)
 {
   /* Avoid rebuild if possible. */
-  if (outliner_requires_rebuild_on_open_change(space_outliner)) {
+  if (space_outliner->runtime->tree_display->is_lazy_built()) {
     ED_region_tag_redraw(region);
   }
   else {
diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc
index 6ab497b3fbb..fe4937829d6 100644
--- a/source/blender/editors/space_outliner/tree/tree_display.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display.cc
@@ -50,4 +50,9 @@ bool AbstractTreeDisplay::supportsModeColumn() const
   return false;
 }
 
+bool AbstractTreeDisplay::is_lazy_built() const
+{
+  return false;
+}
+
 }  // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh
index f8e35655c26..84eafcc3dd6 100644
--- a/source/blender/editors/space_outliner/tree/tree_display.hh
+++ b/source/blender/editors/space_outliner/tree/tree_display.hh
@@ -84,6 +84,15 @@ class AbstractTreeDisplay {
    */
   virtual bool supportsModeColumn() const;
 
+  /**
+   * Some trees may want to skip building children of collapsed parents. This should be done if the
+   * tree type may become very complex, which could cause noticeable slowdowns.
+   * Problem: This doesn't address performance issues while searching, since all elements are
+   * constructed for that. Trees of this type have to be rebuilt for any change to the collapsed
+   * state of any element.
+   */
+  virtual bool is_lazy_built() const;
+
  protected:
   /** All derived classes will need a handle to this, so storing it in the base for convenience. */
   SpaceOutliner &space_outliner_;
@@ -232,6 +241,8 @@ class TreeDisplayDataAPI final : public AbstractTreeDisplay {
   TreeDisplayDataAPI(SpaceOutliner &space_outliner);
 
   ListBase buildTree(const TreeSourceData &source_data) override;
+
+  bool is_lazy_built() const override;
 };
 
 }  // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_display_data.cc b/source/blender/editors/space_outliner/tree/tree_display_data.cc
index bfeb8ce2bdc..3d9b927fbf1 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_data.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_data.cc
@@ -42,4 +42,9 @@ ListBase TreeDisplayDataAPI::buildTree(const TreeSourceData &source_data)
   return tree;
 }
 
+bool TreeDisplayDataAPI::is_lazy_built() const
+{
+  return true;
+}
+
 }  // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_element_rna.cc b/source/blender/editors/space_outliner/tree/tree_element_rna.cc
index 6dd5ec84041..9e1f22b49d6 100644
--- a/source/blender/editors/space_outliner/tree/tree_element_rna.cc
+++ b/source/blender/editors/space_outliner/tree/tree_element_rna.cc
@@ -124,7 +124,7 @@ void TreeElementRNAStruct::expand(SpaceOutliner &space_outliner) const
     }
   }
   else if (tot) {
-    legacy_t

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list