LibOverride/Outliner: Restrict further operations over liboverrides.

Restrict a lot deletion/moving around of liboverride objects and
collections in the Outliner.

While some of those operations may be valid in some specific cases, in
the vast majority of cases they would just end up breaking override
hierarchies/relationships.

Part of T95708/T95707.
This commit is contained in:
Bastien Montagne 2022-03-09 12:47:24 +01:00
parent 6a7066c2c1
commit 6be665926c
3 changed files with 61 additions and 18 deletions

View File

@ -9,6 +9,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_ID.h"
#include "DNA_collection_types.h"
#include "DNA_object_types.h"
@ -275,6 +276,12 @@ struct CollectionEditData {
Scene *scene;
SpaceOutliner *space_outliner;
GSet *collections_to_edit;
/* Whether the processed operation should be allowed on liboverride collections, or not. */
bool is_liboverride_allowed;
/* Whether the processed operation should be allowed on hierarchy roots of liboverride
* collections, or not. */
bool is_liboverride_hierarchy_root_allowed;
};
static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *customdata)
@ -287,27 +294,40 @@ static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *c
}
if (collection->flag & COLLECTION_IS_MASTER) {
/* skip - showing warning/error message might be misleading
* when deleting multiple collections, so just do nothing */
}
else {
/* Delete, duplicate and link don't edit children, those will come along
* with the parents. */
BLI_gset_add(data->collections_to_edit, collection);
return TRAVERSE_SKIP_CHILDS;
/* Skip - showing warning/error message might be misleading
* when deleting multiple collections, so just do nothing. */
return TRAVERSE_CONTINUE;
}
return TRAVERSE_CONTINUE;
if (ID_IS_OVERRIDE_LIBRARY_REAL(collection)) {
if (ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(collection)) {
if (!data->is_liboverride_hierarchy_root_allowed) {
return TRAVERSE_SKIP_CHILDS;
}
}
else {
if (!data->is_liboverride_allowed) {
return TRAVERSE_SKIP_CHILDS;
}
}
}
/* Delete, duplicate and link don't edit children, those will come along
* with the parents. */
BLI_gset_add(data->collections_to_edit, collection);
return TRAVERSE_SKIP_CHILDS;
}
void outliner_collection_delete(
bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool hierarchy)
bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool do_hierarchy)
{
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
data.is_liboverride_allowed = false;
data.is_liboverride_hierarchy_root_allowed = do_hierarchy;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
@ -356,14 +376,14 @@ void outliner_collection_delete(
}
if (!skip) {
BKE_collection_delete(bmain, collection, hierarchy);
BKE_collection_delete(bmain, collection, do_hierarchy);
}
else {
BKE_reportf(
reports,
RPT_WARNING,
"Cannot delete linked collection '%s', it is used by other linked scenes/collections",
collection->id.name + 2);
BKE_reportf(reports,
RPT_WARNING,
"Cannot delete collection '%s', it is either a linked one used by other "
"linked scenes/collections, or a library override one",
collection->id.name + 2);
}
}
}
@ -662,6 +682,8 @@ static int collection_link_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
data.is_liboverride_allowed = false; /* No linking of non-root collections. */
data.is_liboverride_hierarchy_root_allowed = true;
if ((ID_IS_LINKED(active_collection) || ID_IS_OVERRIDE_LIBRARY(active_collection)) ||
((active_collection->flag & COLLECTION_IS_MASTER) &&
@ -726,6 +748,8 @@ static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op))
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
data.is_liboverride_allowed = false; /* No instancing of non-root collections. */
data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
@ -825,6 +849,8 @@ static bool collections_view_layer_poll(bContext *C, bool clear, int flag)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
data.is_liboverride_allowed = true;
data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
bool result = false;
@ -891,6 +917,8 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
data.is_liboverride_allowed = true;
data.is_liboverride_hierarchy_root_allowed = true;
bool clear = strstr(op->idname, "clear") != nullptr;
int flag = strstr(op->idname, "holdout") ? LAYER_COLLECTION_HOLDOUT :
strstr(op->idname, "indirect_only") ? LAYER_COLLECTION_INDIRECT_ONLY :
@ -1029,6 +1057,8 @@ static int collection_isolate_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
data.is_liboverride_allowed = true;
data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
outliner_tree_traverse(space_outliner,
&space_outliner->tree,
@ -1126,6 +1156,8 @@ static int collection_visibility_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
data.is_liboverride_allowed = true;
data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
outliner_tree_traverse(space_outliner,
@ -1273,6 +1305,8 @@ static int collection_flag_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
data.is_liboverride_allowed = true;
data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
const bool has_layer_collection = space_outliner->outlinevis == SO_VIEW_LAYER;

View File

@ -545,7 +545,7 @@ void outliner_collection_delete(struct bContext *C,
struct Main *bmain,
struct Scene *scene,
struct ReportList *reports,
bool hierarchy);
bool do_hierarchy);
void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
void OUTLINER_OT_collection_duplicate_linked(struct wmOperatorType *ot);

View File

@ -1705,7 +1705,16 @@ static TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void
return TRAVERSE_SKIP_CHILDS;
}
BLI_gset_add(objects_to_delete, tselem->id);
ID *id = tselem->id;
if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
if (!ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(id)) {
/* Only allow deletion of liboverride objects if they are root overrides. */
return TRAVERSE_SKIP_CHILDS;
}
}
BLI_gset_add(objects_to_delete, id);
return TRAVERSE_CONTINUE;
}