Fix T50714: Collections: Adding object to scene without an existing collection

This was causing blender to segfault.

We now add create a new collection and link to the layer before adding
the new object

(also included unittests, and requires updated lib/tests)
This commit is contained in:
Dalai Felinto
2017-02-23 12:35:14 +01:00
parent 8261a84ffb
commit 2f9a0dfe64
7 changed files with 164 additions and 1 deletions

View File

@@ -121,7 +121,14 @@ def object_data_add(context, obdata, operator=None, name=None):
"""
scene = context.scene
layer = context.render_layer
scene_collection = context.scene_collection
layer_collection = context.layer_collection
if not layer_collection:
# when there is no collection linked to this render_layer create one
scene_collection = scene.master_collection.collections.new("")
layer_collection = layer.collections.link(scene_collection)
else:
scene_collection = layer_collection.collection
bpy.ops.object.select_all(action='DESELECT')

View File

@@ -692,6 +692,14 @@ Object *BKE_object_add(
ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
lc = BKE_layer_collection_active(sl);
if (lc == NULL) {
BLI_assert(BLI_listbase_count_ex(&sl->layer_collections, 1) == 0);
/* when there is no collection linked to this SceneLayer, create one */
SceneCollection *sc = BKE_collection_add(scene, NULL, NULL);
lc = BKE_collection_link(sl, sc);
}
BKE_collection_object_add(scene, lc->scene_collection, ob);
base = BKE_scene_layer_base_find(sl, ob);

View File

@@ -67,6 +67,9 @@ RENDER_LAYER_TEST(operator_context)
RENDER_LAYER_TEST(object_add_cylinder)
RENDER_LAYER_TEST(object_add_empty)
RENDER_LAYER_TEST(object_add_torus)
RENDER_LAYER_TEST(object_add_no_collection_cylinder)
RENDER_LAYER_TEST(object_add_no_collection_empty)
RENDER_LAYER_TEST(object_add_no_collection_torus)
RENDER_LAYER_TEST(object_copy)
RENDER_LAYER_TEST(evaluation_visibility_a)
RENDER_LAYER_TEST(evaluation_visibility_b)

View File

@@ -309,3 +309,30 @@ class RenderLayerTesting(unittest.TestCase):
),
"Scene dump files differ")
def do_object_add_no_collection(self, add_mode):
"""
Test for adding objects when no collection
exists in render layer
"""
import bpy
# empty layer of collections
layer = bpy.context.render_layer
while layer.collections:
layer.collections.unlink(layer.collections[0])
# add new objects
if add_mode == 'EMPTY':
bpy.ops.object.add() # 'Empty'
elif add_mode == 'CYLINDER':
bpy.ops.mesh.primitive_cylinder_add() # 'Cylinder'
elif add_mode == 'TORUS':
bpy.ops.mesh.primitive_torus_add() # 'Torus'
self.assertEqual(len(layer.collections), 1, "New collection not created")
collection = layer.collections[0]
self.assertEqual(len(collection.objects), 1, "New collection is empty")

View File

@@ -0,0 +1,40 @@
# ./blender.bin --background -noaudio --python tests/python/render_layer/test_scene_copy.py -- --testdir="/data/lib/tests/"
# ############################################################
# Importing - Same For All Render Layer Tests
# ############################################################
import unittest
import os, sys
sys.path.append(os.path.dirname(__file__))
from render_layer_common import *
# ############################################################
# Testing
# ############################################################
class UnitTesting(RenderLayerTesting):
def test_object_add_cylinder(self):
"""
See if new objects are added to the correct collection
bpy.ops.mesh.primitive_cylinder_add()
"""
import os
self.do_object_add_no_collection('CYLINDER')
# ############################################################
# 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()

View File

@@ -0,0 +1,39 @@
# ./blender.bin --background -noaudio --python tests/python/render_layer/test_scene_copy.py -- --testdir="/data/lib/tests/"
# ############################################################
# Importing - Same For All Render Layer Tests
# ############################################################
import unittest
import os, sys
sys.path.append(os.path.dirname(__file__))
from render_layer_common import *
# ############################################################
# Testing
# ############################################################
class UnitTesting(RenderLayerTesting):
def test_syncing_object_add_empty(self):
"""
See if new objects are added to the correct collection
bpy.ops.object.add()
"""
self.do_object_add_no_collection('EMPTY')
# ############################################################
# 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()

View File

@@ -0,0 +1,39 @@
# ./blender.bin --background -noaudio --python tests/python/render_layer/test_scene_copy.py -- --testdir="/data/lib/tests/"
# ############################################################
# Importing - Same For All Render Layer Tests
# ############################################################
import unittest
import os, sys
sys.path.append(os.path.dirname(__file__))
from render_layer_common import *
# ############################################################
# Testing
# ############################################################
class UnitTesting(RenderLayerTesting):
def test_syncing_object_add_torus(self):
"""
See if new objects are added to the correct collection
bpy.ops.mesh.primitive_torus_add()
"""
self.do_object_add_no_collection('TORUS')
# ############################################################
# 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()