[Bf-blender-cvs] [26c0ca3aa7f] master: Outliner: Unified delete hierarchy operator

Nathan Craddock noreply at git.blender.org
Wed Jun 17 17:01:50 CEST 2020


Commit: 26c0ca3aa7f4f6e3836aac1636bf60c302afd12e
Author: Nathan Craddock
Date:   Wed Jun 17 09:00:04 2020 -0600
Branches: master
https://developer.blender.org/rB26c0ca3aa7f4f6e3836aac1636bf60c302afd12e

Outliner: Unified delete hierarchy operator

This resolves T73673 by allowing delete hierarchy in all outliner view
modes. It also unifies the collection and object hierarchy delete into a
single operator like in rBae98a033c856. This makes it easier to delete
all selected collection and object hierarchies at once.

This also removes the old object delete hierarchy code in favor of the
batch delete code which has been default for over a year.

Maniphest Tasks: T73673

Differential Revision: https://developer.blender.org/D7675

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

M	release/scripts/startup/bl_ui/space_outliner.py
M	source/blender/editors/space_outliner/outliner_tools.c

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

diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index ee8015df273..aa4d0b94b7f 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -213,7 +213,7 @@ class OUTLINER_MT_collection(Menu):
         layout.separator()
 
         layout.operator("outliner.delete", text="Delete", icon='X')
-        layout.operator("outliner.collection_hierarchy_delete")
+        layout.operator("outliner.delete", text="Delete Hierarchy").hierarchy = True
 
         layout.separator()
 
@@ -279,9 +279,7 @@ class OUTLINER_MT_object(Menu):
         layout.separator()
 
         layout.operator("outliner.delete", text="Delete", icon='X')
-
-        if space.display_mode == 'VIEW_LAYER' and not space.use_filter_collection:
-            layout.operator("outliner.object_operation", text="Delete Hierarchy").type = 'DELETE_HIERARCHY'
+        layout.operator("outliner.delete", text="Delete Hierarchy").hierarchy = True
 
         layout.separator()
 
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 80a63af3f42..4b780df1cbf 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -44,6 +44,7 @@
 #include "DNA_world_types.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_ghash.h"
 #include "BLI_utildefines.h"
 
 #include "BKE_anim_data.h"
@@ -689,12 +690,8 @@ static void object_deselect_cb(bContext *C,
   }
 }
 
