scopedvr-map-editor/src/editor/shortcut_keys.gd
slyphax 26bcbe0cdd Terrain-Pinsel: Kante-Regler (Falloff), Einebnen, Rampe, Druck-Stärke, Mal-Slot-Ersatz
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 09:52:03 +01:00

121 lines
No EOL
5.4 KiB
GDScript

extends RefCounted
class_name ShortcutKeys
## InputMap-Actions der Editor-Tastatur-Shortcuts (Karte t_c46d31c2, Karte 1/3).
##
## Konvention (alle Shortcut-Karten): Tastaturcode-basiert — JEDER Action wird
## ein InputEventKey mit PHYSICAL keycode zugewiesen (KEY_*-Konstante). Die
## physische Taste liegt unabhängig vom Tastaturlayout an derselben Position
## (QWERTZ wie QWERTY bei W/A/S/D/Leertaste/Shift), damit deutsche und
## Windows-Tastaturen identisch bedienen — keine OS-Hardcodes (PLAN.md
## Plattform-Regel).
##
## Registrierung per Code statt project.godot: KEY_*-Konstanten bleiben im
## Quelltext lesbar und der Test kann exakt dieselben Konstanten prüfen.
## register() ist idempotent (mehrfacher Aufruf = keine Doppel-Events).
## Action → Liste von Events. Einträge:
## KEY_X = einfache physische Taste
## {"key": KEY_X, "shift": true} = Taste + Modifier (z. B. Umschalt+F)
const ACTIONS := {
# --- Freelook-Flug (Rechte Maustaste halten bzw. Umschalt+F) -------------
"editor_freelook_toggle": [{"key": KEY_F, "shift": true}],
"editor_freelook": [MOUSE_BUTTON_RIGHT],
"editor_fly_forward": [KEY_W],
"editor_fly_back": [KEY_S],
"editor_fly_left": [KEY_A],
"editor_fly_right": [KEY_D],
# Flug-Vertikal + Tempo (Shooter-Konvention, Sly-Wunsch 17.10.):
# Leertaste = hoch, Shift = runter (Half-Life/CS-Konvention), Strg halten =
# temporär schneller, Alt halten = langsamer. Mausrad bleibt Grundtempo.
# Konflikt-Freiheit: Leertaste/Shift/Strg SIND im Editor sonst nur als
# Modifier-Kombos belegt (Strg+Z, Umschalt+Klick …) — allein gedrückt
# triggern sie KEINE Werkzeug-Aktion (Tests: test_shortcuts.gd,
# Konflikt-Gruppe). Im Flugmodus gibt der Kamera-Einstieg den GUI-Fokus
# frei (orbit_camera._enter_fly), damit Leertaste keinen fokussierten
# Button auslöst.
"editor_fly_up": [KEY_SPACE],
"editor_fly_down": [KEY_SHIFT],
"editor_fly_fast": [KEY_CTRL],
"editor_fly_slow": [KEY_ALT],
# --- Auswahl / Objekt-Operationen ----------------------------------------
"editor_focus_selection": [KEY_F],
"editor_cancel": [KEY_ESCAPE],
"editor_delete_selection": [KEY_DELETE],
"editor_duplicate_selection": [{"key": KEY_D, "ctrl": true}],
# Strg+LMB = Mehrfachauswahl umschalten (Maus-Event, handler prüft den
# Modifier direkt am InputEventMouseButton — Action dokumentiert die Idee).
"editor_multi_select": [{"key": KEY_NONE, "mouse_left_ctrl": true}],
# --- Objekt-Manipulation (Karte t_55257792, Karte 2/3) -------------------
"editor_rotate_90": [KEY_R],
"editor_nudge_up": [KEY_UP],
"editor_nudge_down": [KEY_DOWN],
"editor_nudge_left": [KEY_LEFT],
"editor_nudge_right": [KEY_RIGHT],
"editor_lift_to_floor": [{"key": KEY_PAGEUP, "ctrl": true}],
"editor_grab": [KEY_G],
# --- Terrain-Pinsel (nur im Terrain-Werkzeug aktiv, main gated) ----------
"editor_brush_smaller": [KEY_BRACKETLEFT],
"editor_brush_larger": [KEY_BRACKETRIGHT],
"editor_brush_raise": [KEY_1],
"editor_brush_lower": [KEY_2],
"editor_brush_smooth": [KEY_3],
"editor_brush_paint": [KEY_4],
"editor_brush_flatten": [KEY_5],
"editor_brush_ramp": [KEY_6],
# --- Datei & Undo (Karte t_11b5c25b, Karte 3/3) --------------------------
# Strg+Z/Strg+Y laufen seit dem M2-UX-Fundament; hier NACHGEBUGGEN als
# dokumentierte Actions (alle 3 Shortcut-Karten: ACTIONS-Dict = Source of
# truth). Strg+Umschalt+Z ist der zweite Redo-Weg (beide belegt).
"editor_undo": [{"key": KEY_Z, "ctrl": true}],
"editor_redo_y": [{"key": KEY_Y, "ctrl": true}],
"editor_redo_shift_z": [{"key": KEY_Z, "ctrl": true, "shift": true}],
"editor_save": [{"key": KEY_S, "ctrl": true}],
"editor_save_as": [{"key": KEY_S, "ctrl": true, "shift": true}],
"editor_open_map": [{"key": KEY_O, "ctrl": true}],
"editor_new_map": [{"key": KEY_N, "ctrl": true}],
# --- Werkzeugwechsel (F-Tasten statt Ziffern, Slys Weiche) ---------------
"editor_tool_terrain": [KEY_F1],
"editor_tool_objects": [KEY_F2],
"editor_tool_bauen": [KEY_F3],
"editor_tool_spawns": [KEY_F4],
# --- Kurzhilfe-Overlay + Test-Platzhalter --------------------------------
"editor_help_overlay": [KEY_H],
"editor_test_map": [KEY_F5],
# --- Höhenlinien fixieren (Karte t_89c0ec95) ------------------------------
# L = Nutzer-Wahl „Linien immer an/aus" — ohne Fix sind sie NUR im
# Terrain-Werkzeug (F1) sichtbar (Werkzeug-Kopplung in main.gd). L ist
# sonst unbesetzt (Kollisions-Prüfung Karte t_89c0ec95: keine Taste in
# ACTIONS nutzt KEY_L, Ziffern bleiben Terrain-Pinsel allein vorbehalten).
"editor_contours_toggle": [KEY_L],
}
static func register() -> void:
for action in ACTIONS:
if InputMap.has_action(action):
continue
InputMap.add_action(action)
for entry in ACTIONS[action]:
InputMap.action_add_event(action, _make_event(entry))
static func _make_event(entry) -> InputEvent:
if entry is Dictionary:
if entry.get("mouse_left_ctrl", false):
var mb := InputEventMouseButton.new()
mb.button_index = MOUSE_BUTTON_LEFT
mb.ctrl_pressed = true
return mb
var key := InputEventKey.new()
key.physical_keycode = int(entry.get("key", KEY_NONE))
key.shift_pressed = bool(entry.get("shift", false))
key.ctrl_pressed = bool(entry.get("ctrl", false))
key.alt_pressed = bool(entry.get("alt", false))
return key
if entry is int and entry >= MOUSE_BUTTON_NONE and entry <= MOUSE_BUTTON_RIGHT:
var mouse := InputEventMouseButton.new()
mouse.button_index = int(entry)
return mouse
var simple := InputEventKey.new()
simple.physical_keycode = int(entry)
return simple