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>2019-12-06 19:45:50 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-12-06 22:03:00 +0300
commit6ffcddc10afa07b073ce01c25884e23fc2b661df (patch)
tree86e7ddb017474083890bf16fac4876175a923e57 /release/scripts/startup
parent7465078e637b729e8b36a4f4b73a50a347052df4 (diff)
Tool System: experimental fallback tool support
Implement T66304 as an experimental option, available under the preferences "Experimental" section. - When enabled most tools in the 3D view have a gizmo. - Dragging outside the gizmo uses the 'fallback' tool. - The fallback tool can be changed or disabled in the tool options or from a pie menu (Alt-W).
Diffstat (limited to 'release/scripts/startup')
-rw-r--r--release/scripts/startup/bl_operators/wm.py63
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py364
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py44
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py18
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py6
5 files changed, 414 insertions, 81 deletions
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 24670b2a37d..1452b6767b6 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -1645,6 +1645,12 @@ class WM_OT_tool_set_by_id(Operator):
default=False,
options={'SKIP_SAVE'},
)
+ as_fallback: BoolProperty(
+ name="Set Fallback",
+ description="Set the fallback tool instead of the primary tool",
+ default=False,
+ options={'SKIP_SAVE', 'HIDDEN'},
+ )
space_type: rna_space_type_prop
@@ -1672,7 +1678,10 @@ class WM_OT_tool_set_by_id(Operator):
space_type = context.space_data.type
fn = activate_by_id_or_cycle if self.cycle else activate_by_id
- if fn(context, space_type, self.name):
+ if fn(context, space_type, self.name, as_fallback=self.as_fallback):
+ if self.as_fallback:
+ tool_settings = context.tool_settings
+ tool_settings.workspace_tool_type = 'FALLBACK'
return {'FINISHED'}
else:
self.report({'WARNING'}, f"Tool {self.name!r:s} not found for space {space_type!r:s}.")
@@ -1699,13 +1708,20 @@ class WM_OT_tool_set_by_index(Operator):
default=True,
)
+ as_fallback: BoolProperty(
+ name="Set Fallback",
+ description="Set the fallback tool instead of the primary",
+ default=False,
+ options={'SKIP_SAVE', 'HIDDEN'},
+ )
+
space_type: rna_space_type_prop
def execute(self, context):
from bl_ui.space_toolsystem_common import (
activate_by_id,
activate_by_id_or_cycle,
- item_from_index,
+ item_from_index_active,
item_from_flat_index,
)
@@ -1714,7 +1730,7 @@ class WM_OT_tool_set_by_index(Operator):
else:
space_type = context.space_data.type
- fn = item_from_flat_index if self.expand else item_from_index
+ fn = item_from_flat_index if self.expand else item_from_index_active
item = fn(context, space_type, self.index)
if item is None:
# Don't report, since the number of tools may change.
@@ -1722,7 +1738,10 @@ class WM_OT_tool_set_by_index(Operator):
# Same as: WM_OT_tool_set_by_id
fn = activate_by_id_or_cycle if self.cycle else activate_by_id
- if fn(context, space_type, item.idname):
+ if fn(context, space_type, item.idname, as_fallback=self.as_fallback):
+ if self.as_fallback:
+ tool_settings = context.tool_settings
+ tool_settings.workspace_tool_type = 'FALLBACK'
return {'FINISHED'}
else:
# Since we already have the tool, this can't happen.
@@ -1776,6 +1795,41 @@ class WM_OT_toolbar(Operator):
return {'FINISHED'}
+class WM_OT_toolbar_fallback_pie(Operator):
+ bl_idname = "wm.toolbar_fallback_pie"
+ bl_label = "Fallback Tool Pie Menu"
+
+ @classmethod
+ def poll(cls, context):
+ return context.space_data is not None
+
+ def invoke(self, context, event):
+ if not context.preferences.experimental.use_tool_fallback:
+ return {'PASS_THROUGH'}
+
+ from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
+ space_type = context.space_data.type
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ return {'PASS_THROUGH'}
+
+ # It's possible we don't have the fallback tool available.
+ # This can happen in the image editor for example when there is no selection
+ # in painting modes.
+ item, _ = cls._tool_get_by_id(context, space_type, cls.tool_fallback_id)
+ if item is None:
+ print("Tool", cls.tool_fallback_id, "not active in", cls)
+ return {'PASS_THROUGH'}
+
+ def draw_cb(self, context):
+ from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
+ ToolSelectPanelHelper.draw_fallback_tool_items_for_pie_menu(self.layout, context)
+
+ wm = context.window_manager
+ wm.popup_menu_pie(draw_func=draw_cb, title="Fallback Tool", event=event)
+ return {'FINISHED'}
+
+
class WM_OT_toolbar_prompt(Operator):
"""Leader key like functionality for accessing tools"""
bl_idname = "wm.toolbar_prompt"
@@ -2563,6 +2617,7 @@ classes = (
WM_OT_tool_set_by_id,
WM_OT_tool_set_by_index,
WM_OT_toolbar,
+ WM_OT_toolbar_fallback_pie,
WM_OT_toolbar_prompt,
BatchRenameAction,
WM_OT_batch_rename,
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
index 7c7825403a9..a5501301015 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_common.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -162,7 +162,7 @@ class ToolActivePanelHelper:
layout.use_property_decorate = False
ToolSelectPanelHelper.draw_active_tool_header(
context,
- layout,
+ layout.column(),
show_tool_name=True,
tool_key=ToolSelectPanelHelper._tool_key_from_context(context, space_type=self.bl_space_type),
)
@@ -262,76 +262,100 @@ class ToolSelectPanelHelper:
else:
yield item, -1
- @staticmethod
- def _tool_get_active(context, space_type, mode, with_icon=False):
+ @classmethod
+ def _tool_get_active(cls, context, space_type, mode, with_icon=False):
"""
Return the active Python tool definition and icon name.
"""
- cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
- if cls is not None:
- tool_active = ToolSelectPanelHelper._tool_active_from_context(context, space_type, mode)
- tool_active_id = getattr(tool_active, "idname", None)
- for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context, mode)):
- if item is not None:
- if item.idname == tool_active_id:
- if with_icon:
- icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(item.icon)
- else:
- icon_value = 0
- return (item, tool_active, icon_value)
+ tool_active = ToolSelectPanelHelper._tool_active_from_context(context, space_type, mode)
+ tool_active_id = getattr(tool_active, "idname", None)
+ for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context, mode)):
+ if item is not None:
+ if item.idname == tool_active_id:
+ if with_icon:
+ icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(item.icon)
+ else:
+ icon_value = 0
+ return (item, tool_active, icon_value)
return None, None, 0
- @staticmethod
- def _tool_get_by_id(context, space_type, idname):
+ @classmethod
+ def _tool_get_by_id(cls, context, space_type, idname):
"""
Return the active Python tool definition and index (if in sub-group, else -1).
"""
- cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
- if cls is not None:
- for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)):
- if item is not None:
+ for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)):
+ if item is not None:
+ if item.idname == idname:
+ return (item, index)
+ return None, -1
+
+ @classmethod
+ def _tool_get_by_id_active(cls, context, space_type, idname):
+ """
+ Return the active Python tool definition and index (if in sub-group, else -1).
+ """
+ for item in cls.tools_from_context(context):
+ if item is not None:
+ if type(item) is tuple:
+ if item[0].idname == idname:
+ index = cls._tool_group_active.get(item[0].idname, 0)
+ return (item[index], index)
+ else:
if item.idname == idname:
- return (cls, item, index)
- return None, None, -1
+ return (item, -1)
+ return None, -1
- @staticmethod
- def _tool_get_by_flat_index(context, space_type, tool_index):
+ @classmethod
+ def _tool_get_by_id_active_with_group(cls, context, space_type, idname):
+ """
+ Return the active Python tool definition and index (if in sub-group, else -1).
+ """
+ for item in cls.tools_from_context(context):
+ if item is not None:
+ if type(item) is tuple:
+ if item[0].idname == idname:
+ index = cls._tool_group_active.get(item[0].idname, 0)
+ return (item[index], index, item)
+ else:
+ if item.idname == idname:
+ return (item, -1, None)
+ return None, -1, None
+
+ @classmethod
+ def _tool_get_by_flat_index(cls, context, space_type, tool_index):
"""
Return the active Python tool definition and index (if in sub-group, else -1).
Return the index of the expanded list.
"""
- cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
- if cls is not None:
- i = 0
- for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)):
- if item is not None:
- if i == tool_index:
- return (cls, item, index)
- i += 1
- return None, None, -1
+ i = 0
+ for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)):
+ if item is not None:
+ if i == tool_index:
+ return (item, index)
+ i += 1
+ return None, -1
- @staticmethod
- def _tool_get_by_index(context, space_type, tool_index):
+ @classmethod
+ def _tool_get_active_by_index(cls, context, space_type, tool_index):
"""
Return the active Python tool definition and index (if in sub-group, else -1).
Return the index of the list without expanding.
"""
- cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
- if cls is not None:
- i = 0
- for item in cls.tools_from_context(context):
- if item is not None:
- if i == tool_index:
- if type(item) is tuple:
- index = cls._tool_group_active.get(item[0].idname, 0)
- item = item[index]
- else:
- index = -1
- return (cls, item, index)
- i += 1
- return None, None, -1
+ i = 0
+ for item in cls.tools_from_context(context):
+ if item is not None:
+ if i == tool_index:
+ if type(item) is tuple:
+ index = cls._tool_group_active.get(item[0].idname, 0)
+ item = item[index]
+ else:
+ index = -1
+ return (item, index)
+ i += 1
+ return None, -1
@staticmethod
def _tool_active_from_context(context, space_type, mode=None, create=False):
@@ -633,6 +657,24 @@ class ToolSelectPanelHelper:
space_type = context.space_data.type
return ToolSelectPanelHelper._tool_active_from_context(context, space_type)
+
+ @staticmethod
+ def draw_active_tool_fallback(
+ context, layout, tool,
+ *,
+ is_horizontal_layout=False,
+ ):
+ tool_fallback = tool.tool_fallback
+ space_type = tool.space_type
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ item_fallback, _index = cls._tool_get_by_id(context, space_type, tool_fallback)
+ if item_fallback is not None:
+ draw_settings = item_fallback.draw_settings
+ if draw_settings is not None:
+ if not is_horizontal_layout:
+ layout.separator()
+ draw_settings(context, layout, tool)
+
@staticmethod
def draw_active_tool_header(
context, layout,
@@ -640,6 +682,7 @@ class ToolSelectPanelHelper:
show_tool_name=False,
tool_key=None,
):
+ is_horizontal_layout = layout.direction != 'VERTICAL'
if tool_key is None:
space_type, mode = ToolSelectPanelHelper._tool_key_from_context(context)
else:
@@ -647,7 +690,9 @@ class ToolSelectPanelHelper:
if space_type is None:
return None
- item, tool, icon_value = ToolSelectPanelHelper._tool_get_active(context, space_type, mode, with_icon=True)
+
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ item, tool, icon_value = cls._tool_get_active(context, space_type, mode, with_icon=True)
if item is None:
return None
# Note: we could show 'item.text' here but it makes the layout jitter when switching tools.
@@ -658,8 +703,128 @@ class ToolSelectPanelHelper:
draw_settings = item.draw_settings
if draw_settings is not None:
draw_settings(context, layout, tool)
+
+ if context.preferences.experimental.use_tool_fallback:
+ tool_fallback = tool.tool_fallback
+ else:
+ tool_fallback = None
+
+ if tool_fallback and tool_fallback != item.idname:
+ tool_settings = context.tool_settings
+
+ # Show popover which looks like an enum but isn't one.
+ if tool_settings.workspace_tool_type == 'FALLBACK':
+ tool_fallback_id = cls.tool_fallback_id
+ item, _select_index = cls._tool_get_by_id_active(context, space_type, tool_fallback_id)
+ label = item.label
+ else:
+ label = "Active Tool"
+
+ split = layout.split(factor=0.5)
+ row = split.row()
+ row.alignment = 'RIGHT'
+ row.label(text="Drag")
+ row = split.row()
+ row.context_pointer_set("tool", tool)
+ row.popover(panel="TOPBAR_PT_tool_fallback", text=label)
+
return tool
+ # Show a list of tools in the popover.
+ @staticmethod
+ def draw_fallback_tool_items(layout, context):
+
+ space_type = context.space_data.type
+ if space_type == 'PROPERTIES':
+ space_type = 'VIEW_3D'
+
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ tool_fallback_id = cls.tool_fallback_id
+
+ _item, _select_index, item_group = cls._tool_get_by_id_active_with_group(context, space_type, tool_fallback_id)
+
+ if item_group is None:
+ # Could print comprehensive message - listing available items.
+ raise Exception("Fallback tool doesn't exist")
+
+ col = layout.column(align=True)
+ tool_settings = context.tool_settings
+ col.prop_enum(
+ tool_settings,
+ "workspace_tool_type",
+ value='DEFAULT',
+ text="Active Tool",
+ )
+ is_active_tool = (tool_settings.workspace_tool_type == 'DEFAULT')
+
+ col = layout.column(align=True)
+ if is_active_tool:
+ index_current = -1
+ else:
+ index_current = cls._tool_group_active.get(item_group[0].idname, 0)
+ for i, sub_item in enumerate(item_group):
+ is_active = (i == index_current)
+
+ props = col.operator(
+ "wm.tool_set_by_id",
+ text=sub_item.label,
+ depress=is_active,
+ )
+ props.name = sub_item.idname
+ props.as_fallback = True
+ props.space_type = space_type
+
+ @staticmethod
+ def draw_fallback_tool_items_for_pie_menu(layout, context):
+ space_type = context.space_data.type
+ if space_type == 'PROPERTIES':
+ space_type = 'VIEW_3D'
+
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ tool_fallback_id = cls.tool_fallback_id
+
+ _item, _select_index, item_group = cls._tool_get_by_id_active_with_group(context, space_type, tool_fallback_id)
+
+ if item_group is None:
+ # Could print comprehensive message - listing available items.
+ raise Exception("Fallback tool doesn't exist")
+
+ # Allow changing the active tool,
+ # even though this isn't the purpose of the pie menu
+ # it's confusing from a user perspective if we don't allow it.
+ is_fallback_group_active = getattr(
+ ToolSelectPanelHelper._tool_active_from_context(context, space_type),
+ "idname", None,
+ ) in (item.idname for item in item_group)
+
+ pie = layout.menu_pie()
+ tool_settings = context.tool_settings
+ pie.prop_enum(
+ tool_settings,
+ "workspace_tool_type",
+ value='DEFAULT',
+ text="Active Tool",
+ icon='TOOL_SETTINGS', # Could use a less generic icon.
+ )
+ is_active_tool = (tool_settings.workspace_tool_type == 'DEFAULT')
+
+ if is_active_tool:
+ index_current = -1
+ else:
+ index_current = cls._tool_group_active.get(item_group[0].idname, 0)
+ for i, sub_item in enumerate(item_group):
+ is_active = (i == index_current)
+ props = pie.operator(
+ "wm.tool_set_by_id",
+ text=sub_item.label,
+ depress=is_active,
+ icon_value=ToolSelectPanelHelper._icon_value_from_icon_handle(sub_item.icon),
+ )
+ props.name = sub_item.idname
+ props.space_type = space_type
+ if not is_fallback_group_active:
+ props.as_fallback = True
+
# 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.
@@ -701,7 +866,43 @@ class WM_MT_toolsystem_submenu(Menu):
).name = item.idname
-def _activate_by_item(context, space_type, item, index):
+def _activate_by_item(context, space_type, item, index, *, as_fallback=False):
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ tool_fallback_id = cls.tool_fallback_id
+
+ if as_fallback:
+ # To avoid complicating logic too much, isolate all fallback logic to this block.
+ # This will set the tool again, using the item for the fallback instead of the primary tool.
+ #
+ # If this ends up needing to be more complicated,
+ # it would be better to split it into a separate function.
+
+ _item, _select_index, item_group = cls._tool_get_by_id_active_with_group(context, space_type, tool_fallback_id)
+
+ if item_group is None:
+ # Could print comprehensive message - listing available items.
+ raise Exception("Fallback tool doesn't exist")
+ index_new = -1
+ for i, sub_item in enumerate(item_group):
+ if sub_item.idname == item.idname:
+ index_new = i
+ break
+ if index_new == -1:
+ raise Exception("Fallback tool not found in group")
+
+ cls._tool_group_active[tool_fallback_id] = index_new
+
+ # Done, now get the current tool to replace the item & index.
+ tool_active = ToolSelectPanelHelper._tool_active_from_context(context, space_type)
+ item, index = cls._tool_get_by_id(context, space_type, getattr(tool_active, "idname", None))
+
+ # Find fallback keymap.
+ item_fallback = None
+ _item, select_index = cls._tool_get_by_id(context, space_type, tool_fallback_id)
+ if select_index != -1:
+ item_fallback, _index = cls._tool_get_active_by_index(context, space_type, select_index)
+ # End calculating fallback.
+
tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True)
tool.setup(
idname=item.idname,
@@ -711,6 +912,9 @@ def _activate_by_item(context, space_type, item, index):
data_block=item.data_block or "",
operator=item.operator or "",
index=index,
+
+ idname_fallback=item_fallback.idname if item_fallback else "",
+ keymap_fallback=(item_fallback.keymap[0] or "") if item_fallback else "",
)
WindowManager = bpy.types.WindowManager
@@ -729,18 +933,22 @@ def _activate_by_item(context, space_type, item, index):
_activate_by_item._cursor_draw_handle = {}
-def activate_by_id(context, space_type, text):
- _cls, item, index = ToolSelectPanelHelper._tool_get_by_id(context, space_type, text)
+def activate_by_id(context, space_type, idname, *, as_fallback=False):
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ return False
+ item, index = cls._tool_get_by_id(context, space_type, idname)
if item is None:
return False
- _activate_by_item(context, space_type, item, index)
+ _activate_by_item(context, space_type, item, index, as_fallback=as_fallback)
return True
-def activate_by_id_or_cycle(context, space_type, idname, offset=1):
+def activate_by_id_or_cycle(context, space_type, idname, *, offset=1, as_fallback=False):
# Only cycle when the active tool is activated again.
- cls, item, _index = ToolSelectPanelHelper._tool_get_by_id(context, space_type, idname)
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ item, _index = cls._tool_get_by_id(context, space_type, idname)
if item is None:
return False
@@ -774,7 +982,8 @@ def activate_by_id_or_cycle(context, space_type, idname, offset=1):
def description_from_id(context, space_type, idname, *, use_operator=True):
# Used directly for tooltips.
- _cls, item, _index = ToolSelectPanelHelper._tool_get_by_id(context, space_type, idname)
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ item, _index = cls._tool_get_by_id(context, space_type, idname)
if item is None:
return False
@@ -806,23 +1015,52 @@ def description_from_id(context, space_type, idname, *, use_operator=True):
def item_from_id(context, space_type, idname):
# Used directly for tooltips.
- _cls, item, _index = ToolSelectPanelHelper._tool_get_by_id(context, space_type, idname)
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ return None
+ item, _index = cls._tool_get_by_id(context, space_type, idname)
+ return item
+
+
+def item_from_id_active(context, space_type, idname):
+ # Used directly for tooltips.
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ return None
+ item, _index = cls._tool_get_by_id_active(context, space_type, idname)
+ return item
+
+
+def item_from_id_active_with_group(context, space_type, idname):
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ return None
+ cls, item, _index = cls._tool_get_by_id_active_with_group(context, space_type, idname)
return item
def item_from_flat_index(context, space_type, index):
- _cls, item, _index = ToolSelectPanelHelper._tool_get_by_flat_index(context, space_type, index)
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ return None
+ item, _index = cls._tool_get_by_flat_index(context, space_type, index)
return item
-def item_from_index(context, space_type, index):
- _cls, item, _index = ToolSelectPanelHelper._tool_get_by_index(context, space_type, index)
+def item_from_index_active(context, space_type, index):
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ return None
+ item, _index = cls._tool_get_active_by_index(context, space_type, index)
return item
def keymap_from_id(context, space_type, idname):
# Used directly for tooltips.
- _cls, item, _index = ToolSelectPanelHelper._tool_get_by_id(context, space_type, idname)
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ return None
+ item, _index = cls._tool_get_by_id(context, space_type, idname)
if item is None:
return False
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 9a5df62da46..68d39a3be64 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -297,8 +297,15 @@ class _defs_transform:
if layout.use_property_split:
layout.label(text="Gizmos:")
- props = tool.gizmo_group_properties("VIEW3D_GGT_xform_gizmo")
- layout.prop(props, "drag_action")
+ show_drag = True
+ if context.preferences.experimental.use_tool_fallback:
+ tool_settings = context.tool_settings
+ if tool_settings.workspace_tool_type == 'FALLBACK':
+ show_drag = False
+
+ if show_drag:
+ props = tool.gizmo_group_properties("VIEW3D_GGT_xform_gizmo")
+ layout.prop(props, "drag_action")
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1)
@@ -472,7 +479,7 @@ class _defs_edit_mesh:
idname="builtin.rip_region",
label="Rip Region",
icon="ops.mesh.rip",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_free",
keymap=(),
draw_settings=draw_settings,
)
@@ -512,7 +519,7 @@ class _defs_edit_mesh:
idname="builtin.edge_slide",
label="Edge Slide",
icon="ops.transform.edge_slide",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
draw_settings=draw_settings,
)
@@ -527,7 +534,7 @@ class _defs_edit_mesh:
idname="builtin.vertex_slide",
label="Vertex Slide",
icon="ops.transform.vert_slide",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_free",
keymap=(),
draw_settings=draw_settings,
)
@@ -579,7 +586,7 @@ class _defs_edit_mesh:
idname="builtin.inset_faces",
label="Inset Faces",
icon="ops.mesh.inset",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
draw_settings=draw_settings,
)
@@ -597,7 +604,7 @@ class _defs_edit_mesh:
idname="builtin.bevel",
label="Bevel",
icon="ops.mesh.bevel",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
draw_settings=draw_settings,
)
@@ -629,7 +636,7 @@ class _defs_edit_mesh:
idname="builtin.extrude_along_normals",
label="Extrude Along Normals",
icon="ops.mesh.extrude_region_shrink_fatten",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
operator="mesh.extrude_region_shrink_fatten",
keymap=(),
draw_settings=draw_settings,
@@ -641,7 +648,7 @@ class _defs_edit_mesh:
idname="builtin.extrude_individual",
label="Extrude Individual",
icon="ops.mesh.extrude_faces_move",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
)
@@ -698,7 +705,7 @@ class _defs_edit_mesh:
idname="builtin.smooth",
label="Smooth",
icon="ops.mesh.vertices_smooth",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
draw_settings=draw_settings,
)
@@ -714,7 +721,7 @@ class _defs_edit_mesh:
idname="builtin.randomize",
label="Randomize",
icon="ops.transform.vertex_random",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
draw_settings=draw_settings,
)
@@ -753,7 +760,7 @@ class _defs_edit_mesh:
idname="builtin.shrink_fatten",
label="Shrink/Fatten",
icon="ops.transform.shrink_fatten",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
draw_settings=draw_settings,
)
@@ -764,7 +771,7 @@ class _defs_edit_mesh:
idname="builtin.push_pull",
label="Push/Pull",
icon="ops.transform.push_pull",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
)
@@ -890,7 +897,7 @@ class _defs_edit_curve:
idname="builtin.randomize",
label="Randomize",
icon="ops.curve.vertex_random",
- widget=None,
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
keymap=(),
draw_settings=draw_settings,
)
@@ -1682,6 +1689,9 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
# Satisfy the 'ToolSelectPanelHelper' API.
keymap_prefix = "Image Editor Tool:"
+ # Default group to use as a fallback.
+ tool_fallback_id = "builtin.select"
+
@classmethod
def tools_from_context(cls, context, mode=None):
if mode is None:
@@ -1766,6 +1776,9 @@ class NODE_PT_tools_active(ToolSelectPanelHelper, Panel):
# Satisfy the 'ToolSelectPanelHelper' API.
keymap_prefix = "Node Editor Tool:"
+ # Default group to use as a fallback.
+ tool_fallback_id = "builtin.select"
+
@classmethod
def tools_from_context(cls, context, mode=None):
if mode is None:
@@ -1822,6 +1835,9 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
# Satisfy the 'ToolSelectPanelHelper' API.
keymap_prefix = "3D View Tool:"
+ # Default group to use as a fallback.
+ tool_fallback_id = "builtin.select"
+
@classmethod
def tools_from_context(cls, context, mode=None):
if mode is None:
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index dcfeb6a210f..09531cb5ef6 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -78,6 +78,23 @@ class TOPBAR_HT_upper_bar(Header):
unlink="scene.view_layer_remove")
+class TOPBAR_PT_tool_fallback(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Layers"
+ bl_ui_units_x = 8
+
+ def draw(self, context):
+ from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
+ layout = self.layout
+
+ tool_settings = context.tool_settings
+ ToolSelectPanelHelper.draw_fallback_tool_items(layout, context)
+ if tool_settings.workspace_tool_type == 'FALLBACK':
+ tool = context.tool
+ ToolSelectPanelHelper.draw_active_tool_fallback(context, layout, tool)
+
+
class TOPBAR_PT_gpencil_layers(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
@@ -772,6 +789,7 @@ classes = (
TOPBAR_MT_render,
TOPBAR_MT_window,
TOPBAR_MT_help,
+ TOPBAR_PT_tool_fallback,
TOPBAR_PT_gpencil_layers,
TOPBAR_PT_gpencil_primitive,
TOPBAR_PT_gpencil_fill,
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index e9ccbbabdd3..130db518cb7 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -2188,6 +2188,12 @@ class USERPREF_PT_experimental_all(ExperimentalPanel, Panel):
# For the other settings create new panels
# and make sure they are disabled if use_experimental_all is True
+ url_prefix = "https://developer.blender.org/"
+
+ row = col.row()
+ row.prop(experimental, "use_tool_fallback")
+
+ row.operator("wm.url_open", text="", icon='URL').url = url_prefix + "T66304"
"""
# Example panel, leave it here so we always have a template to follow even