Fix T57361: Creating a new scene with a full copy doesn't work.
BKE_scene_copy() & co. were pretty much doing nothing right... Was a tough fight, but at least now they should behave a tad better (and reported issue is fixed). Proper fix is to fully rewrite that PoS, it was already a mess without collections, now it's even hairier to handle properly, we need to use modern new ID handling API for that (and maybe extend it a bit as needed). But way too late to do that in 2.80.
This commit is contained in:
parent
91c6beb28a
commit
a211937892
Notes:
blender-bot
2023-02-14 05:09:28 +01:00
Referenced by issue #57373, NLA tracks created by script do not animate. Referenced by issue #57361, Creating a new scene with a full copy doesn't work ( objects are instanced )
|
@ -1626,64 +1626,56 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
|
|||
|
||||
/**************************** Make Single User ********************************/
|
||||
|
||||
static Object *single_object_users_object(Main *bmain, Object *ob)
|
||||
{
|
||||
/* base gets copy of object */
|
||||
Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
|
||||
|
||||
|
||||
id_us_plus(&obn->id);
|
||||
id_us_min(&ob->id);
|
||||
return obn;
|
||||
}
|
||||
|
||||
static void libblock_relink_collection(Collection *collection)
|
||||
{
|
||||
for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
|
||||
BKE_libblock_relink_to_newid(&cob->ob->id);
|
||||
}
|
||||
BKE_libblock_relink_to_newid(&collection->id);
|
||||
|
||||
for (CollectionChild *child = collection->children.first; child; child = child->next) {
|
||||
libblock_relink_collection(child->collection);
|
||||
}
|
||||
}
|
||||
|
||||
static void single_object_users_collection(Main *bmain, Scene *scene, Collection *collection, const int flag, const bool copy_collections)
|
||||
static void single_object_users_collection(
|
||||
Main *bmain, Scene *scene, Collection *collection,
|
||||
const int flag, const bool copy_collections, const bool is_master_collection)
|
||||
{
|
||||
/* Generate new copies for objects in given collection and all its children,
|
||||
* and optionnaly also copy collections themselves. */
|
||||
if (copy_collections && !is_master_collection) {
|
||||
collection = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
|
||||
}
|
||||
|
||||
/* We do not remap to new objects here, this is done in separate step. */
|
||||
for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
|
||||
Object *ob = cob->ob;
|
||||
/* an object may be in more than one collection */
|
||||
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
|
||||
if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
|
||||
cob->ob = single_object_users_object(bmain, cob->ob);
|
||||
ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (CollectionChild *child = collection->children.first; child; child = child->next) {
|
||||
single_object_users_collection(bmain, scene, child->collection, flag, copy_collections);
|
||||
single_object_users_collection(bmain, scene, child->collection, flag, copy_collections, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
|
||||
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
|
||||
{
|
||||
Collection *collection, *collectionn;
|
||||
|
||||
/* duplicate all the objects of the scene */
|
||||
/* duplicate all the objects of the scene (and matching collections, if required). */
|
||||
Collection *master_collection = BKE_collection_master(scene);
|
||||
single_object_users_collection(bmain, scene, master_collection, flag, copy_collections);
|
||||
|
||||
/* loop over ViewLayers and assign the pointers accordingly */
|
||||
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
|
||||
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
|
||||
ID_NEW_REMAP(base->object);
|
||||
}
|
||||
}
|
||||
single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
|
||||
|
||||
/* duplicate collections that consist entirely of duplicated objects */
|
||||
for (collection = bmain->collection.first; collection; collection = collection->id.next) {
|
||||
if (copy_collections) {
|
||||
/* XXX I guess that was designed for calls from 'make single user' operator... But since copy_collection is
|
||||
* always false then, was not doing anything. And that kind of behavior should be added at operator level,
|
||||
* not in a utility function also used by rather different code... */
|
||||
#if 0
|
||||
if (copy_collections) {
|
||||
Collection *collection, *collectionn;
|
||||
for (collection = bmain->collection.first; collection; collection = collection->id.next) {
|
||||
bool all_duplicated = true;
|
||||
bool any_duplicated = false;
|
||||
|
||||
|
@ -1705,6 +1697,10 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Collection and object pointers in collections */
|
||||
libblock_relink_collection(master_collection);
|
||||
|
||||
/* collection pointers in scene */
|
||||
BKE_scene_groups_relink(scene);
|
||||
|
@ -1713,8 +1709,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
|
|||
ID_NEW_REMAP(scene->camera);
|
||||
if (v3d) ID_NEW_REMAP(v3d->camera);
|
||||
|
||||
/* object and collection pointers */
|
||||
libblock_relink_collection(master_collection);
|
||||
BKE_scene_collection_sync(scene);
|
||||
}
|
||||
|
||||
/* not an especially efficient function, only added so the single user
|
||||
|
|
Loading…
Reference in New Issue