[Bf-blender-cvs] [a6c00778c2e] temp-outliner-library-override-hierarchy: Mostly finished implementation of the hierarchy view

Julian Eisel noreply at git.blender.org
Fri Mar 25 14:17:21 CET 2022


Commit: a6c00778c2e5850d5b5034b27388ff74305505fa
Author: Julian Eisel
Date:   Thu Mar 24 18:52:21 2022 +0100
Branches: temp-outliner-library-override-hierarchy
https://developer.blender.org/rBa6c00778c2e5850d5b5034b27388ff74305505fa

Mostly finished implementation of the hierarchy view

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

M	release/scripts/startup/bl_ui/space_outliner.py
M	source/blender/editors/interface/interface_icons.c
M	source/blender/editors/space_outliner/outliner_draw.cc
M	source/blender/editors/space_outliner/outliner_utils.cc
M	source/blender/editors/space_outliner/tree/tree_display.hh
M	source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchy.cc
M	source/blender/editors/space_outliner/tree/tree_element.cc
M	source/blender/editors/space_outliner/tree/tree_element.hh
M	source/blender/editors/space_outliner/tree/tree_element_id.hh
M	source/blender/makesdna/DNA_space_types.h

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

diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index f80e07213f9..2222a994761 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -43,7 +43,11 @@ class OUTLINER_HT_header(Header):
                 text="",
                 icon='FILTER',
             )
-        if display_mode in {'LIBRARIES', 'LIBRARY_OVERRIDES', 'ORPHAN_DATA'}:
+        if display_mode == 'LIBRARY_OVERRIDES' and space.lib_override_view_mode == 'HIERARCHY':
+            # Don't add ID type filter for library overrides hierarchy mode. Point of it is to see a hierarchy that is usually
+            # constructed out of different ID types.
+            pass
+        elif display_mode in {'LIBRARIES', 'LIBRARY_OVERRIDES', 'ORPHAN_DATA'}:
             row.prop(space, "use_filter_id_type", text="", icon='FILTER')
             sub = row.row(align=True)
             sub.active = space.use_filter_id_type
@@ -366,7 +370,7 @@ class OUTLINER_PT_filter(Panel):
         col.prop(space, "use_filter_complete", text="Exact Match")
         col.prop(space, "use_filter_case_sensitive", text="Case Sensitive")
 
-        if display_mode in {'LIBRARY_OVERRIDES'} and bpy.data.libraries:
+        if display_mode in {'LIBRARY_OVERRIDES'} and space.lib_override_view_mode in {'PROPERTIES'} and bpy.data.libraries:
             col.separator()
             row = col.row()
             row.label(icon='LIBRARY_DATA_OVERRIDE')
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 07e4f6c2a24..cf35663b7b9 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -2169,6 +2169,9 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big)
 
 int UI_icon_from_library(const ID *id)
 {
+  if (ID_IS_OVERRIDE_LIBRARY(id)) {
+    return ICON_LIBRARY_DATA_OVERRIDE;
+  }
   if (ID_IS_LINKED(id)) {
     if (id->tag & LIB_TAG_MISSING) {
       return ICON_LIBRARY_DATA_BROKEN;
@@ -2178,9 +2181,6 @@ int UI_icon_from_library(const ID *id)
     }
     return ICON_LIBRARY_DATA_DIRECT;
   }
-  if (ID_IS_OVERRIDE_LIBRARY(id)) {
-    return ICON_LIBRARY_DATA_OVERRIDE;
-  }
   if (ID_IS_ASSET(id)) {
     return ICON_ASSET_MANAGER;
   }
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index 8b03047b1dd..061e97bda51 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -3911,7 +3911,8 @@ void draw_outliner(const bContext *C)
     /* draw user toggle columns */
     outliner_draw_userbuts(block, region, space_outliner, &space_outliner->tree);
   }
