Fix T63101: Blender crashes on adding any object to collection duplicated with added scene.

Issue was that (deep) duplication code of scene ended up leaving
children collections of new master one without any parent.

Note that even though I think that fix is OK for now, we should really
make 'deep' duplication of IDs part of the generic ID management code.
Am less and less happy with current handling of this, done half from
/editors code, half from some semi-specialized helpers from /blenkernel,
with sometimes nearly the same logic replicated several times for
slightly different needs, etc. Unfortunately this would not be a small
refactor, so it will have to wait...
This commit is contained in:
Bastien Montagne 2019-04-01 21:10:25 +02:00
parent b5382c92cf
commit 17c15798c3
Notes: blender-bot 2023-02-14 08:33:26 +01:00
Referenced by commit a813e259d6, Fix T63220: Cannot make object single user after Duplicate Scene with Link Object Data.
Referenced by issue #63101, Blender crashes on adding any object to collection duplicated with added scene
1 changed files with 19 additions and 6 deletions

View File

@ -1602,7 +1602,7 @@ static void libblock_relink_collection(Collection *collection)
}
}
static void single_object_users_collection(
static Collection *single_object_users_collection(
Main *bmain, Scene *scene, Collection *collection,
const int flag, const bool copy_collections, const bool is_master_collection)
{
@ -1623,9 +1623,24 @@ static void single_object_users_collection(
}
}
for (CollectionChild *child = collection->children.first; child; child = child->next) {
single_object_users_collection(bmain, scene, child->collection, flag, copy_collections, false);
/* Since master collection has already be duplicated as part of scene copy, we do not duplictae it here.
* However, this means its children need to be re-added manually here, otherwise their parent lists are empty
* (which will lead to crashes, see T63101). */
CollectionChild *child_next, *child = collection->children.first;
if (is_master_collection) {
BLI_listbase_clear(&collection->children);
}
for (; child; child = child_next) {
child_next = child->next;
Collection *collection_child_new = single_object_users_collection(
bmain, scene, child->collection, flag, copy_collections, false);
if (is_master_collection) {
BKE_collection_child_add(bmain, collection, collection_child_new);
MEM_freeN(child);
}
}
return collection;
}
/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
@ -1679,9 +1694,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
}
/* Making single user may affect other scenes if they share with current one some collections in their ViewLayer. */
for (Scene *sce = bmain->scenes.first; sce != NULL; sce = sce->id.next) {
BKE_scene_collection_sync(sce);
}
BKE_main_collection_sync(bmain);
}
/* not an especially efficient function, only added so the single user