From 6c573445dd346535adf261b9092a525471abdbb3 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Tue, 15 Oct 2024 12:28:44 +0500 Subject: [PATCH] More clever object selection for assigning aggregates #5560 Basically those two properties (Relating Whole and Related Part) are now showing only objects that are valid for the assigning an aggregate - https://i.imgur.com/bqQsXhG.png --- .../bonsai/bim/module/aggregate/prop.py | 62 +++++++++++++------ 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/aggregate/prop.py b/src/bonsai/bonsai/bim/module/aggregate/prop.py index b719d2eed0..ee6c4d38a2 100644 --- a/src/bonsai/bonsai/bim/module/aggregate/prop.py +++ b/src/bonsai/bonsai/bim/module/aggregate/prop.py @@ -17,6 +17,8 @@ # along with Bonsai. If not, see . import bpy +import ifcopenshell.util.element +import bonsai.tool as tool from bonsai.bim.prop import StrProperty, Attribute from bonsai.bim.module.spatial.data import SpatialData from bpy.types import PropertyGroup @@ -32,29 +34,51 @@ from bpy.props import ( ) -def update_relating_object(self, context): - def message(self, context): - self.layout.label(text="Please select a valid IFC Element") - - if self.relating_object: - self.related_object = None - if not self.relating_object.BIMObjectProperties.ifc_definition_id: - context.window_manager.popup_menu(message, title="Invalid Element Selected", icon="INFO") - self.relating_object = None +def can_aggregate(relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool: + if related_obj == relating_obj: + return False + # Just a quick way to ignore body representations. + if relating_obj.type != "EMPTY": + return False + if not tool.Aggregate.can_aggregate(relating_obj, related_obj): + return False + return True -def update_related_object(self, context): - def message(self, context): - self.layout.label(text="Please select a valid IFC Element") +def poll_relating_object(self: "BIMObjectAggregateProperties", relating_obj: bpy.types.Object) -> bool: + if (tool.Ifc.get_entity(relating_obj)) is None: + return False - if self.related_object: - self.relating_object = None - if not self.related_object.BIMObjectProperties.ifc_definition_id: - context.window_manager.popup_menu(message, title="Invalid Element Selected", icon="INFO") - self.related_object = None + for related_obj_ in tool.Blender.get_selected_objects(): + if not can_aggregate(relating_obj, related_obj_): + return False + return True + + +def poll_related_object(self: "BIMObjectAggregateProperties", related_obj: bpy.types.Object) -> bool: + if (element := tool.Ifc.get_entity(related_obj)) is None: + return False + + aggregate = ifcopenshell.util.element.get_aggregate(element) + if not aggregate: + return False + relating_obj = tool.Ifc.get_object(aggregate) + assert isinstance(relating_obj, bpy.types.Object) + + for related_obj_ in tool.Blender.get_selected_objects(): + if related_obj_ == related_obj: + return False + if not can_aggregate(relating_obj, related_obj_): + return False + return True class BIMObjectAggregateProperties(PropertyGroup): is_editing: BoolProperty(name="Is Editing") - relating_object: PointerProperty(name="Relating Whole", type=bpy.types.Object, update=update_relating_object) - related_object: PointerProperty(name="Related Part", type=bpy.types.Object, update=update_related_object) + relating_object: PointerProperty(name="Relating Whole", type=bpy.types.Object, poll=poll_relating_object) + related_object: PointerProperty( + name="Related Part", + description="Related Part, will be used to derive the Relating Object", + type=bpy.types.Object, + poll=poll_related_object, + )