-  else if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {
+  else if ((space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) &&
+           (space_outliner->lib_override_view_mode == SO_LIB_OVERRIDE_VIEW_PROPERTIES)) {
     /* Draw overrides status columns. */
     outliner_draw_overrides_warning_buts(
         block, region, space_outliner, &space_outliner->tree, true);
diff --git a/source/blender/editors/space_outliner/outliner_utils.cc b/source/blender/editors/space_outliner/outliner_utils.cc
index ed5a2108d3c..7526cc7ef5c 100644
--- a/source/blender/editors/space_outliner/outliner_utils.cc
+++ b/source/blender/editors/space_outliner/outliner_utils.cc
@@ -324,6 +324,9 @@ float outliner_right_columns_width(const SpaceOutliner *space_outliner)
     case SO_LIBRARIES:
       return 0.0f;
     case SO_OVERRIDES_LIBRARY:
+      if (space_outliner->lib_override_view_mode != SO_LIB_OVERRIDE_VIEW_PROPERTIES) {
+        return 0.0f;
+      }
       num_columns = OL_RNA_COL_SIZEX / UI_UNIT_X;
       break;
     case SO_ID_ORPHANS:
diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh
index 2fde6d3b73f..1233e13fd6c 100644
--- a/source/blender/editors/space_outliner/tree/tree_display.hh
+++ b/source/blender/editors/space_outliner/tree/tree_display.hh
@@ -35,6 +35,8 @@ struct ViewLayer;
 
 namespace blender::ed::outliner {
 
+class TreeElementID;
+
 /**
  * \brief The data to build the tree from.
  */
@@ -149,6 +151,10 @@ class TreeDisplayOverrideLibraryHierarchy final : public AbstractTreeDisplay {
   TreeDisplayOverrideLibraryHierarchy(SpaceOutliner &space_outliner);
 
   ListBase buildTree(const TreeSourceData &source_data) override;
+
+ private:
+  ListBase build_hierarchy_for_lib_or_main(Main *bmain, TreeElement &parent_te, Library *lib = nullptr);
+  void build_hierarchy_for_ID(Main *bmain, ID &override_root_id, TreeElementID &te_id) const;
 };
 
 /* -------------------------------------------------------------------- */
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 c4870fe3b6b..186c7c3b6fb 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
@@ -4,22 +4,203 @@
  * \ingroup spoutliner
  */
 
+#include "DNA_ID.h"
+#include "DNA_collection_types.h"
+#include "DNA_key_types.h"
+#include "DNA_space_types.h"
+
 #include "BLI_listbase.h"
+#include "BLI_map.hh"
+
+#include "BLT_translation.h"
+
+#include "BKE_collection.h"
+#include "BKE_lib_query.h"
+#include "BKE_main.h"
 
+#include "../outliner_intern.hh"
+#include "common.hh"
 #include "tree_display.hh"
+#include "tree_element_id.hh"
 
 namespace blender::ed::outliner {
 
+class AbstractTreeElement;
+
 TreeDisplayOverrideLibraryHierarchy::TreeDisplayOverrideLibraryHierarchy(
     SpaceOutliner &space_outliner)
     : AbstractTreeDisplay(space_outliner)
 {
 }
 
-ListBase TreeDisplayOverrideLibraryHierarchy::buildTree(const TreeSourceData & /*source_data*/)
+/* XXX Remove expanded subtree, we add our own items here. Expanding should probably be
+ * optional. */
+static void remove_expanded_children(TreeElement &te)
+{
+  outliner_free_tree(&te.subtree);
+}
+
+ListBase TreeDisplayOverrideLibraryHierarchy::buildTree(const TreeSourceData &source_data)
 {
   ListBase tree = {nullptr};
+
+  /* First step: Build "Current File" hierarchy. */
+  TreeElement *current_file_te = outliner_add_element(
+      &space_outliner_, &tree, source_data.bmain, nullptr, TSE_ID_BASE, 0);
+  current_file_te->name = IFACE_("Current File");
+  {
+    AbstractTreeElement::uncollapse_by_default(current_file_te);
+    build_hierarchy_for_lib_or_main(source_data.bmain, *current_file_te);
+
+    /* Add dummy child if there's nothing to display. */
+    if (BLI_listbase_is_empty(&current_file_te->subtree)) {
+      TreeElement *dummy_te = outliner_add_element(
+          &space_outliner_, &current_file_te->subtree, nullptr, current_file_te, TSE_ID_BASE, 0);
+      dummy_te->name = IFACE_("No Library Overrides");
+    }
+  }
+
+  /* Second step: Build hierarchies for external libraries. */
+  for (Library *lib = (Library *)source_data.bmain->libraries.first; lib;
+       lib = (Library *)lib->id.next) {
+    TreeElement *tenlib = outliner_add_element(
+        &space_outliner_, &tree, lib, nullptr, TSE_SOME_ID, 0);
+    build_hierarchy_for_lib_or_main(source_data.bmain, *tenlib, lib);
+  }
+
+  /* Remove top level library elements again that don't contain any overrides. */
+  LISTBASE_FOREACH_MUTABLE (TreeElement *, top_level_te, &tree) {
+    if (top_level_te == current_file_te) {
+      continue;
+    }
+
+    if (BLI_listbase_is_empty(&top_level_te->subtree)) {
+      outliner_free_tree_element(top_level_te, &tree);
+    }
+  }
+
+  return tree;
+}
+
+/* TODO rename? */
+ListBase TreeDisplayOverrideLibraryHierarchy::build_hierarchy_for_lib_or_main(
+    Main *bmain, TreeElement &parent_te, Library *lib)
+{
+  ListBase tree = {nullptr};
+
+  /* Keep track over which ID base elements were already added, and expand them once added. */
+  Map<ID_Type, TreeElement *> id_base_te_map;
+  /* Index for the ID base elements ("Objects", "Materials", etc). */
+  int base_index = 0;
+
+  ID *iter_id;
+  FOREACH_MAIN_ID_BEGIN (bmain, iter_id) {
+    if (!ID_IS_OVERRIDE_LIBRARY_REAL(iter_id) || !ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(iter_id)) {
+      continue;
+    }
+    if (iter_id->lib != lib) {
+      continue;
+    }
+
+    TreeElement *new_base_te = id_base_te_map.lookup_or_add_cb(GS(iter_id->name), [&]() {
+      TreeElement *new_te = outliner_add_element(&space_outliner_,
+                                                 &parent_te.subtree,
+                                                 lib ? (void *)lib : bmain,
+                                                 &parent_te,
+                                                 TSE_ID_BASE,
+                                                 base_index++);
+      new_te->name = outliner_idcode_to_plural(GS(iter_id->name));
+      return new_te;
+    });
+
+    TreeElement *new_id_te = outliner_add_element(
+        &space_outliner_, &new_base_te->subtree, iter_id, new_base_te, TSE_SOME_ID, 0);
+    remove_expanded_children(*new_id_te);
+
+    build_hierarchy_for_ID(bmain, *iter_id, *tree_element_cast<TreeElementID>(new_id_te));
+  }
+  FOREACH_MAIN_ID_END;
+
   return tree;
 }
 
+struct BuildHierarchyForeachIDCbData {
+  SpaceOutliner &space_outliner;
+  ID &override_root_id;
+  TreeElementID &root_id_te;
+  Map<ID *, TreeElement *> added_elems{};
+};
+
+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). */
+  ID &id = **cb_data->id_pointer;
+  /* If #id is an embedded ID, this will be set to the owner, which is a real ID

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list