mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 06:39:13 +00:00
Deleting openings or voided elements now also remove openings.
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
#
|
#
|
||||||
@@ -87,6 +86,7 @@ classes = [
|
|||||||
operator.SetViewportShadowFromSun,
|
operator.SetViewportShadowFromSun,
|
||||||
operator.LinkIfc,
|
operator.LinkIfc,
|
||||||
operator.SnapSpacesTogether,
|
operator.SnapSpacesTogether,
|
||||||
|
operator.OverrideDelete,
|
||||||
prop.StrProperty,
|
prop.StrProperty,
|
||||||
prop.Attribute,
|
prop.Attribute,
|
||||||
prop.BIMProperties,
|
prop.BIMProperties,
|
||||||
@@ -105,16 +105,20 @@ classes = [
|
|||||||
for mod in modules.values():
|
for mod in modules.values():
|
||||||
classes.extend(mod.classes)
|
classes.extend(mod.classes)
|
||||||
|
|
||||||
|
|
||||||
def menu_func_export(self, context):
|
def menu_func_export(self, context):
|
||||||
self.layout.operator(operator.ExportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcjson)")
|
self.layout.operator(operator.ExportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcjson)")
|
||||||
|
|
||||||
|
|
||||||
def menu_func_import(self, context):
|
def menu_func_import(self, context):
|
||||||
self.layout.operator(operator.ImportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcxml)")
|
self.layout.operator(operator.ImportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcxml)")
|
||||||
|
|
||||||
|
|
||||||
def on_register(scene):
|
def on_register(scene):
|
||||||
handler.setDefaultProperties(scene)
|
handler.setDefaultProperties(scene)
|
||||||
bpy.app.handlers.depsgraph_update_post.remove(on_register)
|
bpy.app.handlers.depsgraph_update_post.remove(on_register)
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
@@ -141,6 +145,7 @@ def register():
|
|||||||
for mod in modules.values():
|
for mod in modules.values():
|
||||||
mod.register()
|
mod.register()
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
for cls in reversed(classes):
|
for cls in reversed(classes):
|
||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
#
|
#
|
||||||
@@ -31,8 +30,8 @@ from . import import_ifc
|
|||||||
from . import schema
|
from . import schema
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
from mathutils import Vector, Matrix, Euler, geometry
|
from mathutils import Vector, Matrix, Euler
|
||||||
from math import radians, degrees, atan, tan, cos, sin
|
from math import radians
|
||||||
|
|
||||||
|
|
||||||
class ExportIFC(bpy.types.Operator):
|
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()
|
a.name() for a in self.schema.declaration_by_name(ifc_class).all_attributes()
|
||||||
]
|
]
|
||||||
return self.applicable_attributes_cache[ifc_class]
|
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)
|
||||||
|
|||||||
@@ -75,3 +75,36 @@ class TestRemoveOpening(test.bim.bootstrap.NewFile):
|
|||||||
Then the object "IfcWall/Cube" has "8" vertices
|
Then the object "IfcWall/Cube" has "8" vertices
|
||||||
And the object "Cube" is not an IFC element
|
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
|
||||||
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user