From d7339600680e12a3982eb5d04832f53beb4f3755 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 9 Nov 2021 20:50:31 +1100 Subject: [PATCH] Fix #1856. Bug where you lost your existing container or aggregation when you added a new aggregation assembly. --- .../bim/module/aggregate/operator.py | 27 ++++++++++++ src/blenderbim/blenderbim/core/tool.py | 1 + .../test/bim/feature/aggregate.feature | 41 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/src/blenderbim/blenderbim/bim/module/aggregate/operator.py b/src/blenderbim/blenderbim/bim/module/aggregate/operator.py index aa69a7b3dd..1d1d57bed0 100644 --- a/src/blenderbim/blenderbim/bim/module/aggregate/operator.py +++ b/src/blenderbim/blenderbim/bim/module/aggregate/operator.py @@ -17,8 +17,11 @@ # along with BlenderBIM Add-on. If not, see . import bpy +import ifcopenshell +import ifcopenshell.util.element import blenderbim.tool as tool import blenderbim.core.aggregate as core +import blenderbim.core.spatial import blenderbim.bim.handler from blenderbim.bim.ifc import IfcStore @@ -92,10 +95,34 @@ class AddAggregate(bpy.types.Operator): def _execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object + element = tool.Ifc.get_entity(obj) + if not element: + return {"FINISHED"} + aggregate_collection = bpy.data.collections.new("IfcElementAssembly/Assembly") context.scene.collection.children.link(aggregate_collection) aggregate = bpy.data.objects.new("Assembly", None) aggregate_collection.objects.link(aggregate) bpy.ops.bim.assign_class(obj=aggregate.name, ifc_class="IfcElementAssembly") + + tool.Collector.sync(obj) + current_aggregate = ifcopenshell.util.element.get_aggregate(element) + current_container = ifcopenshell.util.element.get_container(element) + if current_aggregate: + core.assign_object( + tool.Ifc, + tool.Aggregate, + tool.Collector, + relating_obj=tool.Ifc.get_object(current_aggregate), + related_obj=aggregate, + ) + elif current_container: + blenderbim.core.spatial.assign_container( + tool.Ifc, + tool.Collector, + tool.Spatial, + structure_obj=tool.Ifc.get_object(current_container), + element_obj=aggregate, + ) core.assign_object(tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=aggregate, related_obj=obj) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index 1ab667844c..b2d20cedf2 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -58,6 +58,7 @@ class Brick: @interface class Collector: def assign(cls, obj): pass + def sync(cls, obj): pass @interface diff --git a/src/blenderbim/test/bim/feature/aggregate.feature b/src/blenderbim/test/bim/feature/aggregate.feature index f443af4cfd..3d0d15d1ba 100644 --- a/src/blenderbim/test/bim/feature/aggregate.feature +++ b/src/blenderbim/test/bim/feature/aggregate.feature @@ -38,3 +38,44 @@ Scenario: Unassign object Then the object "IfcSite/My Site" is in the collection "IfcSite/My Site" And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey" And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcProject/My Project" + +Scenario: Add aggregate + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is selected + When I press "bim.add_aggregate" + Then the object "IfcWall/Cube" is in the collection "IfcElementAssembly/Assembly" + And the object "IfcElementAssembly/Assembly" is in the collection "IfcElementAssembly/Assembly" + And the collection "IfcElementAssembly/Assembly" is in the collection "IfcProject/My Project" + +Scenario: Add aggregate - with the aggregate inheriting the existing spatial collection + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is placed in the collection "IfcBuildingStorey/My Storey" + And the object "IfcWall/Cube" is selected + When I press "bim.add_aggregate" + Then the object "IfcWall/Cube" is in the collection "IfcElementAssembly/Assembly" + And the object "IfcElementAssembly/Assembly" is in the collection "IfcElementAssembly/Assembly" + And the collection "IfcElementAssembly/Assembly" is in the collection "IfcBuildingStorey/My Storey" + +Scenario: Add aggregate - add a nested aggregate + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is placed in the collection "IfcBuildingStorey/My Storey" + And the object "IfcWall/Cube" is selected + When I press "bim.add_aggregate" + And the object "IfcWall/Cube" is selected + And I press "bim.add_aggregate" + Then the object "IfcWall/Cube" is in the collection "IfcElementAssembly/Assembly.001" + And the object "IfcElementAssembly/Assembly.001" is in the collection "IfcElementAssembly/Assembly.001" + And the collection "IfcElementAssembly/Assembly.001" is in the collection "IfcElementAssembly/Assembly" + And the collection "IfcElementAssembly/Assembly" is in the collection "IfcBuildingStorey/My Storey"