From 91d3b8161eedffacb936b39d6a3c2a9a9cf1949f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Wed, 27 Nov 2024 19:36:43 -0300 Subject: [PATCH] Integrate aggregate mode toggle with Bonsai's TAB edit mode override. --- .../bonsai/bim/module/aggregate/__init__.py | 15 --- .../bonsai/bim/module/aggregate/operator.py | 104 ------------------ .../bonsai/bim/module/aggregate/prop.py | 17 ++- src/bonsai/bonsai/core/aggregate.py | 9 ++ src/bonsai/bonsai/tool/aggregate.py | 53 +++++++++ 5 files changed, 75 insertions(+), 123 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/aggregate/__init__.py b/src/bonsai/bonsai/bim/module/aggregate/__init__.py index 0f71a0aff4..99461553ec 100644 --- a/src/bonsai/bonsai/bim/module/aggregate/__init__.py +++ b/src/bonsai/bonsai/bim/module/aggregate/__init__.py @@ -30,9 +30,6 @@ classes = ( operator.BIM_OT_aggregate_unassign_object, operator.BIM_OT_break_link_to_other_aggregates, operator.BIM_OT_select_linked_aggregates, - operator.BIM_OT_mode_set_aggregate, - operator.BIM_OT_disable_mode_set_aggregate, - operator.BIM_OT_toggle_mode_set_aggregate, prop.BIMObjectAggregateProperties, prop.NotEditingObjects, prop.BIMAggregateProperties, @@ -40,24 +37,12 @@ classes = ( ui.BIM_PT_linked_aggregate, ) -addon_keymaps = [] def register(): bpy.types.Object.BIMObjectAggregateProperties = bpy.props.PointerProperty(type=prop.BIMObjectAggregateProperties) bpy.types.Scene.BIMAggregateProperties = bpy.props.PointerProperty(type=prop.BIMAggregateProperties) - wm = bpy.context.window_manager - if wm.keyconfigs.addon: - km = wm.keyconfigs.addon.keymaps.new(name="Object Mode", space_type="EMPTY") - kmi = km.keymap_items.new("bim.toggle_mode_set_aggregate", "TAB", "PRESS", ctrl=True) - addon_keymaps.append((km, kmi)) def unregister(): del bpy.types.Object.BIMObjectAggregateProperties del bpy.types.Scene.BIMAggregateProperties - wm = bpy.context.window_manager - kc = wm.keyconfigs.addon - if kc: - for km, kmi in addon_keymaps: - km.keymap_items.remove(kmi) - addon_keymaps.clear() diff --git a/src/bonsai/bonsai/bim/module/aggregate/operator.py b/src/bonsai/bonsai/bim/module/aggregate/operator.py index ec595f11d5..54865e6b7c 100644 --- a/src/bonsai/bonsai/bim/module/aggregate/operator.py +++ b/src/bonsai/bonsai/bim/module/aggregate/operator.py @@ -24,7 +24,6 @@ import bonsai.tool as tool import bonsai.core.aggregate as core import bonsai.core.spatial from bonsai.bim.ifc import IfcStore -from bonsai.bim.module.aggregate.decorator import AggregateModeDecorator class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator): @@ -371,106 +370,3 @@ class BIM_OT_select_linked_aggregates(bpy.types.Operator): obj.select_set(True) return {"FINISHED"} - -class BIM_OT_toggle_mode_set_aggregate(bpy.types.Operator, tool.Ifc.Operator): - bl_description = "Toggle Aggregate mode on and off" - bl_idname = "bim.toggle_mode_set_aggregate" - bl_label = "IFC Toggle Mode Set Aggregate" - bl_options = {"REGISTER", "UNDO"} - - def invoke(self, context, event): - return IfcStore.execute_ifc_operator(self, context, is_invoke=True) - - def _invoke(self, context, event): - if not tool.Ifc.get(): - return {"FINISHED"} - return self.execute(context) - - def _execute(self, context): - props = context.scene.BIMAggregateProperties - if props.in_aggregate_mode: - AggregateModeDecorator.uninstall() - BIM_OT_disable_mode_set_aggregate._execute(self, context) - else: - AggregateModeDecorator.install(context) - BIM_OT_mode_set_aggregate._execute(self, context) - - - - - -class BIM_OT_mode_set_aggregate(bpy.types.Operator, tool.Ifc.Operator): - bl_description = "Switch from Object to Aggregate Edit mode" - bl_idname = "bim.aggregate_mode_set_edit" - bl_label = "IFC Aggregate Mode Set Edit" - bl_options = {"REGISTER", "UNDO"} - - def invoke(self, context, event): - return IfcStore.execute_ifc_operator(self, context, is_invoke=True) - - def _invoke(self, context, event): - if not tool.Ifc.get(): - return {"FINISHED"} - return self.execute(context) - - def _execute(self, context): - active_object = context.active_object - props = context.scene.BIMAggregateProperties - if props.in_aggregate_mode: - BIM_OT_disable_mode_set_aggregate._execute(self, context) - - element = tool.Ifc.get_entity(active_object) - if not element: - return {"FINISHED"} - aggregate = ifcopenshell.util.element.get_aggregate(element) - parts = ifcopenshell.util.element.get_parts(element) - if not aggregate and not parts: - return {"FINISHED"} - if not parts: - parts = ifcopenshell.util.element.get_parts(aggregate) - if parts: - props.editing_aggregate = tool.Ifc.get_object(aggregate) if aggregate else tool.Ifc.get_object(element) - parts_objs = [tool.Ifc.get_object(part) for part in parts] - objs = [] - visible_objects = tool.Raycast.get_visible_objects(context) - for obj in visible_objects: - if obj.visible_in_viewport_get(context.space_data): - objs.append(obj.original) - for obj in objs: - if obj.original not in parts_objs: - if not obj.data: - continue - obj.original.display_type = "BOUNDS" - obj.hide_select = True - not_editing_obj = props.not_editing_objects.add() - not_editing_obj.obj = obj.original - - props.in_aggregate_mode = True - return {"FINISHED"} - -class BIM_OT_disable_mode_set_aggregate(bpy.types.Operator, tool.Ifc.Operator): - bl_description = "Switch from Aggregate to Object Edit mode" - bl_idname = "bim.disable_aggregate_mode_set_edit" - bl_label = "IFC Disable Aggregate Mode Set Edit" - bl_options = {"REGISTER", "UNDO"} - - def invoke(self, context, event): - return IfcStore.execute_ifc_operator(self, context, is_invoke=True) - - def _invoke(self, context, event): - if not tool.Ifc.get(): - return {"FINISHED"} - return self.execute(context) - - def _execute(self, context): - props = context.scene.BIMAggregateProperties - objs = [o.obj for o in props.not_editing_objects] - for obj in objs: - obj.original.display_type = "TEXTURED" - obj.hide_select = False - element = tool.Ifc.get_entity(obj) - if not element: - continue - - props.in_aggregate_mode = False - props.not_editing_objects.clear() diff --git a/src/bonsai/bonsai/bim/module/aggregate/prop.py b/src/bonsai/bonsai/bim/module/aggregate/prop.py index 637bc3cd2c..5ec8db5bd3 100644 --- a/src/bonsai/bonsai/bim/module/aggregate/prop.py +++ b/src/bonsai/bonsai/bim/module/aggregate/prop.py @@ -32,7 +32,7 @@ from bpy.props import ( FloatVectorProperty, CollectionProperty, ) -from bonsai.bim.module.aggregate.decorator import AggregateDecorator +from bonsai.bim.module.aggregate.decorator import AggregateDecorator, AggregateModeDecorator def can_aggregate(relating_obj: bpy.types.Object, related_obj: bpy.types.Object) -> bool: @@ -81,6 +81,13 @@ def update_aggregate_decorator(self, context): AggregateDecorator.uninstall() +def update_aggregate_mode_decorator(self, context): + if self.in_aggregate_mode: + AggregateModeDecorator.install(bpy.context) + else: + AggregateModeDecorator.uninstall() + + class BIMObjectAggregateProperties(PropertyGroup): is_editing: BoolProperty(name="Is Editing") relating_object: PointerProperty(name="Relating Whole", type=bpy.types.Object, poll=poll_relating_object) @@ -90,12 +97,14 @@ class BIMObjectAggregateProperties(PropertyGroup): type=bpy.types.Object, poll=poll_related_object, ) - + + class NotEditingObjects(bpy.types.PropertyGroup): obj: PointerProperty(type=bpy.types.Object) - + + class BIMAggregateProperties(PropertyGroup): - in_aggregate_mode: BoolProperty(name="In Edit Mode") + in_aggregate_mode: BoolProperty(name="In Edit Mode", update=update_aggregate_mode_decorator) editing_aggregate: PointerProperty(name="Editing Aggregate", type=bpy.types.Object) not_editing_objects: CollectionProperty(type=NotEditingObjects) aggregate_decorator: BoolProperty( diff --git a/src/bonsai/bonsai/core/aggregate.py b/src/bonsai/bonsai/core/aggregate.py index 073c50b6ed..30e2c14965 100644 --- a/src/bonsai/bonsai/core/aggregate.py +++ b/src/bonsai/bonsai/core/aggregate.py @@ -86,6 +86,15 @@ def add_part_to_object( assign_object(ifc, aggregator, collector, relating_obj=obj, related_obj=part_obj) blender.set_active_object(obj) +def enable_aggregate_mode(aggregator: tool.Aggregate, obj: bpy.types.Object,): + if aggregator.get_aggregate_mode(): + disable_aggregate_mode(aggregator) + + aggregator.enable_aggregate_mode(obj) + +def disable_aggregate_mode(aggregator: tool.Aggregate): + aggregator.disable_aggregate_mode() + class IncompatibleAggregateError(Exception): pass diff --git a/src/bonsai/bonsai/tool/aggregate.py b/src/bonsai/bonsai/tool/aggregate.py index fed5047758..1ff62b86b8 100644 --- a/src/bonsai/bonsai/tool/aggregate.py +++ b/src/bonsai/bonsai/tool/aggregate.py @@ -106,3 +106,56 @@ class Aggregate(bonsai.core.tool.Aggregate): if constraint: bpy.context.view_layer.objects.active = part bpy.ops.constraint.apply(constraint=constraint.name) + + @classmethod + def get_aggregate_mode(cls): + return bpy.context.scene.BIMAggregateProperties.in_aggregate_mode + + @classmethod + def enable_aggregate_mode(cls, active_object: bpy.types.Object): + context = bpy.context + props = context.scene.BIMAggregateProperties + + element = tool.Ifc.get_entity(active_object) + if not element: + return {"FINISHED"} + aggregate = ifcopenshell.util.element.get_aggregate(element) + parts = ifcopenshell.util.element.get_parts(element) + if not aggregate and not parts: + return {"FINISHED"} + if not parts: + parts = ifcopenshell.util.element.get_parts(aggregate) + if parts: + props.editing_aggregate = tool.Ifc.get_object(aggregate) if aggregate else tool.Ifc.get_object(element) + parts_objs = [tool.Ifc.get_object(part) for part in parts] + objs = [] + visible_objects = tool.Raycast.get_visible_objects(context) + for obj in visible_objects: + if obj.visible_in_viewport_get(context.space_data): + objs.append(obj.original) + for obj in objs: + if obj.original not in parts_objs: + if not obj.data and not tool.Ifc.get_entity(obj.original).is_a("IfcElementAssembly"): + continue + obj.original.display_type = "BOUNDS" + obj.hide_select = True + not_editing_obj = props.not_editing_objects.add() + not_editing_obj.obj = obj.original + + props.in_aggregate_mode = True + return {"FINISHED"} + + @classmethod + def disable_aggregate_mode(cls): + context = bpy.context + props = context.scene.BIMAggregateProperties + objs = [o.obj for o in props.not_editing_objects] + for obj in objs: + obj.original.display_type = "TEXTURED" + obj.hide_select = False + element = tool.Ifc.get_entity(obj) + if not element: + continue + + props.in_aggregate_mode = False + props.not_editing_objects.clear()