mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-29 00:03:17 +00:00
Applying multiple opening objects in bulk
Merry Christmas.
This commit is contained in:
@@ -415,7 +415,7 @@ class BimToolUI:
|
|||||||
row.label(text="", icon="EVENT_SHIFT")
|
row.label(text="", icon="EVENT_SHIFT")
|
||||||
row.label(text="", icon="EVENT_O")
|
row.label(text="", icon="EVENT_O")
|
||||||
|
|
||||||
if len(context.selected_objects) == 2:
|
if len(context.selected_objects) > 1:
|
||||||
row.operator("bim.add_opening", text="Apply Void")
|
row.operator("bim.add_opening", text="Apply Void")
|
||||||
else:
|
else:
|
||||||
row.operator("bim.add_potential_opening", text="Add Void")
|
row.operator("bim.add_potential_opening", text="Add Void")
|
||||||
|
|||||||
@@ -34,90 +34,97 @@ class AddOpening(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
if len(context.selected_objects) != 2:
|
if len(context.selected_objects) < 2:
|
||||||
cls.poll_message_set("Select two elements to add an opening")
|
cls.poll_message_set("Select openings and a target element")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = context.scene.BIMModelProperties
|
props = context.scene.BIMModelProperties
|
||||||
if len(context.selected_objects) != 2:
|
selected_objects = context.selected_objects
|
||||||
return {"FINISHED"}
|
target_object = selected_objects[0]
|
||||||
|
|
||||||
# The convention is that element1 is the element and element2 is the opening.
|
|
||||||
obj1, obj2 = context.selected_objects
|
|
||||||
element1 = tool.Ifc.get_entity(obj1)
|
|
||||||
element2 = tool.Ifc.get_entity(obj2)
|
|
||||||
|
|
||||||
if not element1 and not element2:
|
opening_objects = [obj for obj in selected_objects if obj != target_object]
|
||||||
return {"FINISHED"} # Both are not IFC objects.
|
|
||||||
|
|
||||||
if element1 and element2:
|
|
||||||
if element1.is_a("IfcOpeningElement") and element2.is_a("IfcOpeningElement"):
|
|
||||||
return {"FINISHED"} # You can't add an opening to another opening.
|
|
||||||
elif not element1.is_a("IfcOpeningElement") and not element2.is_a("IfcOpeningElement"):
|
|
||||||
if element1.is_a("IfcWindow") or element1.is_a("IfcDoor"): # Add a fill to an element.
|
|
||||||
obj1, obj2 = obj2, obj1
|
|
||||||
FilledOpeningGenerator().generate(obj2, obj1, target=obj2.matrix_world.translation)
|
|
||||||
return {"FINISHED"}
|
|
||||||
elif element1.is_a("IfcOpeningElement") or element2.is_a("IfcOpeningElement"):
|
|
||||||
if element1.is_a("IfcOpeningElement"): # Reassign an opening to another element.
|
|
||||||
obj1, obj2 = obj2, obj1
|
|
||||||
element1, element2 = element2, element1
|
|
||||||
|
|
||||||
if element2 and not element1:
|
for opening_obj in opening_objects:
|
||||||
obj1, obj2 = obj2, obj1
|
element1 = tool.Ifc.get_entity(target_object)
|
||||||
element1, element2 = element2, element1
|
obj1 = target_object
|
||||||
|
element2 = tool.Ifc.get_entity(opening_obj)
|
||||||
|
obj2 = opening_obj
|
||||||
|
|
||||||
if element1.is_a("IfcOpeningElement"):
|
if not element1 and not element2:
|
||||||
return {"FINISHED"} # You can't add an opening to another opening.
|
return {"FINISHED"} # Both are not IFC objects.
|
||||||
|
|
||||||
if tool.Ifc.is_moved(obj1):
|
if element1 and element2:
|
||||||
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj1)
|
if element1.is_a("IfcOpeningElement") and element2.is_a("IfcOpeningElement"):
|
||||||
|
self.report({'INFO'}, "You can't add an opening to another opening.")
|
||||||
|
continue
|
||||||
|
elif not element1.is_a("IfcOpeningElement") and not element2.is_a("IfcOpeningElement"):
|
||||||
|
if element1.is_a("IfcWindow") or element1.is_a("IfcDoor"): # Add a fill to an element.
|
||||||
|
obj1, obj2 = obj2, obj1
|
||||||
|
FilledOpeningGenerator().generate(obj2, obj1, target=obj2.matrix_world.translation)
|
||||||
|
continue
|
||||||
|
elif element1.is_a("IfcOpeningElement") or element2.is_a("IfcOpeningElement"):
|
||||||
|
if element1.is_a("IfcOpeningElement"): # Reassign an opening to another element.
|
||||||
|
obj1, obj2 = obj2, obj1
|
||||||
|
element1, element2 = element2, element1
|
||||||
|
|
||||||
has_visible_openings = False
|
if element2 and not element1:
|
||||||
for opening in [r.RelatedOpeningElement for r in element1.HasOpenings]:
|
obj1, obj2 = obj2, obj1
|
||||||
if tool.Ifc.get_object(opening):
|
element1, element2 = element2, element1
|
||||||
has_visible_openings = True
|
|
||||||
break
|
|
||||||
|
|
||||||
body_context = ifcopenshell.util.representation.get_context(IfcStore.get_file(), "Model", "Body")
|
if element1.is_a("IfcOpeningElement"):
|
||||||
if not element2:
|
self.report({'INFO'}, "You can't add an opening to another opening.")
|
||||||
element2 = blenderbim.core.root.assign_class(
|
continue
|
||||||
tool.Ifc,
|
|
||||||
tool.Collector,
|
|
||||||
tool.Root,
|
|
||||||
obj=obj2,
|
|
||||||
ifc_class="IfcOpeningElement",
|
|
||||||
should_add_representation=True,
|
|
||||||
context=body_context,
|
|
||||||
)
|
|
||||||
ifcopenshell.api.run("void.add_opening", tool.Ifc.get(), opening=element2, element=element1)
|
|
||||||
|
|
||||||
if tool.Ifc.is_moved(obj2):
|
if tool.Ifc.is_moved(obj1):
|
||||||
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj2)
|
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj1)
|
||||||
|
|
||||||
voided_objs = [obj1]
|
has_visible_openings = False
|
||||||
for subelement in ifcopenshell.util.element.get_decomposition(element1):
|
for opening in [r.RelatedOpeningElement for r in element1.HasOpenings]:
|
||||||
subobj = tool.Ifc.get_object(subelement)
|
if tool.Ifc.get_object(opening):
|
||||||
if subobj:
|
has_visible_openings = True
|
||||||
voided_objs.append(subobj)
|
break
|
||||||
|
|
||||||
for voided_obj in voided_objs:
|
body_context = ifcopenshell.util.representation.get_context(IfcStore.get_file(), "Model", "Body")
|
||||||
if voided_obj.data:
|
if not element2:
|
||||||
representation = tool.Ifc.get().by_id(voided_obj.data.BIMMeshProperties.ifc_definition_id)
|
element2 = blenderbim.core.root.assign_class(
|
||||||
blenderbim.core.geometry.switch_representation(
|
|
||||||
tool.Ifc,
|
tool.Ifc,
|
||||||
tool.Geometry,
|
tool.Collector,
|
||||||
obj=voided_obj,
|
tool.Root,
|
||||||
representation=representation,
|
obj=obj2,
|
||||||
should_reload=True,
|
ifc_class="IfcOpeningElement",
|
||||||
is_global=True,
|
should_add_representation=True,
|
||||||
should_sync_changes_first=False,
|
context=body_context,
|
||||||
)
|
)
|
||||||
|
ifcopenshell.api.run("void.add_opening", tool.Ifc.get(), opening=element2, element=element1)
|
||||||
|
|
||||||
if not has_visible_openings:
|
if tool.Ifc.is_moved(obj2):
|
||||||
tool.Ifc.unlink(obj=obj2)
|
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj2)
|
||||||
bpy.data.objects.remove(obj2)
|
|
||||||
|
voided_objs = [obj1]
|
||||||
|
for subelement in ifcopenshell.util.element.get_decomposition(element1):
|
||||||
|
subobj = tool.Ifc.get_object(subelement)
|
||||||
|
if subobj:
|
||||||
|
voided_objs.append(subobj)
|
||||||
|
|
||||||
|
for voided_obj in voided_objs:
|
||||||
|
if voided_obj.data:
|
||||||
|
representation = tool.Ifc.get().by_id(voided_obj.data.BIMMeshProperties.ifc_definition_id)
|
||||||
|
blenderbim.core.geometry.switch_representation(
|
||||||
|
tool.Ifc,
|
||||||
|
tool.Geometry,
|
||||||
|
obj=voided_obj,
|
||||||
|
representation=representation,
|
||||||
|
should_reload=True,
|
||||||
|
is_global=True,
|
||||||
|
should_sync_changes_first=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not has_visible_openings:
|
||||||
|
tool.Ifc.unlink(obj=obj2)
|
||||||
|
bpy.data.objects.remove(obj2)
|
||||||
|
|
||||||
context.view_layer.objects.active = obj1
|
context.view_layer.objects.active = obj1
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|||||||
Reference in New Issue
Block a user