Applying multiple opening objects in bulk

Merry Christmas.
This commit is contained in:
Ryan Schultz
2023-12-25 10:33:49 -06:00
parent 0980075c88
commit 7df5ef6cd6
2 changed files with 74 additions and 67 deletions
@@ -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"}