From de3b844829855d02d145dd513cc37f2fa08150de Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 2 Jun 2023 17:33:04 +0500 Subject: [PATCH] Placeholders for spatial and structural tools --- .../blenderbim/bim/module/cad/workspace.py | 1 - .../blenderbim/bim/module/drawing/__init__.py | 2 +- .../bim/module/drawing/workspace.py | 9 -- .../blenderbim/bim/module/model/workspace.py | 3 +- .../blenderbim/bim/module/spatial/__init__.py | 5 +- .../bim/module/spatial/workspace.py | 126 ++++++++++++++++++ .../bim/module/structural/__init__.py | 5 +- .../bim/module/structural/workspace.py | 126 ++++++++++++++++++ src/blenderbim/blenderbim/tool/blender.py | 18 +++ 9 files changed, 280 insertions(+), 15 deletions(-) create mode 100644 src/blenderbim/blenderbim/bim/module/spatial/workspace.py create mode 100644 src/blenderbim/blenderbim/bim/module/structural/workspace.py diff --git a/src/blenderbim/blenderbim/bim/module/cad/workspace.py b/src/blenderbim/blenderbim/bim/module/cad/workspace.py index ad4fdd676f..d05c149e9b 100644 --- a/src/blenderbim/blenderbim/bim/module/cad/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/cad/workspace.py @@ -33,7 +33,6 @@ class CadTool(WorkSpaceTool): bl_description = "Gives you CAD authoring related superpowers" bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.cad") bl_widget = None - # https://docs.blender.org/api/current/bpy.types.KeyMapItems.html bl_keymap = tool.Blender.get_default_selection_keypmap() + ( ("bim.cad_hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_C")]}), ("bim.cad_hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}), diff --git a/src/blenderbim/blenderbim/bim/module/drawing/__init__.py b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py index 066ae37b87..55a1070ab3 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py @@ -109,7 +109,7 @@ classes = ( def register(): if not bpy.app.background: - bpy.utils.register_tool(workspace.AnnotationTool, after={"bim.bim_tool"}, separator=True, group=True) + bpy.utils.register_tool(workspace.AnnotationTool, after={"bim.bim_tool"}, separator=False, group=True) bpy.types.Scene.DocProperties = bpy.props.PointerProperty(type=prop.DocProperties) bpy.types.Scene.BIMAnnotationProperties = bpy.props.PointerProperty(type=prop.BIMAnnotationProperties) bpy.types.Camera.BIMCameraProperties = bpy.props.PointerProperty(type=prop.BIMCameraProperties) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/workspace.py b/src/blenderbim/blenderbim/bim/module/drawing/workspace.py index 6c048c8dd7..34530ef02f 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/workspace.py @@ -47,7 +47,6 @@ class AnnotationTool(WorkSpaceTool): bl_description = "Gives you Annotation related superpowers" bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.annotation") bl_widget = None - # https://docs.blender.org/api/current/bpy.types.KeyMapItems.html bl_keymap = tool.Blender.get_default_selection_keypmap() + ( ("bim.annotation_hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}), ("bim.annotation_hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_C")]}), @@ -193,14 +192,6 @@ class AnnotationToolUI: if DecoratorData.get_ifc_text_data(bpy.context.object): add_layout_hotkey_operator(cls.layout, "Edit Text", "S_E", "") - @classmethod - def draw_header_interface(cls): - cls.draw_type_selection_interface() - - @classmethod - def draw_basic_annotation_tool_interface(cls): - cls.draw_type_selection_interface() - @classmethod def draw_type_selection_interface(cls): # shared by both sidebar and header diff --git a/src/blenderbim/blenderbim/bim/module/model/workspace.py b/src/blenderbim/blenderbim/bim/module/model/workspace.py index ddb1368eaf..ad9629637f 100644 --- a/src/blenderbim/blenderbim/bim/module/model/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/model/workspace.py @@ -38,7 +38,6 @@ class BimTool(WorkSpaceTool): bl_description = "Gives you BIM authoring related superpowers" bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.bim") bl_widget = None - # https://docs.blender.org/api/current/bpy.types.KeyMapItems.html bl_keymap = tool.Blender.get_default_selection_keypmap() + ( # ("bim.wall_tool_op", {"type": 'MOUSEMOVE', "value": 'ANY'}, {"properties": []}), # ("mesh.add_wall", {"type": 'LEFTMOUSE', "value": 'PRESS'}, {"properties": []}), @@ -184,7 +183,7 @@ class BimToolUI: row.prop(data=cls.props, property="x_angle", text="X Angle") op = row.operator("bim.change_extrusion_x_angle", icon="FILE_REFRESH", text="") op.x_angle = cls.props.x_angle - + elif AuthoringData.data["active_material_usage"] == "PROFILE": row = cls.layout.row(align=True) row.prop(data=cls.props, property="cardinal_point", text="Axis") diff --git a/src/blenderbim/blenderbim/bim/module/spatial/__init__.py b/src/blenderbim/blenderbim/bim/module/spatial/__init__.py index f72600a59b..01bac6c2cc 100644 --- a/src/blenderbim/blenderbim/bim/module/spatial/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/__init__.py @@ -17,7 +17,7 @@ # along with BlenderBIM Add-on. If not, see . import bpy -from . import ui, prop, operator +from . import ui, prop, operator, workspace classes = ( operator.AssignContainer, @@ -36,10 +36,13 @@ classes = ( prop.BIMObjectSpatialProperties, ui.BIM_PT_spatial, ui.BIM_UL_containers, + workspace.Hotkey, ) def register(): + if not bpy.app.background: + bpy.utils.register_tool(workspace.SpatialTool, after={"bim.annotation_tool"}, separator=False, group=True) bpy.types.Scene.BIMSpatialProperties = bpy.props.PointerProperty(type=prop.BIMSpatialProperties) bpy.types.Object.BIMObjectSpatialProperties = bpy.props.PointerProperty(type=prop.BIMObjectSpatialProperties) diff --git a/src/blenderbim/blenderbim/bim/module/spatial/workspace.py b/src/blenderbim/blenderbim/bim/module/spatial/workspace.py new file mode 100644 index 0000000000..7c592d12d7 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/spatial/workspace.py @@ -0,0 +1,126 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2023 @Andrej730 +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + + +import os +import bpy +import blenderbim.tool as tool +from blenderbim.bim.helper import prop_with_search +from bpy.types import WorkSpaceTool +from blenderbim.bim.ifc import IfcStore +import blenderbim.bim.handler + + +# declaring it here to avoid circular import problems +class Operator: + def execute(self, context): + IfcStore.execute_ifc_operator(self, context) + blenderbim.bim.handler.refresh_ui_data() + return {"FINISHED"} + + +class SpatialTool(WorkSpaceTool): + bl_space_type = "VIEW_3D" + bl_context_mode = "OBJECT" + bl_idname = "bim.spatial_tool" + bl_label = "Spatial Tool" + bl_description = "Gives you Spatial related superpowers" + # TODO: replace with spatial icon + bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.annotation") + bl_widget = None + bl_keymap = tool.Blender.get_default_selection_keypmap() + ( + ("bim.spatial_hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}), + ) + + def draw_settings(context, layout, ws_tool): + # Unlike operators, Blender doesn't treat workspace tools as a class, so we'll create our own. + SpatialToolUI.draw(context, layout) + + +def add_layout_hotkey(layout, text, hotkey, description): + args = ["spatial", layout, text, hotkey, description] + tool.Blender.add_layout_hotkey_operator(*args) + + +# NOTES before adding new operators: +# - add scene.BIMSpatialProperties +# - add SpatialData + + +class SpatialToolUI: + @classmethod + def draw(cls, context, layout): + cls.layout = layout + # cls.props = context.scene.BIMSpatialProperties + + row = cls.layout.row(align=True) + if not tool.Ifc.get(): + row.label(text="No IFC Project", icon="ERROR") + return + + # if not SpatialData.is_loaded: + # SpatialData.load() + + cls.draw_type_selection_interface(context) + + if context.active_object and context.selected_objects: + cls.draw_selected_object_interface(context) + cls.draw_default_interface() + + @classmethod + def draw_default_interface(cls): + add_layout_hotkey(cls.layout, "Placeholder", "S_A", "Placeholder Operator") + + @classmethod + def draw_selected_object_interface(cls, context): + pass + + @classmethod + def draw_type_selection_interface(cls, context): + pass + + +class Hotkey(bpy.types.Operator, Operator): + bl_idname = "bim.spatial_hotkey" + bl_label = "Hotkey" + bl_options = {"REGISTER", "UNDO"} + hotkey: bpy.props.StringProperty() + description: bpy.props.StringProperty() + + @classmethod + def poll(cls, context): + return tool.Ifc.get() + + @classmethod + def description(cls, context, operator): + return operator.description or "" + + def _execute(self, context): + # self.props = context.scene.BIMSpatialProperties + getattr(self, f"hotkey_{self.hotkey}")() + + def invoke(self, context, event): + # https://blender.stackexchange.com/questions/276035/how-do-i-make-operators-remember-their-property-values-when-called-from-a-hotkey + # self.props = context.scene.BIMSpatialProperties + return self.execute(context) + + def draw(self, context): + pass + + def hotkey_S_A(self): + pass diff --git a/src/blenderbim/blenderbim/bim/module/structural/__init__.py b/src/blenderbim/blenderbim/bim/module/structural/__init__.py index c37f6a4751..8fde813631 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/structural/__init__.py @@ -17,7 +17,7 @@ # along with BlenderBIM Add-on. If not, see . import bpy -from . import ui, prop, operator +from . import ui, prop, operator, workspace classes = ( operator.LoadStructuralAnalysisModels, @@ -88,10 +88,13 @@ classes = ( ui.BIM_PT_structural_loads, ui.BIM_UL_boundary_conditions, ui.BIM_PT_boundary_conditions, + workspace.Hotkey, ) def register(): + if not bpy.app.background: + bpy.utils.register_tool(workspace.StructuralTool, after={"bim.spatial_tool"}, separator=False, group=True) bpy.types.Scene.BIMStructuralProperties = bpy.props.PointerProperty(type=prop.BIMStructuralProperties) bpy.types.Object.BIMStructuralProperties = bpy.props.PointerProperty(type=prop.BIMObjectStructuralProperties) diff --git a/src/blenderbim/blenderbim/bim/module/structural/workspace.py b/src/blenderbim/blenderbim/bim/module/structural/workspace.py new file mode 100644 index 0000000000..22d598e499 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/structural/workspace.py @@ -0,0 +1,126 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2023 @Andrej730 +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + + +import os +import bpy +import blenderbim.tool as tool +from blenderbim.bim.helper import prop_with_search +from bpy.types import WorkSpaceTool +from blenderbim.bim.ifc import IfcStore +import blenderbim.bim.handler + + +# declaring it here to avoid circular import problems +class Operator: + def execute(self, context): + IfcStore.execute_ifc_operator(self, context) + blenderbim.bim.handler.refresh_ui_data() + return {"FINISHED"} + + +class StructuralTool(WorkSpaceTool): + bl_space_type = "VIEW_3D" + bl_context_mode = "OBJECT" + bl_idname = "bim.structural_tool" + bl_label = "Structural Tool" + bl_description = "Gives you Structure related superpowers" + # TODO: replace with structural icon + bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.annotation") + bl_widget = None + bl_keymap = tool.Blender.get_default_selection_keypmap() + ( + ("bim.structural_hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}), + ) + + def draw_settings(context, layout, ws_tool): + # Unlike operators, Blender doesn't treat workspace tools as a class, so we'll create our own. + StructuralToolUI.draw(context, layout) + + +def add_layout_hotkey(layout, text, hotkey, description): + args = ["structural", layout, text, hotkey, description] + tool.Blender.add_layout_hotkey_operator(*args) + + +# NOTES before adding new operators: +# - add scene.BIMStructuralProperties +# - add StructuralData + + +class StructuralToolUI: + @classmethod + def draw(cls, context, layout): + cls.layout = layout + # cls.props = context.scene.BIMStructuralProperties + + row = cls.layout.row(align=True) + if not tool.Ifc.get(): + row.label(text="No IFC Project", icon="ERROR") + return + + # if not StructuralData.is_loaded: + # StructuralData.load() + + cls.draw_type_selection_interface(context) + + if context.active_object and context.selected_objects: + cls.draw_selected_object_interface(context) + cls.draw_default_interface() + + @classmethod + def draw_default_interface(cls): + add_layout_hotkey(cls.layout, "Placeholder", "S_A", "Placeholder Operator") + + @classmethod + def draw_selected_object_interface(cls, context): + pass + + @classmethod + def draw_type_selection_interface(cls, context): + pass + + +class Hotkey(bpy.types.Operator, Operator): + bl_idname = "bim.structural_hotkey" + bl_label = "Hotkey" + bl_options = {"REGISTER", "UNDO"} + hotkey: bpy.props.StringProperty() + description: bpy.props.StringProperty() + + @classmethod + def poll(cls, context): + return tool.Ifc.get() + + @classmethod + def description(cls, context, operator): + return operator.description or "" + + def _execute(self, context): + # self.props = context.scene.BIMStructuralProperties + getattr(self, f"hotkey_{self.hotkey}")() + + def invoke(self, context, event): + # https://blender.stackexchange.com/questions/276035/how-do-i-make-operators-remember-their-property-values-when-called-from-a-hotkey + # self.props = context.scene.BIMStructuralProperties + return self.execute(context) + + def draw(self, context): + pass + + def hotkey_S_A(self): + pass diff --git a/src/blenderbim/blenderbim/tool/blender.py b/src/blenderbim/blenderbim/tool/blender.py index 2a4d208df3..63ec2b6d01 100644 --- a/src/blenderbim/blenderbim/tool/blender.py +++ b/src/blenderbim/blenderbim/tool/blender.py @@ -143,6 +143,7 @@ class Blender: # box_keymap = def_keymap.km_3d_view_tool_select_box(def_keymap.Params(), fallback=None)[2]["items"] # click_keymap = def_keymap.km_3d_view_tool_select(def_keymap.Params(select_mouse="LEFTMOUSE"), fallback=None)[2]["items"] # ``` + # https://docs.blender.org/api/current/bpy.types.KeyMapItems.html keymap = ( # box selection keymap ("view3d.select_box", {"type": "LEFTMOUSE", "value": "CLICK_DRAG"}, None), @@ -171,6 +172,23 @@ class Blender: ) return keymap + @classmethod + def add_layout_hotkey_operator(cls, tool_name, layout, text, hotkey, description): + 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(f"bim.{tool_name}_hotkey", text=text) + op.hotkey = hotkey + op.description = description + return op, row + @classmethod def get_object_bounding_box(cls, obj): """Returns dict with local min and max x, y, z values for the object.