-static void outliner_object_delete(bContext *C,
-                                   ReportList *reports,
-                                   Scene *scene,
-                                   TreeStoreElem *tselem)
+static void outliner_object_delete_fn(bContext *C, ReportList *reports, Scene *scene, Object *ob)
 {
-  Object *ob = (Object *)tselem->id;
   if (ob) {
     Main *bmain = CTX_data_main(C);
     if (ob->id.tag & LIB_TAG_INDIRECT) {
@@ -860,7 +857,6 @@ void outliner_do_object_operation_ex(bContext *C,
                                      bool select_recurse)
 {
   TreeElement *te;
-
   for (te = lb->first; te; te = te->next) {
     TreeStoreElem *tselem = TREESTORE(te);
     bool select_handled = false;
@@ -1175,82 +1171,6 @@ static void outliner_do_data_operation(
   }
 }
 
-static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, Base *base)
-{
-  Base *child_base, *base_next;
-  Object *parent;
-  ViewLayer *view_layer = CTX_data_view_layer(C);
-
-  if (!base) {
-    return NULL;
-  }
-
-  for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) {
-    base_next = child_base->next;
-    for (parent = child_base->object->parent; parent && (parent != base->object);
-         parent = parent->parent) {
-      /* pass */
-    }
-    if (parent) {
-      base_next = outline_delete_hierarchy(C, reports, scene, child_base);
-    }
-  }
-
-  base_next = base->next;
-
-  Main *bmain = CTX_data_main(C);
-  if (base->object->id.tag & LIB_TAG_INDIRECT) {
-    BKE_reportf(reports,
-                RPT_WARNING,
-                "Cannot delete indirectly linked object '%s'",
-                base->object->id.name + 2);
-    return base_next;
-  }
-  else if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
-           ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
-    BKE_reportf(reports,
-                RPT_WARNING,
-                "Cannot delete object '%s' from scene '%s', indirectly used objects need at least "
-                "one user",
-                base->object->id.name + 2,
-                scene->id.name + 2);
-    return base_next;
-  }
-  ED_object_base_free_and_unlink(CTX_data_main(C), scene, base->object);
-  return base_next;
-}
-
-static void object_delete_hierarchy_cb(bContext *C,
-                                       ReportList *reports,
-                                       Scene *scene,
-                                       TreeElement *te,
-                                       TreeStoreElem *UNUSED(tsep),
-                                       TreeStoreElem *tselem,
-                                       void *UNUSED(user_data))
-{
-  ViewLayer *view_layer = CTX_data_view_layer(C);
-  Base *base = (Base *)te->directdata;
-  Object *obedit = CTX_data_edit_object(C);
-
-  if (!base) {
-    base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
-  }
-  if (base) {
-    /* Check also library later. */
-    for (; obedit && (obedit != base->object); obedit = obedit->parent) {
-      /* pass */
-    }
-    if (obedit == base->object) {
-      ED_object_editmode_exit(C, EM_FREEDATA);
-    }
-
-    outline_delete_hierarchy(C, reports, scene, base);
-  }
-
-  DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
-  WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-}
-
 static Base *outline_batch_delete_hierarchy(
     ReportList *reports, Main *bmain, ViewLayer *view_layer, Scene *scene, Base *base)
 {
@@ -1303,21 +1223,16 @@ static Base *outline_batch_delete_hierarchy(
   return base_next;
 }
 
-static void object_batch_delete_hierarchy_cb(bContext *C,
+static void object_batch_delete_hierarchy_fn(bContext *C,
                                              ReportList *reports,
                                              Scene *scene,
-                                             TreeElement *te,
-                                             TreeStoreElem *UNUSED(tsep),
-                                             TreeStoreElem *tselem,
-                                             void *UNUSED(user_data))
+                                             Object *ob)
 {
   ViewLayer *view_layer = CTX_data_view_layer(C);
-  Base *base = (Base *)te->directdata;
   Object *obedit = CTX_data_edit_object(C);
 
-  if (!base) {
-    base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
-  }
+  Base *base = BKE_view_layer_base_find(view_layer, ob);
+
   if (base) {
     /* Check also library later. */
     for (; obedit && (obedit != base->object); obedit = obedit->parent) {
@@ -1341,7 +1256,6 @@ enum {
   OL_OP_SELECT = 1,
   OL_OP_DESELECT,
   OL_OP_SELECT_HIERARCHY,
-  OL_OP_DELETE_HIERARCHY,
   OL_OP_REMAP,
   OL_OP_LOCALIZED, /* disabled, see below */
   OL_OP_TOGVIS,
@@ -1356,7 +1270,6 @@ static const EnumPropertyItem prop_object_op_types[] = {
     {OL_OP_SELECT, "SELECT", ICON_RESTRICT_SELECT_OFF, "Select", ""},
     {OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""},
     {OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""},
-    {OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""},
     {OL_OP_REMAP,
      "REMAP",
      0,
@@ -1370,7 +1283,6 @@ static const EnumPropertyItem prop_object_op_types[] = {
 
 static int outliner_object_operation_exec(bContext *C, wmOperator *op)
 {
-  struct wmMsgBus *mbus = CTX_wm_message_bus(C);
   Main *bmain = CTX_data_main(C);
   Scene *scene = CTX_data_scene(C);
   wmWindow *win = CTX_wm_window(C);
@@ -1411,43 +1323,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
     str = "Deselect Objects";
     selection_changed = true;
   }
-  else if (event == OL_OP_DELETE_HIERARCHY) {
-    ViewLayer *view_layer = CTX_data_view_layer(C);
-    const Base *basact_prev = BASACT(view_layer);
-
-    /* Keeping old 'safe and slow' code for a bit (new one enabled on 28/01/2019). */
-    if (G.debug_value == 666) {
-      outliner_do_object_operation_ex(
-          C, op->reports, scene, soops, &soops->tree, object_delete_hierarchy_cb, NULL, false);
-    }
-    else {
-      BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
-      outliner_do_object_operation_ex(C,
-                                      op->reports,
-                                      scene,
-                                      soops,
-                                      &soops->tree,
-                                      object_batch_delete_hierarchy_cb,
-                                      NULL,
-                                      false);
-
-      BKE_id_multi_tagged_delete(bmain);
-    }
-
-    /* XXX: See outliner_delete_exec comment below. */
-    outliner_cleanup_tree(soops);
-
-    DEG_relations_tag_update(bmain);
-    str = "Delete Object Hierarchy";
-    DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
-    WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-    if (basact_prev != BASACT(view_layer)) {
-      WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-      WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
-    }
-    selection_changed = true;
-  }
   else if (event == OL_OP_REMAP) {
     outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
     /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth trick
@@ -1511,22 +1386,38 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
 /** \name Delete Object/Collection Operator
  * \{ */
 
-static void outliner_objects_delete(
-    bContext *C, Scene *scene, SpaceOutliner *soops, ReportList *reports, ListBase *lb)
+typedef void (*OutlinerDeleteFunc)(bContext *C, ReportList *reports, Scene *scene, Object *ob);
+
+static void outliner_do_object_delete(bContext *C,
+                                      ReportList *reports,
+                                      Scene *scene,
+                                      GSet *objects_to_delete,
+                                      OutlinerDeleteFunc delete_fn)
 {
-  LISTBASE_FOREACH (TreeElement *, te, lb) {
-    TreeStoreElem *tselem = TREESTORE(te);
+  GSetIterator objects_to_delete_iter;
+  GSET_ITER (objects_to_delete_iter, objects_to_delete) {
+    Object *ob = (Object *)BLI_gsetIterator_getKey(&objects_to_delete_iter);
 
-    if (tselem->flag & TSE_SELECTED) {
-      if (tselem->type == 0 && te->idcode == ID_OB) {
-        outliner_object_delete(C, reports, scene, tselem);
-      }
-    }
+    delete_fn(C, reports, scene, ob);
+  }
+}
 
-    if (TSELEM_OPEN(tselem, soops)) {
-      outliner_objects_delete(C, scene, soops, reports, &te->subtree);
-    }
+static Tr

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list