Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-11-02 15:05:13 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-11-02 15:05:13 +0300
commit1ca3e1a91dbb4bbd99d8d8275e2a9c8dc0505d1c (patch)
treec638ed870b8b8838592daa29cb079cf5c49fd0c1 /release
parent08141260ffa619fef1871ccd446b8a59a7b111ca (diff)
UI: support nested tools in toolbar
Diffstat (limited to 'release')
-rw-r--r--release/scripts/startup/bl_ui/__init__.py1
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py145
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py51
3 files changed, 167 insertions, 30 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')),)),
],