diff options
-rw-r--r-- | release/scripts/startup/bl_ui/__init__.py | 1 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_toolsystem_common.py | 145 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_toolsystem_toolbar.py | 51 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_workspace_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_workspace.c | 5 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 6 |
6 files changed, 180 insertions, 31 deletions
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index a12fd6352ea..037fe9618ec 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -68,6 +68,7 @@ _modules = [ # Generic Space Modules # # Depends on DNA_WORKSPACE_TOOL (C define). + "space_toolsystem_common", "space_toolsystem_toolbar", "space_clip", diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index 1dade5b6735..69f4b0bbf2a 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -18,6 +18,9 @@ # <pep8 compliant> import bpy +from bpy.types import ( + Menu, +) __all__ = ( "ToolSelectPanelHelper", @@ -48,6 +51,19 @@ class ToolSelectPanelHelper: an optional triple of: ``(operator_id, operator_properties, keymap_item_args)`` """ + @staticmethod + def _tool_is_group(tool): + return type(tool[0]) is not str + + @staticmethod + def _tools_flatten(tools): + for item in tools: + if ToolSelectPanelHelper._tool_is_group(item): + for sub_item in item: + yield sub_item + else: + yield item + @classmethod def _km_actionmouse_simple(cls, kc, text, actions): @@ -85,7 +101,7 @@ class ToolSelectPanelHelper: if kc is None: return - for t in cls.tools_all(): + for t in ToolSelectPanelHelper._tools_flatten(cls.tools_all()): text, mp_idname, actions = t if actions is not None: km, km_idname = cls._km_actionmouse_simple(kc, text, actions) @@ -101,6 +117,7 @@ class ToolSelectPanelHelper: workspace = context.workspace km_idname_active = workspace.tool_keymap or None mp_idname_active = workspace.tool_manipulator_group or None + index_active = workspace.tool_index layout = self.layout for tool_items in self.tools_from_context(context): @@ -110,22 +127,122 @@ class ToolSelectPanelHelper: if item is None: col = layout.column(align=True) continue - text, mp_idname, actions = item - if actions is not None: - km, km_idname = self._tool_keymap[text] + if self._tool_is_group(item): + index = 0 + is_active = False + for i, sub_item in enumerate(item): + text, mp_idname, actions = sub_item + km, km_idname = (None, None) if actions is None else self._tool_keymap[text] + is_active = ( + km_idname_active == km_idname and + mp_idname_active == mp_idname + ) + if is_active: + index = i + break + del i, sub_item + item = item[index] + use_menu = True else: - km = None - km_idname = None - - props = col.operator( - "wm.tool_set", - text=text, - depress=( - km_idname_active == km_idname and - mp_idname_active == mp_idname - ), + index = -1 + use_menu = False + + text, mp_idname, actions = item + km, km_idname = (None, None) if actions is None else self._tool_keymap[text] + is_active = ( + km_idname_active == km_idname and + mp_idname_active == mp_idname ) + if use_menu: + props = col.operator_menu_hold( + "wm.tool_set", + text=text, + depress=is_active, + menu="WM_MT_toolsystem_submenu", + ) + else: + props = col.operator( + "wm.tool_set", + text=text, + depress=is_active, + ) + props.keymap = km_idname or "" props.manipulator_group = mp_idname or "" + props.index = index + + def tools_from_context(cls, context): + return (cls._tools[None], cls._tools.get(context.mode, ())) + + +# The purpose of this menu is to be a generic popup to select between tools +# in cases when a single tool allows to select alternative tools. +class WM_MT_toolsystem_submenu(Menu): + bl_label = "" + + @staticmethod + def _tool_group_from_button(context): + # Lookup the tool definitions based on the space-type. + space_type = context.space_data.type + cls = next( + (cls for cls in ToolSelectPanelHelper.__subclasses__() + if cls.bl_space_type == space_type), + None + ) + if cls is not None: + props = context.button_operator + km_idname_button = props.keymap or None + mp_idname_button = props.manipulator_group or None + index_button = props.index + + for item_items in cls.tools_from_context(context): + for item_group in item_items: + if (item_group is not None) and ToolSelectPanelHelper._tool_is_group(item_group): + if index_button < len(item_group): + item = item_group[index_button] + text, mp_idname, actions = item + km, km_idname = (None, None) if actions is None else cls._tool_keymap[text] + is_active = ( + km_idname_button == km_idname and + mp_idname_button == mp_idname + ) + if is_active: + return cls, item_group, index_button + return None, None, -1 + + def draw(self, context): + layout = self.layout + cls, item_group, index_active = self._tool_group_from_button(context) + if item_group is None: + # Should never happen, just in case + layout.label(f"Unable to find toolbar group") + return + + index = 0 + for item in item_group: + if item is None: + layout.separator() + continue + text, mp_idname, actions = item + km, km_idname = (None, None) if actions is None else cls._tool_keymap[text] + + props = layout.operator( + "wm.tool_set", + text=text, + ) + props.keymap = km_idname or "" + props.manipulator_group = mp_idname or "" + props.index = index + index += 1 + + +classes = ( + WM_MT_toolsystem_submenu, +) + +if __name__ == "__main__": # only for live edit. + from bpy.utils import register_class + for cls in classes: + register_class(cls) diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 71e41850a51..6667eb566c2 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -66,20 +66,25 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): None: [ ("Cursor", None, (("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='CLICK')),)), - ("Select Border", None, ( - ("view3d.select_border", dict(deselect=False), dict(type='EVT_TWEAK_A', value='ANY')), - ("view3d.select_border", dict(deselect=True), dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)), - )), - ("Select Circle", None, ( - ("view3d.select_circle", dict(deselect=False), dict(type='ACTIONMOUSE', value='PRESS')), - ("view3d.select_circle", dict(deselect=True), dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)), - )), - ("Select Lasso", None, ( - ("view3d.select_lasso", - dict(deselect=False), dict(type='EVT_TWEAK_A', value='ANY')), - ("view3d.select_lasso", - dict(deselect=True), dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)), - )), + + # 'Select' Group + ( + ("Select Border", None, ( + ("view3d.select_border", dict(deselect=False), dict(type='EVT_TWEAK_A', value='ANY')), + ("view3d.select_border", dict(deselect=True), dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)), + )), + ("Select Circle", None, ( + ("view3d.select_circle", dict(deselect=False), dict(type='ACTIONMOUSE', value='PRESS')), + ("view3d.select_circle", dict(deselect=True), dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)), + )), + ("Select Lasso", None, ( + ("view3d.select_lasso", + dict(deselect=False), dict(type='EVT_TWEAK_A', value='ANY')), + ("view3d.select_lasso", + dict(deselect=True), dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)), + )), + ), + # End group. ], 'OBJECT': [ *_tools_transform, @@ -122,8 +127,22 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): ("mesh.polybuild_hover", dict(use_boundary=True), dict(type='MOUSEMOVE', value='ANY', any=True)), )), - ("Knife", None, (("mesh.knife_tool", dict(wait_for_input=False), dict(type='ACTIONMOUSE', value='PRESS')),)), - ("Bisect", None, (("mesh.bisect", dict(), dict(type='EVT_TWEAK_A', value='ANY')),)), + # Knife Group + ( + ("Knife", None, ( + ("mesh.knife_tool", + dict(wait_for_input=False, use_occlude_geometry=True, only_selected=False), + dict(type='ACTIONMOUSE', value='PRESS')),)), + ("Knife (Selected)", None, ( + ("mesh.knife_tool", + dict(wait_for_input=False, use_occlude_geometry=False, only_selected=True), + dict(type='ACTIONMOUSE', value='PRESS')),)), + ("Bisect", None, ( + ("mesh.bisect", + dict(), + dict(type='EVT_TWEAK_A', value='ANY')),)), + ), + # End group. ("Extrude Cursor", None, (("mesh.dupli_extrude_cursor", dict(), dict(type='ACTIONMOUSE', value='PRESS')),)), ], diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h index 8cd03a5eafa..1e650fcfb6d 100644 --- a/source/blender/makesdna/DNA_workspace_types.h +++ b/source/blender/makesdna/DNA_workspace_types.h @@ -58,7 +58,8 @@ typedef struct bToolDef { char keymap[64]; char manipulator_group[64]; int spacetype; - int _pad; + /* index when a tool is a member of a group */ + int index; } bToolDef; /** diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c index 8cf5e3e8eaf..e09f7bcbcc1 100644 --- a/source/blender/makesrna/intern/rna_workspace.c +++ b/source/blender/makesrna/intern/rna_workspace.c @@ -156,6 +156,11 @@ static void rna_def_workspace(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Active Tool", "Currently active tool manipulator"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "tool_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "tool.index"); + RNA_def_property_ui_text(prop, "Active Tool Index", "Tool group index"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "orientations", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "transform_orientations", NULL); RNA_def_property_struct_type(prop, "TransformOrientation"); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index c6884f3da8b..0783d364d48 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1760,6 +1760,9 @@ static int wm_operator_tool_set_exec(bContext *C, wmOperator *op) char id_manipulator_group[sizeof(workspace->tool.manipulator_group)]; RNA_string_get(op->ptr, "keymap", id_keymap); RNA_string_get(op->ptr, "manipulator_group", id_manipulator_group); + int index = RNA_int_get(op->ptr, "index"); + + workspace->tool.index = index; if (workspace->tool.manipulator_group[0]) { wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(workspace->tool.manipulator_group, false); @@ -1780,6 +1783,8 @@ static int wm_operator_tool_set_exec(bContext *C, wmOperator *op) WM_manipulator_group_type_ensure(workspace->tool.manipulator_group); } + ED_region_tag_redraw(CTX_wm_region(C)); + return OPERATOR_FINISHED; } @@ -1795,6 +1800,7 @@ static void WM_OT_tool_set(wmOperatorType *ot) RNA_def_string(ot->srna, "keymap", NULL, KMAP_MAX_NAME, "Key Map", ""); RNA_def_string(ot->srna, "manipulator_group", NULL, MAX_NAME, "Manipulator Group", ""); + RNA_def_int(ot->srna, "index", 0, INT_MIN, INT_MAX, "Index", "", INT_MIN, INT_MAX); } #endif /* USE_WORKSPACE_TOOL */ |