[Bf-blender-cvs] [c73cc15e07e] blender-v3.3-release: LibOverride: Rework Outliner contextual menu.

Bastien Montagne noreply at git.blender.org
Fri Aug 12 15:12:07 CEST 2022


Commit: c73cc15e07ea6b0e2e4d1f7fa419e428291f45ad
Author: Bastien Montagne
Date:   Fri Aug 12 15:06:18 2022 +0200
Branches: blender-v3.3-release
https://developer.blender.org/rBc73cc15e07ea6b0e2e4d1f7fa419e428291f45ad

LibOverride: Rework Outliner contextual menu.

Follow-up to design discussions here at the studio, add liboverride
operations into their own sub-menu, with three main entries:
- Create: Create, or enable for user editing, override hierarchies.
- Reset: Keep overrides data, but reset all local changes to the
  reference linked data values.
- Clear: like reset, but also turn editable overrides back to system
  overrides (aka non user editable).

Those three options can all operate either on the selected items, their
content only, or both.

Advanced operations are moved into a "Troubleshoot Hierarchy" sub-menu,
where one can resync, resync enforced, and fully delete library
overrides. Those operations always affect a whole override hierarchy,
regardless of which items are selected or not.

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

M	release/scripts/startup/bl_ui/space_outliner.py
M	source/blender/editors/space_outliner/outliner_intern.hh
M	source/blender/editors/space_outliner/outliner_ops.cc
M	source/blender/editors/space_outliner/outliner_tools.cc

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

diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 011a430a1ec..66e6a174003 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -97,6 +97,10 @@ class OUTLINER_MT_context_menu(Menu):
 
         layout.separator()
 
+        layout.menu("OUTLINER_MT_liboverride")
+
+        layout.separator()
+
         layout.menu("OUTLINER_MT_context_menu_view")
 
         layout.separator()
@@ -320,6 +324,19 @@ class OUTLINER_MT_asset(Menu):
         layout.operator("asset.clear", text="Clear Asset (Set Fake User)").set_fake_user = True
 
 
+class OUTLINER_MT_liboverride(Menu):
+    bl_label = "Library Override"
+
+    def draw(self, _context):
+        layout = self.layout
+
+        layout.operator_menu_enum("outliner.liboverride_operation", "selection_set", text="Create").type = 'OVERRIDE_LIBRARY_CREATE_HIERARCHY'
+        layout.operator_menu_enum("outliner.liboverride_operation", "selection_set", text="Reset").type = 'OVERRIDE_LIBRARY_RESET'
+        layout.operator_menu_enum("outliner.liboverride_operation", "selection_set", text="Clear").type = 'OVERRIDE_LIBRARY_CLEAR_SINGLE'
+
+        layout.operator_menu_enum("outliner.liboverride_troubleshoot_operation", "type", text="Troubleshoot Hierarchy").selection_set = 'SELECTED'
+
+
 class OUTLINER_PT_filter(Panel):
     bl_space_type = 'OUTLINER'
     bl_region_type = 'HEADER'
@@ -457,6 +474,7 @@ classes = (
     OUTLINER_MT_collection_view_layer,
     OUTLINER_MT_object,
     OUTLINER_MT_asset,
+    OUTLINER_MT_liboverride,
     OUTLINER_MT_context_menu,
     OUTLINER_MT_context_menu_view,
     OUTLINER_MT_view_pie,
diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh
index 18173b37123..5362782dd84 100644
--- a/source/blender/editors/space_outliner/outliner_intern.hh
+++ b/source/blender/editors/space_outliner/outliner_intern.hh
@@ -530,6 +530,8 @@ void OUTLINER_OT_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_liboverride_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_liboverride_troubleshoot_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_id_remap(struct wmOperatorType *ot);
 void OUTLINER_OT_id_copy(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.cc b/source/blender/editors/space_outliner/outliner_ops.cc
index 8baac45666e..b384c41aa69 100644
--- a/source/blender/editors/space_outliner/outliner_ops.cc
+++ b/source/blender/editors/space_outliner/outliner_ops.cc
@@ -29,6 +29,8 @@ void outliner_operatortypes(void)
   WM_operatortype_append(OUTLINER_OT_object_operation);
   WM_operatortype_append(OUTLINER_OT_lib_operation);
   WM_operatortype_append(OUTLINER_OT_lib_relocate);
+  WM_operatortype_append(OUTLINER_OT_liboverride_operation);
+  WM_operatortype_append(OUTLINER_OT_liboverride_troubleshoot_operation);
   WM_operatortype_append(OUTLINER_OT_id_operation);
   WM_operatortype_append(OUTLINER_OT_id_delete);
   WM_operatortype_append(OUTLINER_OT_id_remap);
diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc
index 87604818ee1..9a8bd15df85 100644
--- a/source/blender/editors/space_outliner/outliner_tools.cc
+++ b/source/blender/editors/space_outliner/outliner_tools.cc
@@ -453,6 +453,99 @@ static void outliner_do_libdata_operation(bContext *C,
   });
 }
 
