From ef779e22592095a85920309e15e349a6be590056 Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Tue, 10 Mar 2026 21:08:01 -0500 Subject: [PATCH] - Shift+click or Shift+Ctrl+F duplicates and mirrors, keeping original - Show Mirror Geometry button for any active IFC element, not just flippable types Generated with the assistance of an AI coding tool. --- src/bonsai/bonsai/bim/module/model/product.py | 18 ++++++++++++++++-- .../bonsai/bim/module/model/workspace.py | 3 ++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/model/product.py b/src/bonsai/bonsai/bim/module/model/product.py index d2654486b8..b057e11074 100644 --- a/src/bonsai/bonsai/bim/module/model/product.py +++ b/src/bonsai/bonsai/bim/module/model/product.py @@ -684,7 +684,12 @@ class TrueMirrorElements(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.mirror_geometry" bl_label = "Mirror Element Geometry" bl_options = {"REGISTER", "UNDO"} - bl_description = "Mirrors the selected objects by mirroring their representation (or their types representation)" + bl_description = ( + "Mirrors the selected objects by inverting their representation. " + "If an active object is set, mirrors about its YZ plane; otherwise mirrors in place along the X axis. " + "Shift: duplicate and mirror, leaving the original in place" + ) + keep_original: bpy.props.BoolProperty(name="Keep Original", default=False) @classmethod def poll(cls, context): @@ -698,7 +703,16 @@ class TrueMirrorElements(bpy.types.Operator, tool.Ifc.Operator): if objs_to_mirror: mirror_ref = active_obj if mirror_ref is None: - objs_to_mirror = context.selected_objects + objs_to_mirror = list(context.selected_objects) + + if self.keep_original: + if mirror_ref: + mirror_ref.select_set(False) + bpy.ops.bim.override_object_duplicate_move(is_interactive=False) + objs_to_mirror = [obj for obj in context.selected_objects if obj != mirror_ref] + if mirror_ref: + mirror_ref.select_set(True) + for obj in objs_to_mirror: self.mirror_obj(context, obj, mirror_ref) return {"FINISHED"} diff --git a/src/bonsai/bonsai/bim/module/model/workspace.py b/src/bonsai/bonsai/bim/module/model/workspace.py index 2881516d5b..1bb04a9f07 100644 --- a/src/bonsai/bonsai/bim/module/model/workspace.py +++ b/src/bonsai/bonsai/bim/module/model/workspace.py @@ -1146,6 +1146,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator): self.x = self.props.x self.y = self.props.y self.z = self.props.z + self.shift = event.shift return self.execute(context) def draw(self, context): @@ -1304,7 +1305,7 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator): def hotkey_C_F(self): if not bpy.context.selected_objects: return - bpy.ops.bim.mirror_geometry() + bpy.ops.bim.mirror_geometry(keep_original=getattr(self, "shift", False)) def hotkey_S_G(self): obj = bpy.context.active_object