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>2020-07-01 18:13:57 +0300
committerJulian Eisel <julian@blender.org>2020-07-01 18:13:57 +0300
commit0829cebeb024095c268f190c34daa8ae9a5a224c (patch)
tree12ee5a4a1c2a32e12eff47c8eb9bb0ed217791c1 /source/blender/editors/space_outliner/outliner_tools.c
parentcfde6ebf450594faa57c4bfeaecff10fe512c91b (diff)
parent42be3964eb201180f6b0fa1ff6ce43b8c3845bc2 (diff)
Merge branch 'master' into asset-uuid--archivedasset-uuid--archived
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_tools.c')
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c216
1 files changed, 66 insertions, 150 deletions
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index b4c5dd8813a..51b919cd0dc 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"
@@ -573,8 +574,7 @@ static void merged_element_search_exec_fn(struct bContext *C, void *UNUSED(arg1)
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te = (TreeElement *)element;
- outliner_item_select(soops, te, false, false);
- outliner_item_do_activate_from_tree_element(C, te, te->store_elem, false, false);
+ outliner_item_select(C, soops, te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
ED_outliner_select_sync_from_outliner(C, soops);
}
@@ -664,12 +664,13 @@ static void object_select_hierarchy_cb(bContext *C,
Scene *UNUSED(scene),
TreeElement *te,
TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
+ TreeStoreElem *UNUSED(tselem),
void *UNUSED(user_data))
{
/* Don't extend because this toggles, which is nice for Ctrl-Click but not for a menu item.
* it's especially confusing when multiple items are selected since some toggle on/off. */
- outliner_item_do_activate_from_tree_element(C, te, tselem, false, true);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ outliner_item_select(C, soops, te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE | OL_ITEM_RECURSIVE);
}
static void object_deselect_cb(bContext *C,
@@ -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) {
@@ -862,7 +859,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;
@@ -1177,82 +1173,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)
{
@@ -1305,21 +1225,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) {
@@ -1343,7 +1258,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,
@@ -1358,7 +1272,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,
@@ -1372,7 +1285,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);
@@ -1413,43 +1325,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
@@ -1513,22 +1388,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 TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void *customdata)
+{
+ GSet *objects_to_delete = (GSet *)customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (outliner_is_collection_tree_element(te)) {
+ return TRAVERSE_CONTINUE;
}
+
+ if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
+
+ BLI_gset_add(objects_to_delete, tselem->id);
+
+ return TRAVERSE_CONTINUE;
}
static int outliner_delete_exec(bContext *C, wmOperator *op)
@@ -1537,12 +1428,32 @@ static int outliner_delete_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
-
ViewLayer *view_layer = CTX_data_view_layer(C);
const Base *basact_prev = BASACT(view_layer);
- outliner_collection_delete(C, bmain, scene, op->reports, false);
- outliner_objects_delete(C, scene, soops, op->reports, &soops->tree);
+ const bool delete_hierarchy = RNA_boolean_get(op->ptr, "hierarchy");
+
+ /* Get selected objects skipping duplicates to prevent deleting objects linked to multiple
+ * collections twice */
+ GSet *objects_to_delete = BLI_gset_ptr_new(__func__);
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, outliner_find_objects_to_delete, objects_to_delete);
+
+ if (delete_hierarchy) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ outliner_do_object_delete(
+ C, op->reports, scene, objects_to_delete, object_batch_delete_hierarchy_fn);
+
+ BKE_id_multi_tagged_delete(bmain);
+ }
+ else {
+ outliner_do_object_delete(C, op->reports, scene, objects_to_delete, outliner_object_delete_fn);
+ }
+
+ BLI_gset_free(objects_to_delete, NULL);
+
+ outliner_collection_delete(C, bmain, scene, op->reports, delete_hierarchy);
/* Tree management normally happens from draw_outliner(), but when
* you're clicking too fast on Delete object from context menu in
@@ -1579,6 +1490,11 @@ void OUTLINER_OT_delete(wmOperatorType *ot)
/* flags */
ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(
+ ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */