Remove the code in `BKE_collection_move` to preserve LayerCollection flags.

This code was actually buggy (forcefully re-enabling excluded layers in some
cases).

Further more, it should not be needed now that layerCollection resync code
reuses as much as possible existing layers instead of deleting and
re-creating them all the time.

Differential Revision: https://developer.blender.org/D12016
This commit is contained in:
Bastien Montagne 2021-07-28 15:29:35 +02:00
parent b18d0244fc
commit 3db37075f6
1 changed files with 1 additions and 139 deletions

View File

@ -1809,125 +1809,6 @@ bool BKE_collection_objects_select(ViewLayer *view_layer, Collection *collection
/** \name Collection move (outliner drag & drop)
* \{ */
/* Local temporary storage for layer collection flags. */
typedef struct LayerCollectionFlag {
struct LayerCollectionFlag *next, *prev;
/** The view layer for the collections being moved, NULL for their children. */
ViewLayer *view_layer;
/** The original #LayerCollection's collection field. */
Collection *collection;
/** The original #LayerCollection's flag. */
int flag;
/** Corresponds to #LayerCollection->layer_collections. */
ListBase children;
} LayerCollectionFlag;
static void layer_collection_flags_store_recursive(const LayerCollection *layer_collection,
LayerCollectionFlag *flag)
{
flag->collection = layer_collection->collection;
flag->flag = layer_collection->flag;
LISTBASE_FOREACH (const LayerCollection *, child, &layer_collection->layer_collections) {
LayerCollectionFlag *child_flag = MEM_callocN(sizeof(LayerCollectionFlag), __func__);
BLI_addtail(&flag->children, child_flag);
layer_collection_flags_store_recursive(child, child_flag);
}
}
/**
* For every view layer, find the \a collection and save flags
* for it and its children in a temporary tree structure.
*/
static void layer_collection_flags_store(Main *bmain,
const Collection *collection,
ListBase *r_layer_level_list)
{
BLI_listbase_clear(r_layer_level_list);
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(
view_layer, collection);
/* Skip this view layer if the collection isn't found for some reason. */
if (layer_collection == NULL) {
continue;
}
/* Store the flags for the collection and all of its children. */
LayerCollectionFlag *flag = MEM_callocN(sizeof(LayerCollectionFlag), __func__);
flag->view_layer = view_layer;
/* Recursively save flags from collection children. */
layer_collection_flags_store_recursive(layer_collection, flag);
BLI_addtail(r_layer_level_list, flag);
}
}
}
static void layer_collection_flags_free_recursive(LayerCollectionFlag *flag)
{
LISTBASE_FOREACH (LayerCollectionFlag *, child, &flag->children) {
layer_collection_flags_free_recursive(child);
}
BLI_freelistN(&flag->children);
}
static void layer_collection_flags_restore_recursive(LayerCollection *layer_collection,
LayerCollectionFlag *flag)
{
/* There should be a flag struct for every layer collection. */
BLI_assert(BLI_listbase_count(&layer_collection->layer_collections) ==
BLI_listbase_count(&flag->children));
/* The flag and the layer collection should actually correspond. */
BLI_assert(flag->collection == layer_collection->collection);
LayerCollectionFlag *child_flag = flag->children.first;
LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) {
layer_collection_flags_restore_recursive(child, child_flag);
child_flag = child_flag->next;
}
/* We treat exclude as a special case.
*
* If in a different view layer the parent collection was disabled (e.g., background)
* and now we moved a new collection to be part of the background this collection should
* probably be disabled.
*
* NOTE: If we were to also keep the exclude flag we would need to re-sync the collections.
*/
layer_collection->flag = flag->flag | (layer_collection->flag & LAYER_COLLECTION_EXCLUDE);
}
/**
* Restore a collection's (and its children's) flags for each view layer
* from the structure built in #layer_collection_flags_store.
*/
static void layer_collection_flags_restore(ListBase *flags, const Collection *collection)
{
LISTBASE_FOREACH (LayerCollectionFlag *, flag, flags) {
ViewLayer *view_layer = flag->view_layer;
/* The top level of flag structs must have this set. */
BLI_assert(view_layer != NULL);
LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(
view_layer, collection);
/* Check that the collection is still in the scene (and therefore its view layers). In most
* cases this is true, but if we move a sub-collection shared by several scenes to a collection
* local to the target scene, it is effectively removed from every other scene's hierarchy
* (e.g. moving into current scene's master collection). Then the other scene's view layers
* won't contain a matching layer collection anymore, so there is nothing to restore to. */
if (layer_collection != NULL) {
layer_collection_flags_restore_recursive(layer_collection, flag);
}
layer_collection_flags_free_recursive(flag);
}
BLI_freelistN(flags);
}
bool BKE_collection_move(Main *bmain,
Collection *to_parent,
Collection *from_parent,
@ -1968,26 +1849,7 @@ bool BKE_collection_move(Main *bmain,
}
}
/* Make sure we store the flag of the layer collections before we remove and re-create them.
* Otherwise they will get lost and everything will be copied from the new parent collection.
* Don't use flag syncing when moving a collection to a different scene, as it no longer exists
* in the same view layers anyway. */
const bool do_flag_sync = BKE_scene_find_from_collection(bmain, to_parent) ==
BKE_scene_find_from_collection(bmain, collection);
ListBase layer_flags;
if (do_flag_sync) {
layer_collection_flags_store(bmain, collection, &layer_flags);
}
/* Create and remove layer collections. */
BKE_main_collection_sync(bmain);
/* Restore the original layer collection flags and free their temporary storage. */
if (do_flag_sync) {
layer_collection_flags_restore(&layer_flags, collection);
}
/* We need to sync it again to pass the correct flags to the collections objects. */
/* Update layer collections. */
BKE_main_collection_sync(bmain);
return true;