Layers/Collections: Fix crash when deleting collection
authorDalai Felinto <dfelinto@gmail.com>
Tue, 2 Jan 2018 20:19:25 +0000 (18:19 -0200)
committerDalai Felinto <dfelinto@gmail.com>
Tue, 2 Jan 2018 20:19:26 +0000 (18:19 -0200)
If the collection to be deleted has a nested collection that is directly linked
to a view layer, we were getting a crash.

source/blender/blenkernel/intern/collection.c
tests/python/view_layer/CMakeLists.txt
tests/python/view_layer/test_scene_collection_delete.py [new file with mode: 0644]

index f6915cc2432da93b001d92849b2b73804ae3f376..e2b10de575cdb87f1355ebee6b6e4f91f36c1f9a 100644 (file)
@@ -188,6 +188,15 @@ bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
                return false;
        }
 
+       /* We need to do bottom up removal, otherwise we get a crash when we remove a collection that
+        * has one of its nested collections linked to a view layer. */
+       SceneCollection *scene_collection_nested = sc->scene_collections.first;
+       while (scene_collection_nested != NULL) {
+               SceneCollection *scene_collection_next = scene_collection_nested->next;
+               BKE_collection_remove(owner_id, scene_collection_nested);
+               scene_collection_nested = scene_collection_next;
+       }
+
        /* Unlink from the respective collection tree. */
        if (!collection_remlink(sc_master, sc)) {
                BLI_assert(false);
index 1c0648afead798fcc6e10430a7cc5861e4715932..eaaf25b38890e95026971fd4774605976ca870cf 100644 (file)
@@ -170,6 +170,7 @@ VIEW_LAYER_TEST(move_into_layer_collection_i)
 VIEW_LAYER_TEST(move_into_layer_collection_j)
 VIEW_LAYER_TEST(layer_linking)
 VIEW_LAYER_TEST(layer_syncing)
+VIEW_LAYER_TEST(scene_collection_delete)
 VIEW_LAYER_TEST(scene_copy_a)
 VIEW_LAYER_TEST(scene_copy_b)
 VIEW_LAYER_TEST(scene_copy_c)
diff --git a/tests/python/view_layer/test_scene_collection_delete.py b/tests/python/view_layer/test_scene_collection_delete.py
new file mode 100644 (file)
index 0000000..3f917e5
--- /dev/null
@@ -0,0 +1,54 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+from view_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(ViewLayerTesting):
+    def test_scene_collection_delete(self):
+        """
+        See if a scene collection can be properly deleted even
+        when linked
+        """
+        import bpy
+
+        # delete all initial objects
+        while bpy.data.objects:
+            bpy.data.objects.remove(bpy.data.objects[0])
+
+        # delete all initial collections
+        scene = bpy.context.scene
+        master_collection = scene.master_collection
+        while master_collection.collections:
+            master_collection.collections.remove(master_collection.collections[0])
+
+        collection_parent = master_collection.collections.new('parent')
+        collection_nested = collection_parent.collections.new('child linked')
+        bpy.context.view_layer.collections.link(collection_nested)
+        master_collection.collections.remove(collection_parent)
+
+        # Update depsgraph.
+        scene.update()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+    import sys
+
+    extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+    sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+    UnitTesting._extra_arguments = extra_arguments
+    unittest.main()