mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Fix bug where syncing an object removed from the collection tree breaks.
This commit is contained in:
@@ -27,7 +27,7 @@ class BIM_PT_spatial(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
bl_parent_id = "BIM_PT_geometry_object"
|
||||
bl_parent_id = "BIM_PT_object_metadata"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
@@ -32,6 +32,9 @@ class Collector(blenderbim.core.tool.Collector):
|
||||
if element.is_a("IfcProject") or element.is_a("IfcGridAxis"):
|
||||
return
|
||||
|
||||
if not obj.users_collection:
|
||||
return
|
||||
|
||||
object_collection = None
|
||||
collection_collection = None
|
||||
|
||||
|
||||
@@ -5,41 +5,44 @@
|
||||
|
||||
# ############################################################################ #
|
||||
|
||||
# This allows us to write full integration tests that test how all systems work
|
||||
# as a whole. Whilst other tests focus on portions of the software, these tests
|
||||
# simulate what happens when a user opens Blender, presses buttons, and does
|
||||
# things.
|
||||
# Note: these tests are commented out as they are for learning purposes only. If
|
||||
# you want to run these tests, uncomment it :)
|
||||
|
||||
# These tests read like english. You can see all the possible sentences defined
|
||||
# in test_feature.py. Most of the time, there is already a sentence defined for
|
||||
# what you want to test.
|
||||
|
||||
@demo
|
||||
Feature: Demo
|
||||
|
||||
# Every operator has at least one scenario associated with it to test it.
|
||||
Scenario: Demonstrate hello world
|
||||
Given an empty IFC project
|
||||
When I press "bim.demonstrate_hello_world"
|
||||
# Blender doesn't have a way of testing that things are visible in the
|
||||
# interface and layout. We can check properties, and whats in the 3D
|
||||
# scenegraph, but not layout. There is no "DOM" like in web applications.
|
||||
# Too bad, we can't check the results, but we still write the test, that way
|
||||
# we can still check for errors like crashes or Python errors, like a "smoke
|
||||
# test".
|
||||
Then nothing happens
|
||||
|
||||
# This operator has two scenarios because there are two possibilities of a user
|
||||
# interacting with it.
|
||||
Scenario: Demonstrate rename project - with a name provided
|
||||
Given an empty IFC project
|
||||
When I set "scene.BIMDemoProperties.name" to "Foobar"
|
||||
And I press "bim.demonstrate_rename_project"
|
||||
Then the object "IfcProject/Foobar" is an "IfcProject"
|
||||
|
||||
# This is the other possible scenario for the rename project operator.
|
||||
Scenario: Demonstrate rename project - with no name
|
||||
Given an empty IFC project
|
||||
When I set "scene.BIMDemoProperties.name" to ""
|
||||
And I press "bim.demonstrate_rename_project"
|
||||
Then the object "IfcProject/My Project" is an "IfcProject"
|
||||
#|# This allows us to write full integration tests that test how all systems work
|
||||
#|# as a whole. Whilst other tests focus on portions of the software, these tests
|
||||
#|# simulate what happens when a user opens Blender, presses buttons, and does
|
||||
#|# things.
|
||||
#|
|
||||
#|# These tests read like english. You can see all the possible sentences defined
|
||||
#|# in test_feature.py. Most of the time, there is already a sentence defined for
|
||||
#|# what you want to test.
|
||||
#|
|
||||
#|@demo
|
||||
#|Feature: Demo
|
||||
#|
|
||||
#|# Every operator has at least one scenario associated with it to test it.
|
||||
#|Scenario: Demonstrate hello world
|
||||
#| Given an empty IFC project
|
||||
#| When I press "bim.demonstrate_hello_world"
|
||||
#| # Blender doesn't have a way of testing that things are visible in the
|
||||
#| # interface and layout. We can check properties, and whats in the 3D
|
||||
#| # scenegraph, but not layout. There is no "DOM" like in web applications.
|
||||
#| # Too bad, we can't check the results, but we still write the test, that way
|
||||
#| # we can still check for errors like crashes or Python errors, like a "smoke
|
||||
#| # test".
|
||||
#| Then nothing happens
|
||||
#|
|
||||
#|# This operator has two scenarios because there are two possibilities of a user
|
||||
#|# interacting with it.
|
||||
#|Scenario: Demonstrate rename project - with a name provided
|
||||
#| Given an empty IFC project
|
||||
#| When I set "scene.BIMDemoProperties.name" to "Foobar"
|
||||
#| And I press "bim.demonstrate_rename_project"
|
||||
#| Then the object "IfcProject/Foobar" is an "IfcProject"
|
||||
#|
|
||||
#|# This is the other possible scenario for the rename project operator.
|
||||
#|Scenario: Demonstrate rename project - with no name
|
||||
#| Given an empty IFC project
|
||||
#| When I set "scene.BIMDemoProperties.name" to ""
|
||||
#| And I press "bim.demonstrate_rename_project"
|
||||
#| Then the object "IfcProject/My Project" is an "IfcProject"
|
||||
|
||||
@@ -184,7 +184,7 @@ def the_object_name_is_placed_in_the_collection_collection(name, collection):
|
||||
def additionally_the_object_name_is_selected(name):
|
||||
obj = bpy.context.scene.objects.get(name)
|
||||
if not obj:
|
||||
assert False, 'The object "{name}" could not be selected'
|
||||
assert False, f'The object "{name}" could not be selected'
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
|
||||
# ############################################################################ #
|
||||
|
||||
# Note: these tests are commented out as they are for learning purposes only. If
|
||||
# you want to run these tests, uncomment it :)
|
||||
|
||||
"""
|
||||
|
||||
# Testing the core might seem strange if you haven't written this type of
|
||||
# abstract test before. You essentially want to test that things are called in
|
||||
# the right sequence. This seems almost like writing the code twice, like in
|
||||
@@ -82,3 +87,5 @@ class TestDemonstrateRenameProject:
|
||||
def test_showing_a_hint_if_no_name_provided(self, ifc, demo):
|
||||
demo.show_user_hints().should_be_called()
|
||||
subject.demonstrate_rename_project(ifc, demo, name=None)
|
||||
|
||||
"""
|
||||
|
||||
@@ -37,8 +37,8 @@ class TestImplementsTool(NewFile):
|
||||
class TestAddBrick(NewFile):
|
||||
def test_run(self):
|
||||
BrickStore.graph = brickschema.Graph()
|
||||
result = subject.add_brick("http://example.org/digitaltwin#", "https://brickschema.org/schema/Brick#Equipment")
|
||||
assert "http://example.org/digitaltwin#" in result
|
||||
result = subject.add_brick("https://example.org/digitaltwin#", "https://brickschema.org/schema/Brick#Equipment")
|
||||
assert "https://example.org/digitaltwin#" in result
|
||||
assert list(
|
||||
BrickStore.graph.triples(
|
||||
(URIRef(result), RDF.type, URIRef("https://brickschema.org/schema/Brick#Equipment"))
|
||||
@@ -250,7 +250,7 @@ class TestGetConvertableBrickElements(NewFile):
|
||||
class TestGetItemClass(NewFile):
|
||||
def test_run(self):
|
||||
TestLoadBrickFile().test_run()
|
||||
assert subject.get_item_class("http://example.org/digitaltwin#floor") == "Floor"
|
||||
assert subject.get_item_class("https://example.org/digitaltwin#floor") == "Floor"
|
||||
|
||||
|
||||
class TestGetLibraryBrickReference(NewFile):
|
||||
@@ -300,7 +300,7 @@ class TestImportBrickItems(NewFile):
|
||||
brick = bpy.context.scene.BIMBrickProperties.bricks[0]
|
||||
assert brick.name == "bldg"
|
||||
assert brick.label == "My Building"
|
||||
assert brick.uri == "http://example.org/digitaltwin#bldg"
|
||||
assert brick.uri == "https://example.org/digitaltwin#bldg"
|
||||
assert brick.total_items == 0
|
||||
|
||||
|
||||
|
||||
@@ -249,6 +249,14 @@ class TestAssign(NewFile):
|
||||
|
||||
|
||||
class TestSync(NewFile):
|
||||
def test_doing_nothing_if_the_object_has_no_collection(self):
|
||||
bpy.ops.bim.create_project()
|
||||
wall_obj = bpy.data.objects.new("Object", None)
|
||||
wall_element = tool.Ifc.get().createIfcWall()
|
||||
tool.Ifc.link(wall_element, wall_obj)
|
||||
subject.sync(wall_obj)
|
||||
assert not wall_obj.users_collection
|
||||
|
||||
def test_in_decomposition_mode_elements_can_be_in_spatial_containers(self):
|
||||
bpy.ops.bim.create_project()
|
||||
wall_obj = bpy.data.objects.new("Object", None)
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
|
||||
# ############################################################################ #
|
||||
|
||||
# Note: these tests are commented out as they are for learning purposes only. If
|
||||
# you want to run these tests, uncomment it :)
|
||||
|
||||
"""
|
||||
|
||||
# Because our tools have well defined, isolated functions, it means we can test
|
||||
# them very easily in isolation. Tests are fun, fast, and easy to setup!
|
||||
|
||||
@@ -85,3 +90,5 @@ class TestShowUserHints(NewFile):
|
||||
bpy.context.scene.BIMDemoProperties.show_hints = False
|
||||
subject.show_user_hints()
|
||||
assert bpy.context.scene.BIMDemoProperties.show_hints == True
|
||||
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user