From 99b776b10eba6ae9c77bf93704e44110f6ebf8b5 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Thu, 9 Sep 2021 14:48:40 +1000 Subject: [PATCH] Deleting openings or voided elements now also remove openings. --- src/blenderbim/blenderbim/bim/__init__.py | 7 +++- src/blenderbim/blenderbim/bim/operator.py | 40 +++++++++++++++++-- .../test/bim/module/void/test_operator.py | 33 +++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py index 60da57ebf0..aa2536f4c6 100644 --- a/src/blenderbim/blenderbim/bim/__init__.py +++ b/src/blenderbim/blenderbim/bim/__init__.py @@ -1,4 +1,3 @@ - # BlenderBIM Add-on - OpenBIM Blender Add-on # Copyright (C) 2020, 2021 Dion Moult # @@ -87,6 +86,7 @@ classes = [ operator.SetViewportShadowFromSun, operator.LinkIfc, operator.SnapSpacesTogether, + operator.OverrideDelete, prop.StrProperty, prop.Attribute, prop.BIMProperties, @@ -105,16 +105,20 @@ classes = [ for mod in modules.values(): classes.extend(mod.classes) + def menu_func_export(self, context): self.layout.operator(operator.ExportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcjson)") + def menu_func_import(self, context): self.layout.operator(operator.ImportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcxml)") + def on_register(scene): handler.setDefaultProperties(scene) bpy.app.handlers.depsgraph_update_post.remove(on_register) + def register(): for cls in classes: bpy.utils.register_class(cls) @@ -141,6 +145,7 @@ def register(): for mod in modules.values(): mod.register() + def unregister(): for cls in reversed(classes): bpy.utils.unregister_class(cls) diff --git a/src/blenderbim/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py index 14cf470a42..66e27bc6e7 100644 --- a/src/blenderbim/blenderbim/bim/operator.py +++ b/src/blenderbim/blenderbim/bim/operator.py @@ -1,4 +1,3 @@ - # BlenderBIM Add-on - OpenBIM Blender Add-on # Copyright (C) 2020, 2021 Dion Moult # @@ -31,8 +30,8 @@ from . import import_ifc from . import schema from blenderbim.bim.ifc import IfcStore from bpy_extras.io_utils import ImportHelper -from mathutils import Vector, Matrix, Euler, geometry -from math import radians, degrees, atan, tan, cos, sin +from mathutils import Vector, Matrix, Euler +from math import radians class ExportIFC(bpy.types.Operator): @@ -726,3 +725,38 @@ class CopyAttributeToSelection(bpy.types.Operator): a.name() for a in self.schema.declaration_by_name(ifc_class).all_attributes() ] return self.applicable_attributes_cache[ifc_class] + + +class OverrideDelete(bpy.types.Operator): + bl_idname = "object.delete" + bl_label = "Delete" + + @classmethod + def poll(cls, context): + return context.active_object is not None + + def execute(self, context): + if IfcStore.get_file(): + return IfcStore.execute_ifc_operator(self, context) + for obj in context.selected_objects: + bpy.data.objects.remove(obj) + return {"FINISHED"} + + def invoke(self, context, event): + return context.window_manager.invoke_confirm(self, event) + + def _execute(self, context): + for obj in context.selected_objects: + if obj.BIMObjectProperties.ifc_definition_id: + element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id) + if element.is_a("IfcOpeningElement"): + self.delete_opening_element(element) + elif element.HasOpenings: + for rel in element.HasOpenings: + self.delete_opening_element(rel.RelatedOpeningElement) + bpy.data.objects.remove(obj) + return {"FINISHED"} + + def delete_opening_element(self, element): + obj = IfcStore.get_element(element.VoidsElements[0].RelatingBuildingElement.id()) + bpy.ops.bim.remove_opening(opening_id=element.id(), obj=obj.name) diff --git a/src/blenderbim/test/bim/module/void/test_operator.py b/src/blenderbim/test/bim/module/void/test_operator.py index cd2c1f955d..3e4997438a 100644 --- a/src/blenderbim/test/bim/module/void/test_operator.py +++ b/src/blenderbim/test/bim/module/void/test_operator.py @@ -75,3 +75,36 @@ class TestRemoveOpening(test.bim.bootstrap.NewFile): Then the object "IfcWall/Cube" has "8" vertices And the object "Cube" is not an IFC element """ + + @test.bim.bootstrap.scenario + def test_removing_an_opening_using_deletion(self): + return """ + Given an empty IFC project + When the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And I add a cube of size "1" at "1,0,0" + And the object "IfcWall/Cube" is selected + And additionally the object "Cube" is selected + And I press "bim.add_opening(opening='Cube', obj='IfcWall/Cube')" + And the object "IfcOpeningElement/Cube" is selected + And I delete the selected objects + Then the object "IfcWall/Cube" has no boolean difference by "IfcOpeningElement/Cube" + And the object "IfcWall/Cube" is not voided by "Cube" + """ + + @test.bim.bootstrap.scenario + def test_removing_an_opening_indirectly_by_deleting_its_building_element(self): + return """ + Given an empty IFC project + When the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And I add a cube of size "1" at "1,0,0" + And the object "IfcWall/Cube" is selected + And additionally the object "Cube" is selected + And I press "bim.add_opening(opening='Cube', obj='IfcWall/Cube')" + And the object "IfcWall/Cube" is selected + And I delete the selected objects + Then the object "Cube" is not an IFC element + """