From 4c9697d26082131f83c444b095527566760492ae Mon Sep 17 00:00:00 2001 From: Gorgious56 Date: Fri, 3 Jan 2025 09:59:47 +0100 Subject: [PATCH] Consolidate logic for toggling display of openings --- src/bonsai/bonsai/bim/module/model/opening.py | 153 ++++++++++-------- .../bonsai/bim/module/model/workspace.py | 5 +- 2 files changed, 85 insertions(+), 73 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/model/opening.py b/src/bonsai/bonsai/bim/module/model/opening.py index 84e30bd9b9..6f4118f708 100644 --- a/src/bonsai/bonsai/bim/module/model/opening.py +++ b/src/bonsai/bonsai/bim/module/model/opening.py @@ -824,15 +824,8 @@ class ShowOpenings(Operator, tool.Ifc.Operator): def _execute(self, context): props = bpy.context.scene.BIMModelProperties - objs = context.selected_objects - - # add the obj's aggregate, as well, to objs - for obj in objs: - element = tool.Ifc.get_entity(obj) - if element and getattr(element, "Decomposes", None): - if element.Decomposes and (aggregate := element.Decomposes[0].RelatingObject): - aggregate_obj = tool.Ifc.get_object(aggregate) - objs.append(aggregate_obj) + objs = list(context.selected_objects) + self.update_with_aggregates(objs) for obj in objs: element = tool.Ifc.get_entity(obj) @@ -854,28 +847,30 @@ class ShowOpenings(Operator, tool.Ifc.Operator): DecorationsHandler.install(bpy.context) return {"FINISHED"} - -def get_openings_from_objects(objects): - to_delete = set() - for obj in objects: - element = tool.Ifc.get_entity(obj) - if not element or not hasattr(element, "HasOpenings"): - continue - if element.is_a("IfcOpeningElement"): - element = element.VoidsElements[0].RelatingBuildingElement - obj = tool.Ifc.get_object(element) - opening_elts = [r.RelatedOpeningElement for r in element.HasOpenings] - for opening_elt in opening_elts: - opening_obj = tool.Ifc.get_object(opening_elt) - if opening_obj: - to_delete.add((opening_elt, opening_obj)) - return to_delete + def update_with_aggregates(self, objs): + for obj in objs: + element = tool.Ifc.get_entity(obj) + if element and getattr(element, "Decomposes", None): + if element.Decomposes and (aggregate := element.Decomposes[0].RelatingObject): + aggregate_obj = tool.Ifc.get_object(aggregate) + objs.append(aggregate_obj) -def hide_openings(objects): - for opening, opening_obj in get_openings_from_objects(objects): - tool.Ifc.unlink(element=opening) - bpy.data.objects.remove(opening_obj) +def hide_openings(context, objects): + for opening_prop in context.scene.BIMModelProperties.openings: + opening_obj = opening_prop.obj + if opening_obj: + opening_element = tool.Ifc.get_entity(opening_obj) + if opening_element: + building_element = opening_element.VoidsElements[0].RelatingBuildingElement + if building_element: + building_obj = tool.Ifc.get_object(building_element) + if building_obj in objects: + tool.Ifc.unlink(element=opening_element) + bpy.data.objects.remove(opening_obj) + elif opening_obj in objects: # Hide openings that do not fill a BuildingElement + bpy.data.objects.remove(opening_obj) + tool.Model.clear_scene_openings() @@ -886,7 +881,7 @@ class HideAllOpenings(Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - hide_openings(context.scene.objects) + hide_openings(context, context.scene.objects[:]) return {"FINISHED"} @@ -897,7 +892,7 @@ class HideOpenings(Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - hide_openings(context.selected_objects) + hide_openings(context, context.selected_objects[:]) return {"FINISHED"} @@ -906,51 +901,69 @@ class EditOpenings(Operator, tool.Ifc.Operator): bl_label = "Edit" bl_description = "Edit Openings" bl_options = {"REGISTER", "UNDO"} + apply_all: bpy.props.BoolProperty(default=False) def _execute(self, context): - props = bpy.context.scene.BIMModelProperties - building_objs = set() - current_openings = bpy.data.collections.get("IfcOpeningElement").objects - - for obj in current_openings: - element = tool.Ifc.get_entity(obj) - if not element: - continue - if element.is_a("IfcOpeningElement"): - element = element.VoidsElements[0].RelatingBuildingElement - obj = tool.Ifc.get_object(element) - openings = [r.RelatedOpeningElement for r in element.HasOpenings] - for opening in openings: - opening_obj = tool.Ifc.get_object(opening) - building_objs.add(obj) - - similar_openings = bonsai.core.geometry.get_similar_openings(tool.Ifc, opening) - similar_openings_building_objs = bonsai.core.geometry.get_similar_openings_building_objs( - tool.Ifc, similar_openings - ) - building_objs.update(similar_openings_building_objs) - - if opening_obj: - if tool.Ifc.is_edited(opening_obj): - tool.Geometry.run_geometry_update_representation(obj=opening_obj) - bonsai.core.geometry.edit_similar_opening_placement(tool.Geometry, opening, similar_openings) - elif tool.Ifc.is_moved(opening_obj): - bonsai.core.geometry.edit_object_placement( - tool.Ifc, tool.Geometry, tool.Surveyor, obj=opening_obj - ) - bonsai.core.geometry.edit_similar_opening_placement(tool.Geometry, opening, similar_openings) - - building_objs.update( - self.get_all_building_objects_of_similar_openings(opening) - ) # NB this has nothing to do with clone similar_opening - tool.Ifc.unlink(element=opening) - if bpy.context.scene.BIMGeometryProperties.representation_obj == opening_obj: - bpy.context.scene.BIMGeometryProperties.representation_obj = None - bpy.data.objects.remove(opening_obj) + building_objs, opening_elements = self.get_buildings_and_openings(context.scene.BIMModelProperties) + for opening_element in opening_elements: + self.edit_opening(building_objs, opening_element) + tool.Model.clear_scene_openings() tool.Model.reload_body_representation(building_objs) return {"FINISHED"} + def get_buildings_and_openings(self, context, building_objs, opening_elements): + props = context.scene.BIMModelProperties + building_objs = set() + opening_elements = set() + if self.apply_all: + for opening_prop in props.openings: + opening_obj = opening_prop.obj + if opening_obj is None: + continue + opening_element = tool.Ifc.get_entity(opening_obj) + if opening_element is None: + bpy.data.objects.remove(opening_obj) + continue + opening_elements.add(opening_element) + building_element = opening_element.VoidsElements[0].RelatingBuildingElement + building_objs.add(tool.Ifc.get_object(building_element)) + else: + for obj in context.selected_objects: + building_element = tool.Ifc.get_entity(obj) + if not hasattr(building_element, "HasOpenings"): + continue + for relation in building_element.HasOpenings: + opening_element = relation.RelatedOpeningElement + if tool.Ifc.get_object(opening_element): + opening_elements.add(opening_element) + building_objs.add(obj) + + def edit_opening(self, building_objs, opening_element): + opening_obj = tool.Ifc.get_object(opening_element) + + similar_openings = bonsai.core.geometry.get_similar_openings(tool.Ifc, opening_element) + similar_openings_building_objs = bonsai.core.geometry.get_similar_openings_building_objs( + tool.Ifc, similar_openings + ) + building_objs.update(similar_openings_building_objs) + + if opening_obj: + if tool.Ifc.is_edited(opening_obj): + tool.Geometry.run_geometry_update_representation(obj=opening_obj) + bonsai.core.geometry.edit_similar_opening_placement(tool.Geometry, opening_element, similar_openings) + elif tool.Ifc.is_moved(opening_obj): + bonsai.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=opening_obj) + bonsai.core.geometry.edit_similar_opening_placement(tool.Geometry, opening_element, similar_openings) + + building_objs.update( + self.get_all_building_objects_of_similar_openings(opening_element) + ) # NB this has nothing to do with clone similar_opening + tool.Ifc.unlink(element=opening_element) + if bpy.context.scene.BIMGeometryProperties.representation_obj == opening_obj: + bpy.context.scene.BIMGeometryProperties.representation_obj = None + bpy.data.objects.remove(opening_obj) + def get_all_building_objects_of_similar_openings(self, opening): if not opening.is_a("IfcOpeningElement") or not opening.HasFillings: return [] diff --git a/src/bonsai/bonsai/bim/module/model/workspace.py b/src/bonsai/bonsai/bim/module/model/workspace.py index c1ebac4352..ad7f3224a5 100644 --- a/src/bonsai/bonsai/bim/module/model/workspace.py +++ b/src/bonsai/bonsai/bim/module/model/workspace.py @@ -1254,9 +1254,8 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator): bpy.ops.bim.enable_editing_extrusion_axis() def hotkey_A_O(self): - opening_collection = bpy.data.collections.get("IfcOpeningElement") - if opening_collection and opening_collection.objects: - bpy.ops.bim.edit_openings() + if bpy.context.scene.BIMModelProperties.openings: + bpy.ops.bim.edit_openings(apply_all=True) else: bpy.ops.bim.show_openings()