Merge branch 'blender-v2.93-release'

This commit is contained in:
Bastien Montagne 2021-04-23 14:35:40 +02:00
commit 8adeac7c27
3 changed files with 41 additions and 23 deletions

@ -112,7 +112,9 @@ bool BKE_scene_collections_object_remove(struct Main *bmain,
struct Object *object, struct Object *object,
const bool free_us); const bool free_us);
void BKE_collections_object_remove_nulls(struct Main *bmain); void BKE_collections_object_remove_nulls(struct Main *bmain);
void BKE_collections_child_remove_nulls(struct Main *bmain, struct Collection *old_collection); void BKE_collections_child_remove_nulls(struct Main *bmain,
struct Collection *parent_collection,
struct Collection *child_collection);
/* Dependencies. */ /* Dependencies. */

@ -1302,41 +1302,50 @@ static void collection_missing_parents_remove(Collection *collection)
* *
* \note caller must ensure #BKE_main_collection_sync_remap() is called afterwards! * \note caller must ensure #BKE_main_collection_sync_remap() is called afterwards!
* *
* \param collection: may be \a NULL, * \param parent_collection: The collection owning the pointers that were remapped. May be \a NULL,
* in which case whole \a bmain database of collections is checked.
* \param child_collection: The collection that was remapped to another pointer. May be \a NULL,
* in which case whole \a bmain database of collections is checked. * in which case whole \a bmain database of collections is checked.
*/ */
void BKE_collections_child_remove_nulls(Main *bmain, Collection *collection) void BKE_collections_child_remove_nulls(Main *bmain,
Collection *parent_collection,
Collection *child_collection)
{ {
if (collection == NULL) { if (child_collection == NULL) {
if (parent_collection != NULL) {
collection_null_children_remove(parent_collection);
}
else {
/* We need to do the checks in two steps when more than one collection may be involved, /* We need to do the checks in two steps when more than one collection may be involved,
* otherwise we can miss some cases... * otherwise we can miss some cases...
* Also, master collections are not in bmain, so we also need to loop over scenes. * Also, master collections are not in bmain, so we also need to loop over scenes.
*/ */
for (collection = bmain->collections.first; collection != NULL; for (child_collection = bmain->collections.first; child_collection != NULL;
collection = collection->id.next) { child_collection = child_collection->id.next) {
collection_null_children_remove(collection); collection_null_children_remove(child_collection);
} }
for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
collection_null_children_remove(scene->master_collection); collection_null_children_remove(scene->master_collection);
} }
}
for (collection = bmain->collections.first; collection != NULL; for (child_collection = bmain->collections.first; child_collection != NULL;
collection = collection->id.next) { child_collection = child_collection->id.next) {
collection_missing_parents_remove(collection); collection_missing_parents_remove(child_collection);
} }
for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
collection_missing_parents_remove(scene->master_collection); collection_missing_parents_remove(scene->master_collection);
} }
} }
else { else {
for (CollectionParent *parent = collection->parents.first, *parent_next; parent; for (CollectionParent *parent = child_collection->parents.first, *parent_next; parent;
parent = parent_next) { parent = parent_next) {
parent_next = parent->next; parent_next = parent->next;
collection_null_children_remove(parent->collection); collection_null_children_remove(parent->collection);
if (!collection_find_child(parent->collection, collection)) { if (!collection_find_child(parent->collection, child_collection)) {
BLI_freelinkN(&collection->parents, parent); BLI_freelinkN(&child_collection->parents, parent);
} }
} }
} }

@ -303,6 +303,7 @@ static void libblock_remap_data_postprocess_object_update(Main *bmain,
/* Can be called with both old_collection and new_collection being NULL, /* Can be called with both old_collection and new_collection being NULL,
* this means we have to check whole Main database then. */ * this means we have to check whole Main database then. */
static void libblock_remap_data_postprocess_collection_update(Main *bmain, static void libblock_remap_data_postprocess_collection_update(Main *bmain,
Collection *owner_collection,
Collection *UNUSED(old_collection), Collection *UNUSED(old_collection),
Collection *new_collection) Collection *new_collection)
{ {
@ -311,7 +312,7 @@ static void libblock_remap_data_postprocess_collection_update(Main *bmain,
* and BKE_main_collection_sync_remap() does not tolerate any of those, so for now always check * and BKE_main_collection_sync_remap() does not tolerate any of those, so for now always check
* whole existing collections for NULL pointers. * whole existing collections for NULL pointers.
* I'd consider optimizing that whole collection remapping process a TODO for later. */ * I'd consider optimizing that whole collection remapping process a TODO for later. */
BKE_collections_child_remove_nulls(bmain, NULL /*old_collection*/); BKE_collections_child_remove_nulls(bmain, owner_collection, NULL /*old_collection*/);
} }
else { else {
/* Temp safe fix, but a "tad" brute force... We should probably be able to use parents from /* Temp safe fix, but a "tad" brute force... We should probably be able to use parents from
@ -523,7 +524,7 @@ void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const
break; break;
case ID_GR: case ID_GR:
libblock_remap_data_postprocess_collection_update( libblock_remap_data_postprocess_collection_update(
bmain, (Collection *)old_id, (Collection *)new_id); bmain, NULL, (Collection *)old_id, (Collection *)new_id);
break; break;
case ID_ME: case ID_ME:
case ID_CU: case ID_CU:
@ -628,6 +629,12 @@ void BKE_libblock_relink_ex(
switch (GS(id->name)) { switch (GS(id->name)) {
case ID_SCE: case ID_SCE:
case ID_GR: { case ID_GR: {
/* Note: here we know which collection we have affected, so at lest for NULL children
* detection we can only process that one.
* This is also a required fix in case `id` would not be in Main anymore, which can happen
* e.g. when called from `id_delete`. */
Collection *owner_collection = (GS(id->name) == ID_GR) ? (Collection *)id :
((Scene *)id)->master_collection;
if (old_id) { if (old_id) {
switch (GS(old_id->name)) { switch (GS(old_id->name)) {
case ID_OB: case ID_OB:
@ -636,7 +643,7 @@ void BKE_libblock_relink_ex(
break; break;
case ID_GR: case ID_GR:
libblock_remap_data_postprocess_collection_update( libblock_remap_data_postprocess_collection_update(
bmain, (Collection *)old_id, (Collection *)new_id); bmain, owner_collection, (Collection *)old_id, (Collection *)new_id);
break; break;
default: default:
break; break;
@ -644,7 +651,7 @@ void BKE_libblock_relink_ex(
} }
else { else {
/* No choice but to check whole objects/collections. */ /* No choice but to check whole objects/collections. */
libblock_remap_data_postprocess_collection_update(bmain, NULL, NULL); libblock_remap_data_postprocess_collection_update(bmain, owner_collection, NULL, NULL);
libblock_remap_data_postprocess_object_update(bmain, NULL, NULL); libblock_remap_data_postprocess_object_update(bmain, NULL, NULL);
} }
break; break;