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:
@@ -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')
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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")
|
||||
|
||||
|
@@ -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()
|
@@ -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()
|
@@ -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()
|
Reference in New Issue
Block a user