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], # --- 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