Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2022-03-31 13:09:56 +0300
committerJulian Eisel <julian@blender.org>2022-03-31 13:21:14 +0300
commit0c6dc7c59ebd8d7857e8c078e37e285769fb5770 (patch)
tree4309b5d7018dd0fb6a4fd844844fa966921cad53
parent2202259e9c1f704496c66a19c15d4174d6c9a3f0 (diff)
Outliner: New "Hierarchies" view mode for Library Overrides
Adds a dropdown for the Library Overrides display mode that lets users choose between a "Properties" and a "Hierachies" view mode. The former is what was previously there (a mode that displays all overridden properties with buttons to edit the values), the latter is new. It displays the hierarchical relationships between library overridden data-blocks. E.g. to override the mesh of an object inside a linked collection, the entire collection > object > mesh hierarchy needs to be overridden (whereby the former two will be automatically overridden using system overrides). The Hierarchies mode will also show the override hierarchies of data-blocks that were linked and are overridden in the source file. This information is useful to have, especially for debugging scenes. Part of T95802. Differential Revision: https://developer.blender.org/D14440 Reviewed by: Bastien Montagne
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py10
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt3
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.cc13
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.cc3
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display.cc8
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display.hh24
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc224
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_override_library_properties.cc (renamed from source/blender/editors/space_outliner/tree/tree_display_override_library.cc)8
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element.cc7
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element.hh13
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_id.hh5
-rw-r--r--source/blender/makesdna/DNA_space_types.h14
-rw-r--r--source/blender/makesrna/intern/rna_space.c22
13 files changed, 337 insertions, 17 deletions
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 0f3dc1f8794..eff8ad8e8b3 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -22,6 +22,8 @@ class OUTLINER_HT_header(Header):
if display_mode == 'DATA_API':
OUTLINER_MT_editor_menus.draw_collapsible(context, layout)
+ if display_mode == 'LIBRARY_OVERRIDES':
+ layout.prop(space, "lib_override_view_mode", text="")
layout.separator_spacer()
@@ -41,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 == 'HIERARCHIES':
+ # Don't add ID type filter for library overrides hierarchies 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
@@ -364,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 == 'LIBRARY_OVERRIDES' and bpy.data.libraries:
+ if display_mode == 'LIBRARY_OVERRIDES' and space.lib_override_view_mode == 'PROPERTIES' and bpy.data.libraries:
col.separator()
row = col.row()
row.label(icon='LIBRARY_DATA_OVERRIDE')
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index b57525854d6..fae0e4be2a8 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -38,7 +38,8 @@ set(SRC
tree/tree_display_data.cc
tree/tree_display_libraries.cc
tree/tree_display_orphaned.cc
- tree/tree_display_override_library.cc
+ tree/tree_display_override_library_properties.cc
+ tree/tree_display_override_library_hierarchies.cc
tree/tree_display_scenes.cc
tree/tree_display_sequencer.cc
tree/tree_display_view_layer.cc
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index a6f09a86eb4..d204e12b41d 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -3899,6 +3899,12 @@ void draw_outliner(const bContext *C)
/* Default to no emboss for outliner UI. */
UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
+ if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {
+ /* Draw overrides status columns. */
+ outliner_draw_overrides_warning_buts(
+ block, region, space_outliner, &space_outliner->tree, true);
+ }
+
if (space_outliner->outlinevis == SO_DATA_API) {
int buttons_start_x = outliner_data_api_buttons_start_x(tree_width);
/* draw rna buttons */
@@ -3913,11 +3919,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) {
- /* Draw overrides status columns. */
- outliner_draw_overrides_warning_buts(
- block, region, space_outliner, &space_outliner->tree, true);
-
+ else if ((space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) &&
+ (space_outliner->lib_override_view_mode == SO_LIB_OVERRIDE_VIEW_PROPERTIES)) {
UI_block_emboss_set(block, UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_NO_DRAW_OVERRIDDEN_STATE);
const int x = region->v2d.cur.xmax - right_column_width;
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.cc b/source/blender/editors/space_outliner/tree/tree_display.cc
index f9141dffd6a..141c68594e8 100644
--- a/source/blender/editors/space_outliner/tree/tree_display.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display.cc
@@ -30,7 +30,13 @@ std::unique_ptr<AbstractTreeDisplay> AbstractTreeDisplay::createFromDisplayMode(
case SO_ID_ORPHANS:
return std::make_unique<TreeDisplayIDOrphans>(space_outliner);
case SO_OVERRIDES_LIBRARY:
- return std::make_unique<TreeDisplayOverrideLibrary>(space_outliner);
+ switch ((eSpaceOutliner_LibOverrideViewMode)space_outliner.lib_override_view_mode) {
+ case SO_LIB_OVERRIDE_VIEW_PROPERTIES:
+ return std::make_unique<TreeDisplayOverrideLibraryProperties>(space_outliner);
+ case SO_LIB_OVERRIDE_VIEW_HIERARCHIES:
+ return std::make_unique<TreeDisplayOverrideLibraryHierarchies>(space_outliner);
+ }
+ break;
case SO_VIEW_LAYER:
return std::make_unique<TreeDisplayViewLayer>(space_outliner);
}
diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh
index a60d3339042..327f29aa15e 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.
*/
@@ -127,11 +129,11 @@ class TreeDisplayLibraries final : public AbstractTreeDisplay {
/* Library Overrides Tree-Display. */
/**
- * \brief Tree-Display for the Library Overrides display mode.
+ * \brief Tree-Display for the Library Overrides display mode, Properties view mode.
*/
-class TreeDisplayOverrideLibrary final : public AbstractTreeDisplay {
+class TreeDisplayOverrideLibraryProperties final : public AbstractTreeDisplay {
public:
- TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner);
+ TreeDisplayOverrideLibraryProperties(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
@@ -140,6 +142,22 @@ class TreeDisplayOverrideLibrary final : public AbstractTreeDisplay {
short id_filter_get() const;
};
+/**
+ * \brief Tree-Display for the Library Overrides display mode, Hierarchies view mode.
+ */
+class TreeDisplayOverrideLibraryHierarchies final : public AbstractTreeDisplay {
+ public:
+ TreeDisplayOverrideLibraryHierarchies(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;
+};
+
/* -------------------------------------------------------------------- */
/* Video Sequencer Tree-Display */
diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc
new file mode 100644
index 00000000000..4b568a6004d
--- /dev/null
+++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \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 "BLI_set.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;
+
+TreeDisplayOverrideLibraryHierarchies::TreeDisplayOverrideLibraryHierarchies(
+ SpaceOutliner &space_outliner)
+ : AbstractTreeDisplay(space_outliner)
+{
+}
+
+/* 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 TreeDisplayOverrideLibraryHierarchies::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, -1);
+ 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;
+}
+
+ListBase TreeDisplayOverrideLibraryHierarchies::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 {
+ /* Don't allow copies, the sets below would need deep copying. */
+ BuildHierarchyForeachIDCbData(const BuildHierarchyForeachIDCbData &) = delete;
+
+ Main &bmain;
+ SpaceOutliner &space_outliner;
+ ID &override_root_id;
+
+ /* 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->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 and contains the
+ * override data. So queries of override data should be done via this, but the actual tree
+ * element we add is the embedded ID. */
+ const ID *real_override_id = &id;
+
+ if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(&id)) {
+ if (GS(id.name) == ID_KE) {
+ Key *key = (Key *)&id;
+ real_override_id = key->from;
+ }
+ else if (id.flag & LIB_EMBEDDED_DATA) {
+ /* TODO Needs double-checking if this handles all embedded IDs correctly. */
+ real_override_id = cb_data->id_owner;
+ }
+ }
+
+ if (!ID_IS_OVERRIDE_LIBRARY(real_override_id)) {
+ return IDWALK_RET_NOP;
+ }
+ /* Is this ID part of the same override hierarchy? */
+ if (real_override_id->override_library->hierarchy_root != &build_data.override_root_id) {
+ return IDWALK_RET_NOP;
+ }
+
+ /* 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;
+ }
+
+ /* Avoid duplicates: If there is a 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,
+ &build_data.parent_te->getLegacyElement().subtree,
+ &id,
+ &build_data.parent_te->getLegacyElement(),
+ TSE_SOME_ID,
+ 0);
+ remove_expanded_children(*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;
+}
+
+void TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_ID(Main *bmain,
+ ID &override_root_id,
+ TreeElementID &te_id) const
+{
+ 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, &te_id.get_ID(), build_hierarchy_foreach_ID_cb, &build_data, IDWALK_READONLY);
+}
+
+} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_properties.cc
index 2162c303da1..4c57f91a0a7 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_properties.cc
@@ -25,12 +25,12 @@ namespace blender::ed::outliner {
/* Convenience/readability. */
template<typename T> using List = ListBaseWrapper<T>;
-TreeDisplayOverrideLibrary::TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner)
+TreeDisplayOverrideLibraryProperties::TreeDisplayOverrideLibraryProperties(SpaceOutliner &space_outliner)
: AbstractTreeDisplay(space_outliner)
{
}
-ListBase TreeDisplayOverrideLibrary::buildTree(const TreeSourceData &source_data)
+ListBase TreeDisplayOverrideLibraryProperties::buildTree(const TreeSourceData &source_data)
{
ListBase tree = add_library_contents(*source_data.bmain);
@@ -44,7 +44,7 @@ ListBase TreeDisplayOverrideLibrary::buildTree(const TreeSourceData &source_data
return tree;
}
-ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar)
+ListBase TreeDisplayOverrideLibraryProperties::add_library_contents(Main &mainvar)
{
ListBase tree = {nullptr};
@@ -114,7 +114,7 @@ ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar)
return tree;
}
-short TreeDisplayOverrideLibrary::id_filter_get() const
+short TreeDisplayOverrideLibraryProperties::id_filter_get() const
{
if (space_outliner_.filter & SO_FILTER_ID_TYPE) {
return space_outliner_.filter_id_type;
diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc
index ca67aad00db..7fe3f08b3be 100644
--- a/source/blender/editors/space_outliner/tree/tree_element.cc
+++ b/source/blender/editors/space_outliner/tree/tree_element.cc
@@ -98,6 +98,13 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i
return nullptr;
}
+void AbstractTreeElement::uncollapse_by_default(TreeElement *legacy_te)
+{
+ if (!TREESTORE(legacy_te)->used) {
+ TREESTORE(legacy_te)->flag &= ~TSE_CLOSED;
+ }
+}
+
void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner &space_outliner)
{
/* Most types can just expand. IDs optionally expand (hence the poll) and do additional, common
diff --git a/source/blender/editors/space_outliner/tree/tree_element.hh b/source/blender/editors/space_outliner/tree/tree_element.hh
index 6f2d803ae96..c6593a517dd 100644
--- a/source/blender/editors/space_outliner/tree/tree_element.hh
+++ b/source/blender/editors/space_outliner/tree/tree_element.hh
@@ -50,6 +50,19 @@ class AbstractTreeElement {
return true;
}
+ TreeElement &getLegacyElement()
+ {
+ return legacy_te_;
+ }
+
+ /**
+ * Expand this tree element if it is displayed for the first time (as identified by its
+ * tree-store element).
+ *
+ * Static for now to allow doing this from the legacy tree element.
+ */
+ static void uncollapse_by_default(TreeElement *legacy_te);
+
friend void tree_element_expand(const AbstractTreeElement &tree_element,
SpaceOutliner &space_outliner);
diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.hh b/source/blender/editors/space_outliner/tree/tree_element_id.hh
index b7519fe06f9..c2bbfd9f107 100644
--- a/source/blender/editors/space_outliner/tree/tree_element_id.hh
+++ b/source/blender/editors/space_outliner/tree/tree_element_id.hh
@@ -35,6 +35,11 @@ class TreeElementID : public AbstractTreeElement {
return false;
}
+ ID &get_ID()
+ {
+ return id_;
+ }
+
protected:
/* ID types with animation data can use this. */
void expand_animation_data(SpaceOutliner &, const AnimData *) const;
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 6d7952cb799..e9bf3126c97 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -280,8 +280,12 @@ typedef struct SpaceOutliner {
char search_string[64];
struct TreeStoreElem search_tse;
- short flag, outlinevis, storeflag;
+ short flag;
+ short outlinevis;
+ short lib_override_view_mode;
+ short storeflag;
char search_flags;
+ char _pad[6];
/** Selection syncing flag (#WM_OUTLINER_SYNC_SELECT_FROM_OBJECT and similar flags). */
char sync_select_dirty;
@@ -388,6 +392,14 @@ typedef enum eSpaceOutliner_Mode {
SO_OVERRIDES_LIBRARY = 16,
} eSpaceOutliner_Mode;
+/** #SpaceOutliner.outlinevis */
+typedef enum eSpaceOutliner_LibOverrideViewMode {
+ /* View all overrides with RNA buttons to edit the overridden values. */
+ SO_LIB_OVERRIDE_VIEW_PROPERTIES = 0,
+ /* View entire override hierarchies (relationships between overriden data-blocks). */
+ SO_LIB_OVERRIDE_VIEW_HIERARCHIES = 1,
+} eSpaceOutliner_LibOverrideViewMode;
+
/** #SpaceOutliner.storeflag */
typedef enum eSpaceOutliner_StoreFlag {
/* cleanup tree */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 3839b3ba6a4..e21c10166ab 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3593,6 +3593,21 @@ static void rna_def_space_outliner(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem lib_override_view_mode[] = {
+ {SO_LIB_OVERRIDE_VIEW_PROPERTIES,
+ "PROPERTIES",
+ ICON_NONE,
+ "Properties",
+ "Display all local override data-blocks with their overridden properties and buttons to "
+ "edit them"},
+ {SO_LIB_OVERRIDE_VIEW_HIERARCHIES,
+ "HIERARCHIES",
+ ICON_NONE,
+ "Hierarchies",
+ "Display library override relationships"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem filter_state_items[] = {
{SO_FILTER_OB_ALL, "ALL", 0, "All", "Show all objects in the view layer"},
{SO_FILTER_OB_VISIBLE, "VISIBLE", 0, "Visible", "Show visible objects"},
@@ -3612,6 +3627,13 @@ static void rna_def_space_outliner(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display Mode", "Type of information to display");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+ prop = RNA_def_property(srna, "lib_override_view_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, lib_override_view_mode);
+ RNA_def_property_ui_text(prop,
+ "Library Override View Mode",
+ "Choose different visualizations of library override data");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "search_string");
RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string");