Integrate aggregate mode toggle with Bonsai's TAB edit mode override.

This commit is contained in:
Bruno Perdigão
2024-11-27 19:36:43 -03:00
committed by Bruno Perdigão
parent e9cc205ddd
commit 91d3b8161e
5 changed files with 75 additions and 123 deletions
@@ -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()
@@ -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()
+13 -4
View File
@@ -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(
+9
View File
@@ -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
+53
View File
@@ -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()