[Bf-blender-cvs] [a211937892f] blender2.8: Fix T57361: Creating a new scene with a full copy doesn't work.

Bastien Montagne noreply at git.blender.org
Wed Oct 24 14:48:20 CEST 2018


Commit: a211937892f55ac9510e0f9b625c1bd24cc12550
Author: Bastien Montagne
Date:   Wed Oct 24 14:45:18 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBa211937892f55ac9510e0f9b625c1bd24cc12550

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.

===================================================================

M	source/blender/editors/object/object_relations.c

===================================================================

diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 306cdc9472a..8464c49f374 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -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



More information about the Bf-blender-cvs mailing list