Keymap: add experimental "Toolbar Toggle Pie" preference
When pressing N-key a pie menu is shown which can toggle regions, typically the toolbar, sidebar and the header. This supports toggling regions without having to add a separate shortcut for each one. The pie menu locations selected based on the region alignment. See #107785.
This commit is contained in:
parent
566118f7f1
commit
ab7161e41a
@ -88,6 +88,15 @@ class Prefs(bpy.types.KeyConfigPreferences):
|
||||
update=update_fn,
|
||||
)
|
||||
|
||||
# Experimental: only show with developer extras, see: #107785.
|
||||
use_toolbar_pie: BoolProperty(
|
||||
name="Toolbar Toggle Pie",
|
||||
description=(
|
||||
"N-key opens a pie menu to toggle regions"
|
||||
),
|
||||
default=False,
|
||||
update=update_fn,
|
||||
)
|
||||
# Experimental: only show with developer extras, see: #96544.
|
||||
use_tweak_select_passthrough: BoolProperty(
|
||||
name="Tweak Select: Mouse Select & Move",
|
||||
@ -310,6 +319,9 @@ class Prefs(bpy.types.KeyConfigPreferences):
|
||||
if show_developer_ui and (not is_select_left):
|
||||
row = sub.row()
|
||||
row.prop(self, "use_tweak_tool_lmb_interaction")
|
||||
if show_developer_ui:
|
||||
row = sub.row()
|
||||
row.prop(self, "use_toolbar_pie")
|
||||
|
||||
# 3DView settings.
|
||||
col = layout.column()
|
||||
@ -357,6 +369,7 @@ def load():
|
||||
use_mouse_emulate_3_button=use_mouse_emulate_3_button,
|
||||
spacebar_action=kc_prefs.spacebar_action,
|
||||
use_key_activate_tools=(kc_prefs.tool_key_mode == 'TOOL'),
|
||||
use_toolbar_pie=(show_developer_ui and kc_prefs.use_toolbar_pie),
|
||||
v3d_tilde_action=kc_prefs.v3d_tilde_action,
|
||||
use_v3d_mmb_pan=(kc_prefs.v3d_mmb_action == 'PAN'),
|
||||
v3d_alt_mmb_drag_action=kc_prefs.v3d_alt_mmb_drag_action,
|
||||
|
@ -66,6 +66,8 @@ class Params:
|
||||
"use_alt_click_leader",
|
||||
# Transform keys G/S/R activate tools instead of immediately transforming.
|
||||
"use_key_activate_tools",
|
||||
# Side-bar toggle opens a pie menu instead of immediately toggling the side-bar.
|
||||
"use_toolbar_pie",
|
||||
# Optionally use a modifier to access tools.
|
||||
"tool_modifier",
|
||||
# Experimental option.
|
||||
@ -113,6 +115,7 @@ class Params:
|
||||
# User preferences.
|
||||
spacebar_action='TOOL',
|
||||
use_key_activate_tools=False,
|
||||
use_toolbar_pie=False,
|
||||
use_select_all_toggle=False,
|
||||
use_gizmo_drag=True,
|
||||
use_fallback_tool=False,
|
||||
@ -193,6 +196,7 @@ class Params:
|
||||
# User preferences:
|
||||
self.spacebar_action = spacebar_action
|
||||
self.use_key_activate_tools = use_key_activate_tools
|
||||
self.use_toolbar_pie = use_toolbar_pie
|
||||
|
||||
self.use_gizmo_drag = use_gizmo_drag
|
||||
self.use_select_all_toggle = use_select_all_toggle
|
||||
@ -311,8 +315,21 @@ def _template_items_context_panel(menu, key_args_primary):
|
||||
]
|
||||
|
||||
|
||||
def _template_space_region_type_toggle(*, toolbar_key=None, sidebar_key=None, channels_key=None):
|
||||
def _template_space_region_type_toggle(
|
||||
params,
|
||||
*,
|
||||
toolbar_key=None,
|
||||
sidebar_key=None,
|
||||
channels_key=None,
|
||||
):
|
||||
items = []
|
||||
|
||||
if params.use_toolbar_pie:
|
||||
pie_key = sidebar_key or sidebar_key or channels_key
|
||||
if pie_key is not None:
|
||||
items.append(op_menu_pie("WM_MT_toolbar_toggle_pie", pie_key))
|
||||
return items
|
||||
|
||||
if toolbar_key is not None:
|
||||
items.append(
|
||||
("wm.context_toggle", toolbar_key,
|
||||
@ -1412,7 +1429,7 @@ def km_uv_editor(params):
|
||||
# Editor (3D View)
|
||||
|
||||
# 3D View: all regions.
|
||||
def km_view3d_generic(_params):
|
||||
def km_view3d_generic(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"3D View Generic",
|
||||
@ -1422,6 +1439,7 @@ def km_view3d_generic(_params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
toolbar_key={"type": 'T', "value": 'PRESS'},
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
)
|
||||
@ -1759,7 +1777,7 @@ def km_view3d(params):
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Graph Editor)
|
||||
|
||||
def km_graph_editor_generic(_params):
|
||||
def km_graph_editor_generic(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Graph Editor Generic",
|
||||
@ -1769,6 +1787,7 @@ def km_graph_editor_generic(_params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
("graph.extrapolation_type", {"type": 'E', "value": 'PRESS', "shift": True}, None),
|
||||
@ -1931,6 +1950,7 @@ def km_image_generic(params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
toolbar_key={"type": 'T', "value": 'PRESS'},
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
@ -2051,7 +2071,7 @@ def km_image(params):
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Node)
|
||||
|
||||
def km_node_generic(_params):
|
||||
def km_node_generic(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Node Generic",
|
||||
@ -2061,6 +2081,7 @@ def km_node_generic(_params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
toolbar_key={"type": 'T', "value": 'PRESS'},
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
@ -2252,6 +2273,7 @@ def km_file_browser(params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
toolbar_key={"type": 'T', "value": 'PRESS'},
|
||||
),
|
||||
("wm.context_toggle", {"type": 'N', "value": 'PRESS'},
|
||||
@ -2399,7 +2421,7 @@ def km_file_browser_buttons(_params):
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Dope Sheet)
|
||||
|
||||
def km_dopesheet_generic(_params):
|
||||
def km_dopesheet_generic(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Dopesheet Generic",
|
||||
@ -2409,6 +2431,7 @@ def km_dopesheet_generic(_params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
("wm.context_set_enum", {"type": 'TAB', "value": 'PRESS', "ctrl": True},
|
||||
@ -2536,7 +2559,7 @@ def km_dopesheet(params):
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (NLA)
|
||||
|
||||
def km_nla_generic(_params):
|
||||
def km_nla_generic(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"NLA Generic",
|
||||
@ -2546,6 +2569,7 @@ def km_nla_generic(_params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
("nla.tweakmode_enter", {"type": 'TAB', "value": 'PRESS'},
|
||||
@ -2667,7 +2691,7 @@ def km_nla_editor(params):
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Text)
|
||||
|
||||
def km_text_generic(_params):
|
||||
def km_text_generic(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Text Generic",
|
||||
@ -2677,6 +2701,7 @@ def km_text_generic(_params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
sidebar_key={"type": 'T', "value": 'PRESS', "ctrl": True},
|
||||
),
|
||||
("text.start_find", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
|
||||
@ -2841,6 +2866,7 @@ def km_sequencercommon(params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
toolbar_key={"type": 'T', "value": 'PRESS'},
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
@ -3147,7 +3173,7 @@ def km_console(_params):
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Clip)
|
||||
|
||||
def km_clip(_params):
|
||||
def km_clip(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Clip",
|
||||
@ -3157,6 +3183,7 @@ def km_clip(_params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
toolbar_key={"type": 'T', "value": 'PRESS'},
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
@ -3380,7 +3407,7 @@ def km_clip_dopesheet_editor(_params):
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Spreadsheet)
|
||||
|
||||
def km_spreadsheet_generic(_params):
|
||||
def km_spreadsheet_generic(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Spreadsheet Generic",
|
||||
@ -3390,6 +3417,7 @@ def km_spreadsheet_generic(_params):
|
||||
|
||||
items.extend([
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
channels_key={"type": 'T', "value": 'PRESS'},
|
||||
),
|
||||
|
@ -3301,6 +3301,121 @@ class WM_MT_splash_about(Menu):
|
||||
col.operator("wm.url_open_preset", text="Development Fund", icon='FUND').type = 'FUND'
|
||||
|
||||
|
||||
class WM_MT_toolbar_toggle_pie(Menu):
|
||||
bl_label = "Toggle Toolbars"
|
||||
|
||||
# Map the `region.type` to the `space_data` attribute & text label.
|
||||
# The order of items defines priority, so in the sequencer for e.g.
|
||||
# when there is both a toolbar and channels, the toolbar gets the
|
||||
# axis-aligned pie, and the channels don't.
|
||||
_region_info = {
|
||||
'TOOLS': "show_region_toolbar",
|
||||
'UI': "show_region_ui",
|
||||
# Note that the tool header is enabled/disabled along with the header,
|
||||
# no need to include both in this list.
|
||||
'HEADER': "show_region_header",
|
||||
'FOOTER': "show_region_footer",
|
||||
'CHANNELS': "show_region_channels",
|
||||
}
|
||||
# Map the `region.alignment` to the axis-aligned pie position.
|
||||
_region_align_pie = {
|
||||
'LEFT': 0,
|
||||
'RIGHT': 1,
|
||||
'BOTTOM': 2,
|
||||
'TOP': 3,
|
||||
}
|
||||
# Map the axis-aligned pie position to it's opposite side, see `ui_radial_dir_order` in C++ source.
|
||||
# The value is the preferred direction in order of priority, two diagonals, then the flipped direction.
|
||||
_region_dir_pie_alternatives = {
|
||||
0: (4, 6, 1),
|
||||
1: (5, 7, 0),
|
||||
2: (6, 7, 3),
|
||||
3: (4, 5, 2),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.space_data is not None
|
||||
|
||||
@classmethod
|
||||
def _draw_pie_regions_from_alignment(cls, context, pie):
|
||||
space_data = context.space_data
|
||||
# Store each region by it's type.
|
||||
region_by_type = {}
|
||||
|
||||
for region in context.area.regions:
|
||||
region_type = region.type
|
||||
attr = cls._region_info.get(region_type, (None, None))
|
||||
if attr is None:
|
||||
continue
|
||||
# In some cases channels exists but can't be toggled.
|
||||
if region_type == 'CHANNELS':
|
||||
if not hasattr(space_data, attr):
|
||||
continue
|
||||
# Technically possible these double-up, in practice this should never happen.
|
||||
if region_type in region_by_type:
|
||||
print("%s: Unexpected double-up of region types %r" % (type(self).__name__, region_type))
|
||||
region_by_type[region_type] = region
|
||||
|
||||
# Axis aligned pie menu items to populate.
|
||||
items = [[], [], [], [], [], [], [], []]
|
||||
|
||||
# Use predictable ordering.
|
||||
for region_type in cls._region_info.keys():
|
||||
region = region_by_type.get(region_type)
|
||||
if region is None:
|
||||
continue
|
||||
index = cls._region_align_pie[region.alignment]
|
||||
items[index].append(region_type)
|
||||
|
||||
# Handle any overflow (two or more regions with the same alignment).
|
||||
# This happens in the sequencer (channels + toolbar),
|
||||
# otherwise it should not be that common.
|
||||
items_overflow = []
|
||||
for index in range(4):
|
||||
if len(items[index]) <= 1:
|
||||
continue
|
||||
for index_other in cls._region_dir_pie_alternatives[index]:
|
||||
if not items[index_other]:
|
||||
items[index_other].append(items[index].pop(1))
|
||||
if len(items[index]) <= 1:
|
||||
break
|
||||
del index_other
|
||||
|
||||
for index in range(4):
|
||||
if len(items[index]) <= 1:
|
||||
continue
|
||||
for index_other in range(4, 8):
|
||||
if not items[index_other]:
|
||||
items[index_other].append(items[index].pop(1))
|
||||
if len(items[index]) <= 1:
|
||||
break
|
||||
# Only happens when there are more than 8 regions - practically never!
|
||||
for index in range(4):
|
||||
while len(items[index]) > 1:
|
||||
items_overflow.append([items[index].pop(1)])
|
||||
|
||||
# Use to access the labels.
|
||||
enum_items = bpy.types.Region.bl_rna.properties["type"].enum_items_static_ui
|
||||
|
||||
for region_type_list in (items + items_overflow):
|
||||
if not region_type_list:
|
||||
pie.separator()
|
||||
continue
|
||||
assert len(region_type_list) == 1
|
||||
region_type = region_type_list[0]
|
||||
text = enum_items[region_type].name
|
||||
attr = cls._region_info[region_type]
|
||||
value = getattr(space_data, attr)
|
||||
props = pie.operator("wm.context_toggle", text=text, icon='CHECKBOX_HLT' if value else 'CHECKBOX_DEHLT')
|
||||
props.data_path = "space_data." + attr
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
pie = layout.menu_pie()
|
||||
self._draw_pie_regions_from_alignment(context, pie)
|
||||
|
||||
|
||||
class WM_OT_drop_blend_file(Operator):
|
||||
bl_idname = "wm.drop_blend_file"
|
||||
bl_label = "Handle dropped .blend file"
|
||||
@ -3376,4 +3491,5 @@ classes = (
|
||||
WM_MT_splash_quick_setup,
|
||||
WM_MT_splash,
|
||||
WM_MT_splash_about,
|
||||
WM_MT_toolbar_toggle_pie
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user