diff options
5 files changed, 119 insertions, 47 deletions
diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py index db46bf0736a..fada1255e8b 100644 --- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py +++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py @@ -437,8 +437,8 @@ def dump_rna_messages(msgs, reports, settings, verbose=False): reports, check_ctxt_rna, settings) # And parse keymaps! - from bpy_extras.keyconfig_utils import KM_HIERARCHY - walk_keymap_hierarchy(KM_HIERARCHY, "KM_HIERARCHY") + from bpy_extras.keyconfig_utils import km_hierarchy + walk_keymap_hierarchy(km_hierarchy(), "KM_HIERARCHY") ##### Python source code ##### diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py index ec4db69986c..3da67ed2461 100644 --- a/release/scripts/modules/bpy_extras/keyconfig_utils.py +++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py @@ -18,12 +18,36 @@ # <pep8 compliant> + +def _km_expand_from_toolsystem(space_type, context_mode): + def _fn(): + from bl_ui.space_toolsystem_common import ToolSelectPanelHelper + for cls in ToolSelectPanelHelper.__subclasses__(): + if cls.bl_space_type == space_type: + return cls.keymap_ui_hierarchy(context_mode) + raise Exception("keymap not found") + return _fn + + +def _km_hierarchy_iter_recursive(items): + for sub in items: + if callable(sub): + yield from sub() + else: + yield (*sub[:3], list(_km_hierarchy_iter_recursive(sub[3]))) + + +def km_hierarchy(): + return list(_km_hierarchy_iter_recursive(_km_hierarchy)) + + # bpy.type.KeyMap: (km.name, km.space_type, km.region_type, [...]) # ('Script', 'EMPTY', 'WINDOW', []), -KM_HIERARCHY = [ +# Access via 'km_hierarchy'. +_km_hierarchy = [ ('Window', 'EMPTY', 'WINDOW', []), # file save, window change, exit ('Screen', 'EMPTY', 'WINDOW', [ # full screen, undo, screenshot ('Screen Editing', 'EMPTY', 'WINDOW', []), # re-sizing, action corners @@ -36,24 +60,51 @@ KM_HIERARCHY = [ ('User Interface', 'EMPTY', 'WINDOW', []), ('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform) - ('Object Mode', 'EMPTY', 'WINDOW', []), - ('Mesh', 'EMPTY', 'WINDOW', []), - ('Curve', 'EMPTY', 'WINDOW', []), - ('Armature', 'EMPTY', 'WINDOW', []), - ('Metaball', 'EMPTY', 'WINDOW', []), - ('Lattice', 'EMPTY', 'WINDOW', []), - ('Font', 'EMPTY', 'WINDOW', []), - - ('Pose', 'EMPTY', 'WINDOW', []), - - ('Vertex Paint', 'EMPTY', 'WINDOW', []), - ('Weight Paint', 'EMPTY', 'WINDOW', []), + ('Object Mode', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'OBJECT'), + ]), + ('Mesh', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'EDIT_MESH'), + ]), + ('Curve', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'EDIT_CURVE'), + ]), + ('Armature', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'EDIT_ARMATURE'), + ]), + ('Metaball', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'EDIT_METABALL'), + ]), + ('Lattice', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'EDIT_LATTICE'), + ]), + ('Font', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'EDIT_TEXT'), + ]), + + ('Pose', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'POSE'), + ]), + + ('Vertex Paint', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'PAINT_VERTEX'), + ]), + ('Weight Paint', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'PAINT_WEIGHT'), + ]), ('Weight Paint Vertex Selection', 'EMPTY', 'WINDOW', []), ('Face Mask', 'EMPTY', 'WINDOW', []), - ('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d - ('Sculpt', 'EMPTY', 'WINDOW', []), - - ('Particle', 'EMPTY', 'WINDOW', []), + # image and view3d + ('Image Paint', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'PAINT_TEXTURE'), + ]), + ('Sculpt', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'SCULPT'), + ]), + + ('Particle', 'EMPTY', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', 'PARTICLE'), + ]), ('Knife Tool Modal Map', 'EMPTY', 'WINDOW', []), ('Custom Normals Modal Map', 'EMPTY', 'WINDOW', []), @@ -69,7 +120,10 @@ KM_HIERARCHY = [ ('View3D Zoom Modal', 'EMPTY', 'WINDOW', []), ('View3D Dolly Modal', 'EMPTY', 'WINDOW', []), - ('3D View Generic', 'VIEW_3D', 'WINDOW', []), # toolbar and properties + # toolbar and properties + ('3D View Generic', 'VIEW_3D', 'WINDOW', [ + _km_expand_from_toolsystem('VIEW_3D', None), + ]), ]), ('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [ @@ -88,7 +142,9 @@ KM_HIERARCHY = [ ('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image) ('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d ('UV Sculpt', 'EMPTY', 'WINDOW', []), - ('Image Generic', 'IMAGE_EDITOR', 'WINDOW', []), + ('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [ + _km_expand_from_toolsystem('IMAGE_EDITOR', None), + ]), ]), ('Outliner', 'OUTLINER', 'WINDOW', []), @@ -410,7 +466,7 @@ def keyconfig_test(kc): # Function body result = False - for entry in KM_HIERARCHY: + for entry in km_hierarchy(): if testEntry(kc, entry): result = True return result diff --git a/release/scripts/modules/rna_keymap_ui.py b/release/scripts/modules/rna_keymap_ui.py index 776d2d81d98..2581d7782f1 100644 --- a/release/scripts/modules/rna_keymap_ui.py +++ b/release/scripts/modules/rna_keymap_ui.py @@ -356,7 +356,7 @@ def draw_filtered(display_keymaps, filter_type, filter_text, layout): def draw_hierarchy(display_keymaps, layout): from bpy_extras import keyconfig_utils - for entry in keyconfig_utils.KM_HIERARCHY: + for entry in keyconfig_utils.km_hierarchy(): draw_entry(display_keymaps, entry, layout) diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index f5cb0d006f6..5a32264bc5a 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -302,25 +302,32 @@ class ToolSelectPanelHelper: return context.button_operator.name @classmethod - def _km_action_simple(cls, kc, context_mode, text, keymap_fn): - if context_mode is None: - context_mode = "All" - km_idname = f"{cls.keymap_prefix:s} {context_mode:s}, {text:s}" + def _km_action_simple(cls, kc, context_descr, text, keymap_fn): + km_idname = f"{cls.keymap_prefix:s} {context_descr:s}, {text:s}" km = kc.keymaps.get(km_idname) if km is None: km = kc.keymaps.new(km_idname, space_type=cls.bl_space_type, region_type='WINDOW') keymap_fn[0](km) keymap_fn[0] = km + # Special internal function, gives use items that contain keymaps. + @staticmethod + def _tools_flatten_with_keymap(tools): + for item_parent in tools: + if item_parent is None: + continue + for item in item_parent if (type(item_parent) is tuple) else (item_parent,): + # skip None or generator function + if item is None or _item_is_fn(item): + continue + if item.keymap is not None: + yield item + @classmethod def register(cls): wm = bpy.context.window_manager - - # XXX, should we be manipulating the user-keyconfig on load? - # Perhaps this should only add when keymap items don't already exist. - # - # This needs some careful consideration. - kc = wm.keyconfigs.user + # Write into defaults, users may modify in preferences. + kc = wm.keyconfigs.default # Track which tool-group was last used for non-active groups. # Blender stores the active tool-group index. @@ -333,17 +340,26 @@ class ToolSelectPanelHelper: return for context_mode, tools in cls.tools_all(): - for item_parent in tools: - if item_parent is None: - continue - for item in item_parent if (type(item_parent) is tuple) else (item_parent,): - # skip None or generator function - if item is None or _item_is_fn(item): - continue - keymap_data = item.keymap - if keymap_data is not None and callable(keymap_data[0]): - text = item.text - cls._km_action_simple(kc, context_mode, text, keymap_data) + if context_mode is None: + context_descr = "All" + else: + context_descr = context_mode.replace("_", " ").title() + + for item in cls._tools_flatten_with_keymap(tools): + keymap_data = item.keymap + if callable(keymap_data[0]): + text = item.text + cls._km_action_simple(kc, context_descr, text, keymap_data) + + @classmethod + def keymap_ui_hierarchy(cls, context_mode): + # See: bpy_extras.keyconfig_utils + for context_mode_test, tools in cls.tools_all(): + if context_mode_test == context_mode: + for item in cls._tools_flatten_with_keymap(tools): + km = item.keymap[0] + # print((km.name, cls.bl_space_type, 'WINDOW', [])) + yield (km.name, cls.bl_space_type, 'WINDOW', []) # ------------------------------------------------------------------------- # Layout Generators diff --git a/tests/python/bl_keymap_completeness.py b/tests/python/bl_keymap_completeness.py index 652ed449a3c..0edee3b02f0 100644 --- a/tests/python/bl_keymap_completeness.py +++ b/tests/python/bl_keymap_completeness.py @@ -27,12 +27,12 @@ from bpy_extras import keyconfig_utils def check_maps(): maps = {} - def fill_maps(ls): - for km_name, km_space_type, km_region_type, km_sub in ls: + def fill_maps(seq): + for km_name, km_space_type, km_region_type, km_sub in seq: maps[km_name] = (km_space_type, km_region_type) fill_maps(km_sub) - fill_maps(keyconfig_utils.KM_HIERARCHY) + fill_maps(keyconfig_utils.km_hierarchy()) import bpy keyconf = bpy.context.window_manager.keyconfigs.active |