mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 06:21:40 +00:00
Reuse tool.Blender.add_layout_hotkey_operator
Now all tools are using a general method and it should be easier to maintain the consistency between the tools. Fixes #6238. ping @trhyder just in case
This commit is contained in:
@@ -23,7 +23,7 @@ import bonsai.bim.module.type.prop as type_prop
|
|||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
from bpy.types import WorkSpaceTool
|
from bpy.types import WorkSpaceTool
|
||||||
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData
|
from bonsai.bim.module.model.data import AuthoringData, RailingData, RoofData
|
||||||
from typing import Union
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
def load_custom_icons():
|
def load_custom_icons():
|
||||||
@@ -330,29 +330,7 @@ def add_header_apply_button(layout, text, apply_operator, cancel_operator, ui_co
|
|||||||
row.label(text="Tools")
|
row.label(text="Tools")
|
||||||
|
|
||||||
|
|
||||||
def add_layout_hotkey_operator(
|
add_layout_hotkey_operator = partial(tool.Blender.add_layout_hotkey_operator, tool_name="cad", module_name=__name__)
|
||||||
layout: bpy.types.UILayout, text: str, hotkey: str, description: Union[str, None], ui_context: str = ""
|
|
||||||
) -> bpy.types.OperatorProperties:
|
|
||||||
parts = hotkey.split("_")
|
|
||||||
modifier, key = parts
|
|
||||||
op_text = "" if ui_context == "TOOL_HEADER" else text
|
|
||||||
custom_icon = custom_icon_previews.get(text.upper().replace(" ", "_"), custom_icon_previews["IFC"]).icon_id
|
|
||||||
modifier_icon, modifier_str = tool.Blender.KEY_MODIFIERS.get(modifier, ("NONE", ""))
|
|
||||||
|
|
||||||
row = layout if ui_context == "TOOL_HEADER" else layout.row(align=True)
|
|
||||||
op = row.operator("bim.cad_hotkey", text=op_text, icon_value=custom_icon)
|
|
||||||
|
|
||||||
if ui_context != "TOOL_HEADER" and len(parts) == 2:
|
|
||||||
layout = layout.row(align=True) # Create a new line for hotkey display
|
|
||||||
layout.label(text="", icon=modifier_icon)
|
|
||||||
layout.label(text="", icon=f"EVENT_{key}")
|
|
||||||
|
|
||||||
hotkey_description = f"Hotkey: {modifier_str} {key}"
|
|
||||||
description = "\n\n".join(filter(None, [hotkey_description if description else ""]))
|
|
||||||
op.hotkey = hotkey
|
|
||||||
op.description = description or hotkey_description
|
|
||||||
|
|
||||||
return op
|
|
||||||
|
|
||||||
|
|
||||||
custom_icon_previews = None
|
custom_icon_previews = None
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import bonsai.tool as tool
|
|||||||
from bonsai.bim.helper import prop_with_search
|
from bonsai.bim.helper import prop_with_search
|
||||||
from bonsai.bim.module.model.data import AuthoringData
|
from bonsai.bim.module.model.data import AuthoringData
|
||||||
from bpy.types import WorkSpaceTool
|
from bpy.types import WorkSpaceTool
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
class CoveringTool(WorkSpaceTool):
|
class CoveringTool(WorkSpaceTool):
|
||||||
@@ -45,9 +46,7 @@ class CoveringTool(WorkSpaceTool):
|
|||||||
CoveringToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
|
CoveringToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
|
||||||
|
|
||||||
|
|
||||||
def add_layout_hotkey(layout: bpy.types.UILayout, text: str, hotkey: str, description: str) -> None:
|
add_layout_hotkey = partial(tool.Blender.add_layout_hotkey_operator, tool_name="covering", module_name=__name__)
|
||||||
args = ("covering", layout, text, hotkey, description)
|
|
||||||
tool.Blender.add_layout_hotkey_operator(*args)
|
|
||||||
|
|
||||||
|
|
||||||
class CoveringToolUI:
|
class CoveringToolUI:
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import ifcopenshell.util.representation
|
|||||||
from bonsai.bim.module.drawing.data import DecoratorData, AnnotationData
|
from bonsai.bim.module.drawing.data import DecoratorData, AnnotationData
|
||||||
from bonsai.bim.helper import prop_with_search
|
from bonsai.bim.helper import prop_with_search
|
||||||
from bpy.types import WorkSpaceTool
|
from bpy.types import WorkSpaceTool
|
||||||
from typing import Union
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
class LaunchAnnotationTypeManager(bpy.types.Operator):
|
class LaunchAnnotationTypeManager(bpy.types.Operator):
|
||||||
@@ -135,23 +135,9 @@ class AnnotationTool(WorkSpaceTool):
|
|||||||
AnnotationToolUI.draw(context, layout)
|
AnnotationToolUI.draw(context, layout)
|
||||||
|
|
||||||
|
|
||||||
def add_layout_hotkey_operator(
|
add_layout_hotkey_operator = partial(
|
||||||
layout: bpy.types.UILayout, text: str, hotkey: str, description: Union[str, None]
|
tool.Blender.add_layout_hotkey_operator, tool_name="annotation", module_name=__name__
|
||||||
) -> tuple[bpy.types.OperatorProperties, bpy.types.UILayout]:
|
)
|
||||||
modifiers = {
|
|
||||||
"A": "EVENT_ALT",
|
|
||||||
"S": "EVENT_SHIFT",
|
|
||||||
}
|
|
||||||
modifier, key = hotkey.split("_")
|
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.label(text="", icon=modifiers[modifier])
|
|
||||||
row.label(text="", icon=f"EVENT_{key}")
|
|
||||||
|
|
||||||
op = row.operator("bim.annotation_hotkey", text=text)
|
|
||||||
op.hotkey = hotkey
|
|
||||||
op.description = description
|
|
||||||
return op, row
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: move to operator
|
# TODO: move to operator
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from bonsai.bim.module.model.data import AuthoringData, ItemData
|
|||||||
from bonsai.bim.module.system.data import PortData
|
from bonsai.bim.module.system.data import PortData
|
||||||
from bonsai.bim.module.model.prop import get_ifc_class
|
from bonsai.bim.module.model.prop import get_ifc_class
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
def load_custom_icons():
|
def load_custom_icons():
|
||||||
@@ -365,43 +366,7 @@ class CableTool(BimTool):
|
|||||||
ifc_element_type = "IfcCableSegmentType"
|
ifc_element_type = "IfcCableSegmentType"
|
||||||
|
|
||||||
|
|
||||||
def add_layout_hotkey_operator(
|
add_layout_hotkey_operator = partial(tool.Blender.add_layout_hotkey_operator, tool_name="bim", module_name=__name__)
|
||||||
layout: bpy.types.UILayout,
|
|
||||||
text: str,
|
|
||||||
hotkey: str,
|
|
||||||
description: Union[str, None],
|
|
||||||
ui_context: str = "",
|
|
||||||
*,
|
|
||||||
operator: str = "bim.hotkey",
|
|
||||||
) -> 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 []
|
|
||||||
modifier, key = (parts + ["", ""])[:2]
|
|
||||||
|
|
||||||
op_text = "" if ui_context == "TOOL_HEADER" else text
|
|
||||||
custom_icon = custom_icon_previews.get(text.upper().replace(" ", "_"), custom_icon_previews["IFC"]).icon_id
|
|
||||||
modifier_icon, modifier_str = tool.Blender.KEY_MODIFIERS.get(modifier, ("NONE", ""))
|
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
op = row.operator(operator, text=op_text, icon_value=custom_icon)
|
|
||||||
|
|
||||||
if ui_context != "TOOL_HEADER":
|
|
||||||
row.label(text="", icon=modifier_icon)
|
|
||||||
row.label(text="", icon=f"EVENT_{key}" if key else "BLANK1")
|
|
||||||
|
|
||||||
hotkey_description = f"Hotkey: {modifier_str} {key}".strip()
|
|
||||||
description = "\n\n".join(filter(None, [description, hotkey_description]))
|
|
||||||
|
|
||||||
if operator == "bim.hotkey":
|
|
||||||
op.hotkey = hotkey
|
|
||||||
if ui_context == "TOOL_HEADER":
|
|
||||||
op.description = text + "\n" + description
|
|
||||||
else:
|
|
||||||
op.description = description
|
|
||||||
return op
|
|
||||||
|
|
||||||
|
|
||||||
def format_ifc_camel_case(string):
|
def format_ifc_camel_case(string):
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import bonsai.tool as tool
|
|||||||
from bonsai.bim.module.model.data import AuthoringData
|
from bonsai.bim.module.model.data import AuthoringData
|
||||||
from bpy.types import WorkSpaceTool
|
from bpy.types import WorkSpaceTool
|
||||||
import bonsai.core.spatial
|
import bonsai.core.spatial
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
class SpatialTool(WorkSpaceTool):
|
class SpatialTool(WorkSpaceTool):
|
||||||
@@ -49,9 +50,7 @@ class SpatialTool(WorkSpaceTool):
|
|||||||
SpatialToolUI.draw(context, layout)
|
SpatialToolUI.draw(context, layout)
|
||||||
|
|
||||||
|
|
||||||
def add_layout_hotkey(layout: bpy.types.UILayout, text: str, hotkey: str, description: str) -> None:
|
add_layout_hotkey = partial(tool.Blender.add_layout_hotkey_operator, tool_name="spatial", module_name=__name__)
|
||||||
args = ("spatial", layout, text, hotkey, description)
|
|
||||||
tool.Blender.add_layout_hotkey_operator(*args)
|
|
||||||
|
|
||||||
|
|
||||||
class SpatialToolUI:
|
class SpatialToolUI:
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import os
|
|||||||
import bpy
|
import bpy
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
from bpy.types import WorkSpaceTool
|
from bpy.types import WorkSpaceTool
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
|
||||||
class StructuralTool(WorkSpaceTool):
|
class StructuralTool(WorkSpaceTool):
|
||||||
@@ -41,9 +42,7 @@ class StructuralTool(WorkSpaceTool):
|
|||||||
StructuralToolUI.draw(context, layout)
|
StructuralToolUI.draw(context, layout)
|
||||||
|
|
||||||
|
|
||||||
def add_layout_hotkey(layout: bpy.types.UILayout, text: str, hotkey: str, description: str) -> None:
|
add_layout_hotkey = partial(tool.Blender.add_layout_hotkey_operator, tool_name="structural", module_name=__name__)
|
||||||
args = ("structural", layout, text, hotkey, description)
|
|
||||||
tool.Blender.add_layout_hotkey_operator(*args)
|
|
||||||
|
|
||||||
|
|
||||||
# NOTES before adding new operators:
|
# NOTES before adding new operators:
|
||||||
|
|||||||
@@ -500,18 +500,55 @@ class Blender(bonsai.core.tool.Blender):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_layout_hotkey_operator(
|
def add_layout_hotkey_operator(
|
||||||
cls, tool_name: str, layout: bpy.types.UILayout, text: str, hotkey: str, description: str
|
cls,
|
||||||
|
layout: bpy.types.UILayout,
|
||||||
|
text: str,
|
||||||
|
hotkey: str,
|
||||||
|
description: str,
|
||||||
|
ui_context: str = "",
|
||||||
|
*,
|
||||||
|
tool_name: str,
|
||||||
|
module_name: str,
|
||||||
|
operator: Optional[str] = None,
|
||||||
) -> tuple[bpy.types.OperatorProperties, bpy.types.UILayout]:
|
) -> tuple[bpy.types.OperatorProperties, bpy.types.UILayout]:
|
||||||
|
"""
|
||||||
|
:param module_name: Provide `__name__` of the current module,
|
||||||
|
so method could pick up icon previews based on the module's `custom_icon_previews` attribute.
|
||||||
|
:param operator: Operator to display in UI. Displaying the specific operator in UI can be useful
|
||||||
|
to provide poll error messages.
|
||||||
|
"""
|
||||||
|
if tool_name == "bim":
|
||||||
|
hotkey_operator = "bim.hotkey"
|
||||||
|
else:
|
||||||
|
hotkey_operator = f"bim.{tool_name}_hotkey"
|
||||||
|
operator_to_use = operator or hotkey_operator
|
||||||
|
|
||||||
modifier, key = hotkey.split("_")
|
modifier, key = hotkey.split("_")
|
||||||
|
op_text = "" if ui_context == "TOOL_HEADER" else text
|
||||||
row = layout.row(align=True)
|
|
||||||
modifier_icon, modifier_str = cls.KEY_MODIFIERS.get(modifier, ("NONE", ""))
|
modifier_icon, modifier_str = cls.KEY_MODIFIERS.get(modifier, ("NONE", ""))
|
||||||
row.label(text="", icon=modifier_icon)
|
|
||||||
row.label(text="", icon=f"EVENT_{key}")
|
|
||||||
|
|
||||||
op = row.operator(f"bim.{tool_name}_hotkey", text=text)
|
row = layout if ui_context == "TOOL_HEADER" else layout.row(align=True)
|
||||||
op.hotkey = hotkey
|
module = sys.modules[module_name]
|
||||||
op.description = description
|
icon_previews: Union[bpy.utils.previews.ImagePreviewCollection, None]
|
||||||
|
icon_previews = getattr(module, "custom_icon_previews", None)
|
||||||
|
if icon_previews:
|
||||||
|
custom_icon = icon_previews.get(text.upper().replace(" ", "_"), icon_previews["IFC"]).icon_id
|
||||||
|
op = row.operator(operator_to_use, text=op_text, icon_value=custom_icon)
|
||||||
|
else:
|
||||||
|
op = row.operator(operator_to_use, text=op_text)
|
||||||
|
if ui_context != "TOOL_HEADER":
|
||||||
|
row.label(text="", icon=modifier_icon)
|
||||||
|
row.label(text="", icon=f"EVENT_{key}")
|
||||||
|
|
||||||
|
if operator_to_use == hotkey_operator:
|
||||||
|
hotkey_description = f"Hotkey: {modifier_str} {key}".strip()
|
||||||
|
description = "\n\n".join(filter(None, [description, hotkey_description]))
|
||||||
|
|
||||||
|
op.hotkey = hotkey
|
||||||
|
if ui_context == "TOOL_HEADER":
|
||||||
|
op.description = text + "\n" + description
|
||||||
|
else:
|
||||||
|
op.description = description
|
||||||
return op, row
|
return op, row
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user