[Bf-blender-cvs] [f887dc1f5c8] blender2.8: Fix T57372: Second full scene copy crashes on deletion.

Bastien Montagne noreply at git.blender.org
Mon Oct 29 11:43:38 CET 2018


Commit: f887dc1f5c8414f3a5ad6927730a3a74684ddf26
Author: Bastien Montagne
Date:   Mon Oct 29 11:42:38 2018 +0100
Branches: blender2.8
https://developer.blender.org/rBf887dc1f5c8414f3a5ad6927730a3a74684ddf26

Fix T57372: Second full scene copy crashes on deletion.

Hope this time we are done for good (root of the issue was that master
collections are not in bmain...).

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

M	source/blender/blenkernel/intern/collection.c
M	source/blender/blenkernel/intern/library_remap.c

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

diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index e6546d4454d..c85632b423b 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -650,28 +650,67 @@ void BKE_collections_object_remove_nulls(Main *bmain)
 	}
 }
 
-/*
- * Remove all NULL children from parent objects of changed old_collection.
+static void collection_null_children_remove(Collection *collection)
+{
+	for (CollectionChild *child = collection->children.first, *child_next = NULL; child; child = child_next) {
+		child_next = child->next;
+
+		if (child->collection == NULL) {
+			BLI_freelinkN(&collection->children, child);
+		}
+	}
+}
+
+static void collection_missing_parents_remove(Collection *collection)
+{
+	for (CollectionParent *parent = collection->parents.first, *parent_next; parent != NULL; parent = parent_next) {
+		parent_next = parent->next;
+
+		if (!collection_find_child(parent->collection, collection)) {
+			BLI_freelinkN(&collection->parents, parent);
+		}
+	}
+}
+
+/**
+ * Remove all NULL children from parent collections of changed \a collection.
  * This is used for library remapping, where these pointers have been set to NULL.
  * Otherwise this should never happen.
- * 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, in which case whole \a bmain database of collections is checked.
  */
-void BKE_collections_child_remove_nulls(Main *bmain, Collection *old_collection)
+void BKE_collections_child_remove_nulls(Main *bmain, Collection *collection)
 {
-	for (CollectionParent *cparent = old_collection->parents.first, *cnext; cparent; cparent = cnext) {
-		Collection *parent = cparent->collection;
-		cnext = cparent->next;
-
-		for (CollectionChild *child = parent->children.first, *child_next = NULL; child; child = child_next) {
-			child_next = child->next;
+	if (collection == NULL) {
+		/* We need to do the checks in two steps when more than one collection may be involved,
+		 * otherwise we can miss some cases...
+		 * Also, master collections are not in bmain, so we also need to loop over scenes.
+		 */
+		for (collection = bmain->collection.first; collection != NULL; collection = collection->id.next) {
+			collection_null_children_remove(collection);
+		}
+		for (Scene *scene = bmain->scene.first; scene != NULL; scene = scene->id.next) {
+			collection_null_children_remove(BKE_collection_master(scene));
+		}
 
-			if (child->collection == NULL) {
-				BLI_freelinkN(&parent->children, child);
-			}
+		for (collection = bmain->collection.first; collection != NULL; collection = collection->id.next) {
+			collection_missing_parents_remove(collection);
+		}
+		for (Scene *scene = bmain->scene.first; scene != NULL; scene = scene->id.next) {
+			collection_missing_parents_remove(BKE_collection_master(scene));
 		}
+	}
+	else {
+		for (CollectionParent *parent = collection->parents.first, *parent_next; parent; parent = parent_next) {
+			parent_next = parent->next;
+
+			collection_null_children_remove(parent->collection);
 
-		if (!collection_find_child(parent, old_collection)) {
-			BLI_freelinkN(&old_collection->parents, cparent);
+			if (!collection_find_child(parent->collection, collection)) {
+				BLI_freelinkN(&collection->parents, parent);
+			}
 		}
 	}
 }
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 114159debe3..8a011b55cf3 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -326,17 +326,7 @@ static void libblock_remap_data_postprocess_collection_update(
         Main *bmain, Collection *old_collection, Collection *new_collection)
 {
 	if (new_collection == NULL) {
-		/* In case we unlinked old_collection (new_collection is NULL), we need
-		 * to remove any collection children that have been set to NULL in the
-		 * because of pointer replacement. */
-		if (old_collection != NULL) {
-			BKE_collections_child_remove_nulls(bmain, old_collection);
-		}
-		else {
-			for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
-				BKE_collections_child_remove_nulls(bmain, collection);
-			}
-		}
+		BKE_collections_child_remove_nulls(bmain, old_collection);
 	}
 
 	BKE_main_collection_sync_remap(bmain);



More information about the Bf-blender-cvs mailing list