bim.clone_opening - always show in opening's ui

Otherwise it was hidden until user guesses that 2 objects need to be selected for it to appear.
Also, not sure if it's useful operator anymore - it seems just duplicating an opening and then adding it does the same thing.
This commit is contained in:
Andrej730
2025-01-16 17:13:46 +05:00
parent a383f60915
commit eef04fb91c
2 changed files with 41 additions and 25 deletions
+21 -12
View File
@@ -26,6 +26,7 @@ import numpy as np
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.api.geometry import ifcopenshell.api.geometry
import ifcopenshell.api.void
import ifcopenshell.geom import ifcopenshell.geom
import ifcopenshell.util.shape import ifcopenshell.util.shape
import ifcopenshell.util.element import ifcopenshell.util.element
@@ -1097,20 +1098,28 @@ class EditOpenings(Operator, tool.Ifc.Operator):
class CloneOpening(Operator, tool.Ifc.Operator): class CloneOpening(Operator, tool.Ifc.Operator):
bl_idname = "bim.clone_opening" bl_idname = "bim.clone_opening"
bl_label = "Clone Opening" bl_label = "Clone Opening"
bl_description = "Clone the selected Opening and assign to the selected Element" bl_description = "Clone the active Opening object and assign to the selected Element"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): @classmethod
objects = bpy.context.selected_objects def poll(cls, context):
if len(context.selected_objects) != 2:
cls.poll_message_set("Exactly 2 objects must be selected.")
return False
return True
for obj in objects: def _execute(self, context):
entity = tool.Ifc.get_entity(obj) # NOTE: Operator displayed in UI only with IfcOpeningElement being active.
if entity.is_a() == "IfcWall": ifc_file = tool.Ifc.get()
wall = entity objects = bpy.context.selected_objects
continue opening_obj = context.active_object
if entity.is_a() == "IfcOpeningElement": assert opening_obj
opening = entity opening = tool.Ifc.get_entity(opening_obj)
continue assert opening and opening.is_a("IfcOpeningElement")
voided_obj = next(o for o in objects if o != opening_obj)
voided_element = tool.Ifc.get_entity(voided_obj)
assert voided_element
opening_placement = opening.ObjectPlacement opening_placement = opening.ObjectPlacement
opening_representation = opening.Representation opening_representation = opening.Representation
@@ -1118,7 +1127,7 @@ class CloneOpening(Operator, tool.Ifc.Operator):
new_opening = ifcopenshell.api.run("root.create_entity", tool.Ifc.get(), ifc_class="IfcOpeningElement") new_opening = ifcopenshell.api.run("root.create_entity", tool.Ifc.get(), ifc_class="IfcOpeningElement")
new_opening.Representation = opening_representation new_opening.Representation = opening_representation
ifcopenshell.api.run("void.add_opening", tool.Ifc.get(), opening=new_opening, element=wall) ifcopenshell.api.void.add_opening(ifc_file, opening=new_opening, element=voided_element)
new_opening.ObjectPlacement = opening_placement new_opening.ObjectPlacement = opening_placement
return {"FINISHED"} return {"FINISHED"}
+20 -13
View File
@@ -217,8 +217,18 @@ class CableTool(BimTool):
def add_layout_hotkey_operator( def add_layout_hotkey_operator(
layout: bpy.types.UILayout, text: str, hotkey: str, description: Union[str, None], ui_context: str = "" layout: bpy.types.UILayout,
text: str,
hotkey: str,
description: Union[str, None],
ui_context: str = "",
*,
operator: str = "bim.hotkey",
) -> bpy.types.OperatorProperties: ) -> bpy.types.OperatorProperties:
"""
:param operator: Operator to display in UI. Displaying the specific operator in UI can be useful
to provide poll error messages.
"""
parts = hotkey.split("_") if hotkey else [] parts = hotkey.split("_") if hotkey else []
modifier, key = (parts + ["", ""])[:2] modifier, key = (parts + ["", ""])[:2]
@@ -227,7 +237,7 @@ def add_layout_hotkey_operator(
modifier_icon, modifier_str = MODIFIERS.get(modifier, ("NONE", "")) modifier_icon, modifier_str = MODIFIERS.get(modifier, ("NONE", ""))
row = layout.row(align=True) row = layout.row(align=True)
op = row.operator("bim.hotkey", text=op_text, icon_value=custom_icon) op = row.operator(operator, text=op_text, icon_value=custom_icon)
if ui_context != "TOOL_HEADER": if ui_context != "TOOL_HEADER":
row.label(text="", icon=modifier_icon) row.label(text="", icon=modifier_icon)
@@ -236,11 +246,12 @@ def add_layout_hotkey_operator(
hotkey_description = f"Hotkey: {modifier_str} {key}".strip() hotkey_description = f"Hotkey: {modifier_str} {key}".strip()
description = "\n\n".join(filter(None, [description, hotkey_description])) description = "\n\n".join(filter(None, [description, hotkey_description]))
op.hotkey = hotkey if operator == "bim.hotkey":
if ui_context == "TOOL_HEADER": op.hotkey = hotkey
op.description = text + "\n" + description if ui_context == "TOOL_HEADER":
else: op.description = text + "\n" + description
op.description = description else:
op.description = description
return op return op
@@ -804,12 +815,8 @@ class EditObjectUI:
op_text = "" if IS_TOOL_HEADER else "Edit Openings" op_text = "" if IS_TOOL_HEADER else "Edit Openings"
row.operator("bim.edit_openings", icon="CHECKMARK", text=op_text) row.operator("bim.edit_openings", icon="CHECKMARK", text=op_text)
row.operator("bim.hide_openings", icon="CANCEL", text="") row.operator("bim.hide_openings", icon="CANCEL", text="")
if len(context.selected_objects) == 2: row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row
row = cls.layout.row(align=True) add_layout_hotkey_operator(row, "Clone Opening", "S_L", "", ui_context, operator="bim.clone_opening")
row.label(text="", icon="EVENT_SHIFT")
row.label(text="", icon="EVENT_L")
row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row
row.operator("bim.clone_opening", text="Clone Opening")
@classmethod @classmethod
def draw_align(cls, context): def draw_align(cls, context):