OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / tools / keymap / blender_dump.py

63 lines · python ref:
#!/usr/bin/env python3
"""Dump Blender's 2.7x key-map (left-click select) as JSON — THE REFERENCE the
gate_keymap_blender gate holds our build-mode Keymap to (docs/keymap-blender-279.md §1, §5).

Blender ships its own 2.7x reproduction: scripts/presets/keyconfig/Blender_27x.py runs
keymap_data/blender_default.py with legacy=True, spacebar_action='SEARCH',
use_select_all_toggle=True, use_gizmo_drag=False. blender_default.py imports only `math`,
so it runs outside Blender. The one setting we change: select_mouse='LEFT' (user decision
2026-10-12, "left click select").

    python3 -I tools/keymap/blender_dump.py \
        <blender-source>/scripts/presets/keyconfig/keymap_data/blender_default.py \
        > tools/keymap/blender_279_left.json

Output: {"source", "params", "keymaps": {name: [{"op", "type", "value", "shift", "ctrl",
"alt", "oskey", "any", "props"}...]}} for the key-maps build mode borrows from.
"""
import json
import runpy
import sys

KEYMAPS = ["Window", "Screen", "3D View Generic", "3D View", "Object Mode", "Object Non-modal",
           "Mesh", "View3D Fly Modal"]

PARAMS = dict(select_mouse="LEFT", legacy=True, spacebar_action="SEARCH",
              use_select_all_toggle=True, use_gizmo_drag=False)


def _plain(v):
    """Property values as JSON: tuples -> lists, everything else as is."""
    if isinstance(v, tuple):
        return [_plain(x) for x in v]
    return v


def main(path: str) -> None:
    ns = runpy.run_path(path)
    data = ns["generate_keymaps"](ns["Params"](**PARAMS))
    out = {}
    for name, _space, body in data:
        if name not in KEYMAPS:
            continue
        rows = []
        for item in body.get("items", []):
            op, ev, extra = item
            props = {}
            if extra and extra.get("properties"):
                props = {k: _plain(v) for k, v in extra["properties"]}
            rows.append({
                "op": op, "type": ev.get("type"), "value": ev.get("value"),
                "shift": bool(ev.get("shift", False)), "ctrl": bool(ev.get("ctrl", False)),
                "alt": bool(ev.get("alt", False)), "oskey": bool(ev.get("oskey", False)),
                "any": bool(ev.get("any", False)), "props": props,
            })
        out[name] = rows
    json.dump({"source": "blender_default.py (Blender_27x.py params, select_mouse=LEFT)",
               "params": PARAMS, "keymaps": out}, sys.stdout, indent=1, sort_keys=True)
    sys.stdout.write("\n")


if __name__ == "__main__":
    main(sys.argv[1])