diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2018-01-02 23:19:25 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2018-01-02 23:19:26 +0300 |
commit | 07de8eff774dbb312039133d38b28ade5ab8093d (patch) | |
tree | be0846f4746563b92181f0047be84a6cccabd727 | |
parent | 8300b5e53987b650c0edd03b892dee1f7da94a0d (diff) |
Layers/Collections: Fix crash when deleting collection
If the collection to be deleted has a nested collection that is directly linked
to a view layer, we were getting a crash.
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 9 | ||||
-rw-r--r-- | tests/python/view_layer/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/python/view_layer/test_scene_collection_delete.py | 54 |
3 files changed, 64 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index f6915cc2432..e2b10de575c 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -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); diff --git a/tests/python/view_layer/CMakeLists.txt b/tests/python/view_layer/CMakeLists.txt index 1c0648afead..eaaf25b3889 100644 --- a/tests/python/view_layer/CMakeLists.txt +++ b/tests/python/view_layer/CMakeLists.txt @@ -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 index 00000000000..3f917e5a35c --- /dev/null +++ b/tests/python/view_layer/test_scene_collection_delete.py @@ -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() |