+typedef enum eOutlinerLibOpSelectionSet {
+  /* Only selected items. */
+  OUTLINER_LIB_SELECTIONSET_SELECTED,
+  /* Only content 'inside' selected items (their sub-tree). */
+  OUTLINER_LIB_LIB_SELECTIONSET_CONTENT,
+  /* Combining both options above. */
+  OUTLINER_LIB_LIB_SELECTIONSET_SELECTED_AND_CONTENT,
+} eOutlinerLibOpSelectionSet;
+
+static const EnumPropertyItem prop_lib_op_selection_set[] = {
+    {OUTLINER_LIB_SELECTIONSET_SELECTED,
+     "SELECTED",
+     0,
+     "Selected",
+     "Apply the operation over selected data-blocks only"},
+    {OUTLINER_LIB_LIB_SELECTIONSET_CONTENT,
+     "CONTENT",
+     0,
+     "Content",
+     "Apply the operation over content of the selected items only (the data-blocks in their "
+     "sub-tree)"},
+    {OUTLINER_LIB_LIB_SELECTIONSET_SELECTED_AND_CONTENT,
+     "SELECTED_AND_CONTENT",
+     0,
+     "Selected & Content",
+     "Apply the operation over selected data-blocks and all their dependencies"},
+    {0, nullptr, 0, nullptr, nullptr},
+};
+
+static void outliner_do_libdata_operation_selection_set(bContext *C,
+                                                        ReportList *reports,
+                                                        Scene *scene,
+                                                        SpaceOutliner *space_outliner,
+                                                        const ListBase &subtree,
+                                                        const bool has_parent_selected,
+                                                        outliner_operation_fn operation_fn,
+                                                        eOutlinerLibOpSelectionSet selection_set,
+                                                        void *user_data)
+{
+  const bool do_selected = ELEM(selection_set,
+                                OUTLINER_LIB_SELECTIONSET_SELECTED,
+                                OUTLINER_LIB_LIB_SELECTIONSET_SELECTED_AND_CONTENT);
+  const bool do_content = ELEM(selection_set,
+                               OUTLINER_LIB_LIB_SELECTIONSET_CONTENT,
+                               OUTLINER_LIB_LIB_SELECTIONSET_SELECTED_AND_CONTENT);
+
+  LISTBASE_FOREACH_MUTABLE (TreeElement *, element, &subtree) {
+    /* Get needed data out in case element gets freed. */
+    TreeStoreElem *tselem = TREESTORE(element);
+    const ListBase subtree = element->subtree;
+
+    bool is_selected = tselem->flag & TSE_SELECTED;
+    if ((is_selected && do_selected) || (has_parent_selected && do_content)) {
+      if (((tselem->type == TSE_SOME_ID) && (element->idcode != 0)) ||
+          tselem->type == TSE_LAYER_COLLECTION) {
+        TreeStoreElem *tsep = element->parent ? TREESTORE(element->parent) : nullptr;
+        operation_fn(C, reports, scene, element, tsep, tselem, user_data);
+      }
+    }
+
+    /* Don't access element from now on, it may be freed. Note that the open/collapsed state may
+     * also have been changed in the visitor callback. */
+    outliner_do_libdata_operation_selection_set(C,
+                                                reports,
+                                                scene,
+                                                space_outliner,
+                                                subtree,
+                                                is_selected || has_parent_selected,
+                                                operation_fn,
+                                                selection_set,
+                                                user_data);
+  }
+}
+
+static void outliner_do_libdata_operation_selection_set(bContext *C,
+                                                        ReportList *reports,
+                                                        Scene *scene,
+                                                        SpaceOutliner *space_outliner,
+                                                        outliner_operation_fn operation_fn,
+                                                        eOutlinerLibOpSelectionSet selection_set,
+                                                        void *user_data)
+{
+  outliner_do_libdata_operation_selection_set(C,
+                                              reports,
+                                              scene,
+                                              space_outliner,
+                                              space_outliner->tree,
+                                              false,
+                                              operation_fn,
+                                              selection_set,
+                                              user_data);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -842,6 +935,20 @@ struct OutlinerLibOverrideData {
         id_hierarchy_root_reference);
     value.append(id_root_data);
   }
+  void id_root_set(ID *id_hierarchy_root_reference)
+  {
+    OutlinerLiboverrideDataIDRoot id_root_data;
+    id_root_data.id_root_reference = nullptr;
+    id_root_data.id_hierarchy_root_override = nullptr;
+    id_root_data.id_instance_hint = nullptr;
+    id_root_data.is_override_instancing_object = false;
+
+    Vector<OutlinerLiboverrideDataIDRoot> &value = id_hierarchy_roots.lookup_or_add_default(
+        id_hierarchy_root_reference);
+    if (value.is_empty()) {
+      value.append(id_root_data);
+    }
+  }
 };
 
 /* Store 'UUID' of IDs of selected elements in the Outliner tree, before generating the override
@@ -860,17 +967,29 @@ static void id_override_library_create_hierarchy_pre_process_fn(bContext *C,
   const bool do_hierarchy = data->do_hierarchy;
   ID *id_root_reference = tselem->id;
 
+  if (!BKE_idtype_idcode_is_linkable(GS(id_root_reference->name)) ||
+      (id_root_reference->flag & (LIB_EMBEDDED_DATA | LIB_EMBEDDED_DATA_LIB_OVERRIDE)) != 0) {
+    return;
+  }
+
   BLI_assert(do_hierarchy);
   UNUSED_VARS_NDEBUG(do_hierarchy);
 
+  printf("Adding %s as selected item to get editable override\n", id_root_reference->name);
   data->selected_id_uid.add(id_root_reference->session_uuid);
 
+  if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root_reference) && !ID_IS_LINKED(id_root_reference)) {
+    id_root_reference->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
+    return;
+  }
+
   if (GS(id_root_reference->name) == ID_GR && (tselem->flag & TSE_CLOSED) != 0) {
     /* If selected element is a (closed) collection, check all of its objects recursively, a

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list