[Bf-blender-cvs] [dddf793f757] temp-outliner-library-override-hierarchy: Use non-recursive ID loop & fix issues adding same ID multiple times

Julian Eisel noreply at git.blender.org
Tue Mar 29 18:36:59 CEST 2022


Commit: dddf793f7575512229705c81bc3ab6bc5837766f
Author: Julian Eisel
Date:   Tue Mar 29 18:35:57 2022 +0200
Branches: temp-outliner-library-override-hierarchy
https://developer.blender.org/rBdddf793f7575512229705c81bc3ab6bc5837766f

Use non-recursive ID loop & fix issues adding same ID multiple times

Makes things quite a bit simpler.

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

M	source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchy.cc

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

diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchy.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchy.cc
index d666b3acc5c..688e8bb0657 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchy.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchy.cc
@@ -11,6 +11,7 @@
 
 #include "BLI_listbase.h"
 #include "BLI_map.hh"
+#include "BLI_set.hh"
 
 #include "BLT_translation.h"
 
@@ -82,7 +83,6 @@ ListBase TreeDisplayOverrideLibraryHierarchy::buildTree(const TreeSourceData &so
   return tree;
 }
 
-/* TODO rename? */
 ListBase TreeDisplayOverrideLibraryHierarchy::build_hierarchy_for_lib_or_main(
     Main *bmain, TreeElement &parent_te, Library *lib)
 {
@@ -125,21 +125,29 @@ ListBase TreeDisplayOverrideLibraryHierarchy::build_hierarchy_for_lib_or_main(
 }
 
 struct BuildHierarchyForeachIDCbData {
+  /* Don't allow copies, the sets below would need deep copying. */
+  BuildHierarchyForeachIDCbData(const BuildHierarchyForeachIDCbData &) = delete;
+
+  Main &bmain;
   SpaceOutliner &space_outliner;
   ID &override_root_id;
-  TreeElementID &root_id_te;
-  Map<ID *, TreeElement *> added_elems{};
+
+  /* The tree element to expand. Changes with every level of recursion. */
+  TreeElementID *parent_te;
+  /* The ancestor IDs leading to the current ID, to avoid IDs recursing into themselves. Changes
+   * with every level of recursion. */
+  Set<ID *> parent_ids{};
+  /* The IDs that were already added to #parent_te, to avoid duplicates. Entirely new set with
+   * every level of recursion. */
+  Set<ID *> sibling_ids{};
 };
 
 static int build_hierarchy_foreach_ID_cb(LibraryIDLinkCallbackData *cb_data)
 {
-  if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
-    /* We should never have anything to do with loop-back pointers here. */
-    return IDWALK_RET_NOP;
-  }
   if (!*cb_data->id_pointer) {
     return IDWALK_RET_NOP;
   }
+
   BuildHierarchyForeachIDCbData &build_data = *reinterpret_cast<BuildHierarchyForeachIDCbData *>(
       cb_data->user_data);
   /* Note that this may be an embedded ID (see #real_override_id). */
@@ -168,29 +176,36 @@ static int build_hierarchy_foreach_ID_cb(LibraryIDLinkCallbackData *cb_data)
     return IDWALK_RET_NOP;
   }
 
-  TreeElement *te_to_expand = &build_data.root_id_te.getLegacyElement();
-  /* If there is already an element for the ID linking to the current one, use that as parent. */
-  if (TreeElement *parent_te_id = build_data.added_elems.lookup_default(cb_data->id_self,
-                                                                        nullptr)) {
-    te_to_expand = parent_te_id;
+  /* Avoid endless recursion: If there is an ancestor for this ID already, it recurses into itself.
+   */
+  if (build_data.parent_ids.lookup_key_default(&id, nullptr)) {
+    return IDWALK_RET_NOP;
   }
 
-  /* Check if an ancestor of this element is already the ID we want to add, this would mean an ID
-   * recurses into itself. Don't add the element and stop recursing in that case. */
-  for (TreeElement *parent_iter_te = te_to_expand; parent_iter_te;
-       parent_iter_te = parent_iter_te->parent) {
-    if (TreeElementID *id_te = tree_element_cast<TreeElementID>(parent_iter_te)) {
-      if (&id_te->get_ID() == &id) {
-        return IDWALK_RET_STOP_RECURSION;
-      }
-    }
+  /* Avoid duplicates: If there is an sibling for this ID already, the same ID is just used
+   * multiple times by the same parent. */
+  if (build_data.sibling_ids.lookup_key_default(&id, nullptr)) {
+    return IDWALK_RET_NOP;
   }
 
-  TreeElement *new_te = outliner_add_element(
-      &build_data.space_outliner, &te_to_expand->subtree, &id, te_to_expand, TSE_SOME_ID, 0);
+  TreeElement *new_te = outliner_add_element(&build_data.space_outliner,
+                                             &build_data.parent_te->getLegacyElement().subtree,
+                                             &id,
+                                             &build_data.parent_te->getLegacyElement(),
+                                             TSE_SOME_ID,
+                                             0);
   remove_expanded_children(*new_te);
-
-  build_data.added_elems.add(&id, new_te);
+  build_data.sibling_ids.add(&id);
+
+  BuildHierarchyForeachIDCbData child_build_data{build_data.bmain,
+                                                 build_data.space_outliner,
+                                                 build_data.override_root_id,
+                                                 tree_element_cast<TreeElementID>(new_te)};
+  child_build_data.parent_ids = build_data.parent_ids;
+  child_build_data.parent_ids.add(&id);
+  child_build_data.sibling_ids.reserve(10);
+  BKE_library_foreach_ID_link(
+      &build_data.bmain, &id, build_hierarchy_foreach_ID_cb, &child_build_data, IDWALK_READONLY);
 
   return IDWALK_RET_NOP;
 }
@@ -199,11 +214,11 @@ void TreeDisplayOverrideLibraryHierarchy::build_hierarchy_for_ID(Main *bmain,
                                                                  ID &override_root_id,
                                                                  TreeElementID &te_id) const
 {
-  BuildHierarchyForeachIDCbData build_data{space_outliner_, override_root_id, te_id};
-  ID &id = te_id.get_ID();
+  BuildHierarchyForeachIDCbData build_data{*bmain, space_outliner_, override_root_id, &te_id};
+  build_data.parent_ids.add(&override_root_id);
 
   BKE_library_foreach_ID_link(
-      bmain, &id, build_hierarchy_foreach_ID_cb, &build_data, IDWALK_RECURSE | IDWALK_READONLY);
+      bmain, &te_id.get_ID(), build_hierarchy_foreach_ID_cb, &build_data, IDWALK_READONLY);
 }
 
 }  // namespace blender::ed::outliner



More information about the Bf-blender-cvs mailing list