Map-Editor: Höhenlinien nur im Terrain-Werkzeug (t_89c0ec95)

Sly-Wunsch 17.10.: "die Dauersicht stört" — die Konturen sind genial, aber
nur im Terrain-Werkzeug (F1) gewünscht.

Kopplung am Werkzeug-Wechselpunkt: _set_tool_mode, _after_structure_change
und _recheck_terrain_mode eichen die Konturen NACH (effektiv = Nutzer-Fix
ODER Terrain-Werkzeug). Kein _process-Poll — die Umschaltung passiert
synchron im selben Aufruf, hart ohne Fade (billig und deterministisch).

NEU: Taste L (Action editor_contours_toggle; L war sonst unbesetzt —
Kollisions-Prüfung im Test) und der Button „≈ Höhenlinien" fixieren die
Linien als NUTZER-Wahl dauerhaft in jedem Werkzeug. Default = Fix AUS,
Linien erscheinen also nur bei F1.

Regression aus dem Fundus gefixt: _after_structure_change baute
terrain_view neu OHNE Kontur-Nacheich (das Gitter hatte ihn, die Linien
nicht) — nach jedem Strg+Z kehrte die Dauersicht zurück. Der Rebuild
bekommt jetzt denselben Nacheich wie das Gitter.

Das Relief-Shading (Hillshade + Höhen-Kurve) bleibt davon unberührt und
immer an. Auf flachen Maps (< 2 m Relief) schaltet der Shader weiter
selbst auf aus.

Doku: docs/tasten.md (L-Zeile in Werkzeuge + Kopplungs-Absatz) und
H-Overlay-Zeile (help_text.gd).

Tests: test_shortcuts +5 Checks (Action registriert, physische Taste L,
Kollisions-Freiheit, L ≠ F1/H). test_gui_smoke +21 Checks am ECHTEN main:
Start AUS · Undo/Rebuild bleibt AUS (Root-Cause-Regression) · F1 ein →
F2/F3/F4 aus (synchron, 0 Frames Poll) · L-Fix an/aus inkl. Button-Sync
und Statusmeldungen · Button-Weg ditto.
Suite 11/11 ALL OK: ux 137, shortcuts 203, editor_svmap 31, terrain 112,
library 94, glb_view 28, spawns 52, testrun 14, bauen 87, gui_smoke 89,
rmb_vorrang 32.
This commit is contained in:
Hermes godot-vr 2026-10-17 18:24:45 +00:00
parent d6a0fe2196
commit b85e3bed52
6 changed files with 179 additions and 11 deletions

View file

@ -116,13 +116,22 @@ keinen fokussierten Button auslöst.
| Esc (beim Greifen) | Greifen abbrechen, alte Positionen zurück | | Esc (beim Greifen) | Greifen abbrechen, alte Positionen zurück |
| Esc (beim Platzieren) | Ghost-Preview abbrechen | | Esc (beim Platzieren) | Ghost-Preview abbrechen |
| Esc (Kurzhilfe offen) | Kurzhilfe schließen | | Esc (Kurzhilfe offen) | Kurzhilfe schließen |
| **L** | **Höhenlinien fixieren** (Karte t_89c0ec95): Linien immer sichtbar/unsichtbar — unabhängig vom Werkzeug. Ohne Fix erscheinen sie NUR im Terrain-Werkzeug (F1) |
F1–F4 und F5/H wirken NUR, wenn kein Textfeld/SpinBox fokussiert ist und kein F1–F4 und F5/H/L wirken NUR, wenn kein Textfeld/SpinBox fokussiert ist und kein
Dialog offen ist (ShortcutPolicy) — Tippen geht immer vor. Dialog offen ist (ShortcutPolicy) — Tippen geht immer vor.
Die Terrain-Ziffern 1–4 und [ / ] bleiben (Karte 2/3) NUR im Terrain-Werkzeug Die Terrain-Ziffern 1–4 und [ / ] bleiben (Karte 2/3) NUR im Terrain-Werkzeug
belegt — der Werkzeugwechsel läuft jetzt über die F-Tasten, nicht über Ziffern. belegt — der Werkzeugwechsel läuft jetzt über die F-Tasten, nicht über Ziffern.
Höhenlinien-Kopplung (Karte t_89c0ec95): Die Konturen (1 m, alle 5 m kräftiger)
sind Werkzeug-gekoppelt — **F1 (Terrain) blendet sie ein, jeder andere
Werkzeugwechsel blendet sie aus** (hart, ohne Fade). Wer sie dauerhaft will,
fixiert sie mit **L** oder dem Button „≈ Höhenlinien“ oben. Das Relief-Shading
(Hillshade + Höhen-Kurve) bleibt davon unberührt und immer an. Auf flachen Maps
(< 2 m Gesamtrelief) sind die Linien automatisch aus. L ist sonst unbesetzt
(Kollisions-Prüfung t_89c0ec95).
## Hilfe & Test (Karte 3/3) ## Hilfe & Test (Karte 3/3)
| Eingabe | Wirkung | | Eingabe | Wirkung |

View file

@ -79,6 +79,12 @@ const ACTIONS := {
# --- Kurzhilfe-Overlay + Test-Platzhalter -------------------------------- # --- Kurzhilfe-Overlay + Test-Platzhalter --------------------------------
"editor_help_overlay": [KEY_H], "editor_help_overlay": [KEY_H],
"editor_test_map": [KEY_F5], "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],
} }

View file

@ -66,6 +66,7 @@ static func text() -> String:
["F4", "Werkzeug: Spawn-Zonen malen"], ["F4", "Werkzeug: Spawn-Zonen malen"],
["F5", "▶ Karte testen"], ["F5", "▶ Karte testen"],
["H", "Diese Kurzhilfe an/aus (Esc schließt auch)"], ["H", "Diese Kurzhilfe an/aus (Esc schließt auch)"],
["L", "Höhenlinien FIXIEREN (immer sichtbar/unsichtbar) — ohne Fix erscheinen sie nur im Terrain-Werkzeug (F1)"],
])) ]))
out += "[color=#a8b6ad]Vor „Neue Map“ und „Öffnen“ fragt der Editor nach, wenn noch ungespeicherte Änderungen da sind. Die Statuszeile unten zeigt immer das aktive Werkzeug.[/color]\n" out += "[color=#a8b6ad]Vor „Neue Map“ und „Öffnen“ fragt der Editor nach, wenn noch ungespeicherte Änderungen da sind. Die Statuszeile unten zeigt immer das aktive Werkzeug.[/color]\n"
return out return out

View file

@ -53,7 +53,11 @@ var redo_btn: Button
var grid_btn: Button # „⊞ Gitter“ (Karte t_7ac70014) var grid_btn: Button # „⊞ Gitter“ (Karte t_7ac70014)
var contours_btn: Button # „≈ Höhenlinien“ (Karte t_3ebe4086) var contours_btn: Button # „≈ Höhenlinien“ (Karte t_3ebe4086)
var _grid_on := false # Nutzer-Wahl für das Maßstabsgitter var _grid_on := false # Nutzer-Wahl für das Maßstabsgitter
var _contours_on := true # Nutzer-Wahl für die Höhenlinien (Karte t_3ebe4086) # Höhenlinien (Karte t_89c0ec95): _contours_on ist die NUTZER-Wahl „fixiert
# an“ (L-Taste oder Button). Ohne Fix erscheinen die Linien NUR im
# Terrain-Werkzeug (F1) — Sly-Befund 17.10.: dauerhaft sichtbar störte.
# Effektiv = _contours_fix AN ODER tool_mode == "terrain".
var _contours_on := false
# Auswahl-Panel # Auswahl-Panel
var sel_label: Label var sel_label: Label
@ -220,15 +224,16 @@ func _build_ui() -> void:
grid_btn.toggled.connect(_on_grid_toggled) grid_btn.toggled.connect(_on_grid_toggled)
top_h.add_child(grid_btn) top_h.add_child(grid_btn)
# Höhenlinien-Toggle (Karte t_3ebe4086): Relief-Lesbarkeit — Linien alle # Höhenlinien-Button (Karte t_3ebe4086, Kopplung t_89c0ec95): drücken =
# 1 m plus kräftigere 5-m-Marke. Standardmäßig AN; auf flachen Maps # LINIEN FIXIEREN (immer sichtbar, in jedem Werkzeug). Ohne Fix sind die
# (< 2 m Gesamtrelief) schaltet das Terrain-Mesh selbst auf aus. # Linien NUR im Terrain-Werkzeug (F1) sichtbar; auf flachen Maps (< 2 m
# Gesamtrelief) schaltet das Terrain-Mesh zusätzlich selbst auf aus.
contours_btn = Button.new() contours_btn = Button.new()
contours_btn.text = "≈ Höhenlinien" contours_btn.text = "≈ Höhenlinien"
contours_btn.toggle_mode = true contours_btn.toggle_mode = true
contours_btn.button_pressed = true contours_btn.button_pressed = false
contours_btn.custom_minimum_size = Vector2(150, 40) contours_btn.custom_minimum_size = Vector2(150, 40)
contours_btn.tooltip_text = "Höhenlinien (1 m, alle 5 m kräftiger) im Terrain ein-/ausblenden. Bei flachem Terrain (< 2 m) sind sie automatisch aus." contours_btn.tooltip_text = "Höhenlinien (1 m, alle 5 m kräftiger) FIXIERT an/aus. Ohne Fixierung erscheinen sie nur im Terrain-Werkzeug (F1). Taste L schaltet ebenfalls. Bei flachem Terrain (< 2 m) sind sie automatisch aus."
contours_btn.toggled.connect(_on_contours_toggled) contours_btn.toggled.connect(_on_contours_toggled)
top_h.add_child(contours_btn) top_h.add_child(contours_btn)
@ -1265,6 +1270,14 @@ func _unhandled_key_input(event: InputEvent) -> void:
if _tool_key_allowed(): if _tool_key_allowed():
_toggle_help_overlay() _toggle_help_overlay()
get_viewport().set_input_as_handled() get_viewport().set_input_as_handled()
KEY_L:
# Karte t_89c0ec95: Höhenlinien FIXIEREN an/aus — unabhängig vom
# Werkzeug (wer die Linien dauerhaft will, fixiert sie hier).
# Ohne Modifier (kein Strg+L), gleiche Freigabe wie F1–F5/H:
# Tippen in Textfeldern und offene Dialoge gehen vor.
if not ctrl and _tool_key_allowed():
_on_contours_toggled(not _contours_on)
get_viewport().set_input_as_handled()
KEY_G: KEY_G:
if ctrl: if ctrl:
# Gruppieren/Lösen (Karte t_f6f29d86) # Gruppieren/Lösen (Karte t_f6f29d86)
@ -1525,6 +1538,11 @@ func _set_tool_mode(mode: String) -> void:
_leave_build_mode() _leave_build_mode()
_enter_objects_mode() _enter_objects_mode()
_update_tool_label() _update_tool_label()
# Karte t_89c0ec95: Werkzeugwechsel = Höhenlinien-Umschalter — nach dem
# Terrain-Werkzeug (F1) wieder aus, bei Terrain-Eintritt wieder an
# (sofern nicht fixiert). Signal-getrieben an diesem EINEN Wechselpunkt,
# kein per-Frame-Poll.
_sync_contours_to_builder()
func _enter_terrain_mode() -> void: func _enter_terrain_mode() -> void:
@ -1752,6 +1770,9 @@ func _recheck_terrain_mode() -> void:
terrain_panel.visible = false terrain_panel.visible = false
_sync_terrain_button() _sync_terrain_button()
_update_tool_label() _update_tool_label()
# Karte t_89c0ec95: Dezenter Terrain-Rückschalter = ebenfalls ein
# Werkzeugwechsel — Linien wieder ausblenden (sofern nicht fixiert).
_sync_contours_to_builder()
help_label.text = "Linksklick: auswählen & ziehen · Umschalt+Klick: Auswahl erweitern · Rahmen aufziehen: mehrere wählen · Strg+G: gruppieren\nR: 90° drehen (Mausrad: 15° fein) · Pfeiltasten: 2-m-Raster · G: greifen (Esc: zurück) · Strg+D: duplizieren · Bild↑/↓: anheben/absenken\nStrg+Bild↑: auf Boden setzen · Strg halten: Snap-Zwang · Spiegeln rechts · Entf: löschen · Strg+Z: zurück" help_label.text = "Linksklick: auswählen & ziehen · Umschalt+Klick: Auswahl erweitern · Rahmen aufziehen: mehrere wählen · Strg+G: gruppieren\nR: 90° drehen (Mausrad: 15° fein) · Pfeiltasten: 2-m-Raster · G: greifen (Esc: zurück) · Strg+D: duplizieren · Bild↑/↓: anheben/absenken\nStrg+Bild↑: auf Boden setzen · Strg halten: Snap-Zwang · Spiegeln rechts · Entf: löschen · Strg+Z: zurück"
_set_status("Terrain-Modus aus: Diese Map passt nicht ins Editor-MVP (Terrain-Auflösung über %d) — die Objekte bleiben normal bearbeitbar." % TerrainField.EDITOR_MAX_RESOLUTION, true) _set_status("Terrain-Modus aus: Diese Map passt nicht ins Editor-MVP (Terrain-Auflösung über %d) — die Objekte bleiben normal bearbeitbar." % TerrainField.EDITOR_MAX_RESOLUTION, true)
@ -2062,6 +2083,10 @@ func _after_structure_change() -> void:
interaction.call("clear_selection", true) interaction.call("clear_selection", true)
view_builder.call("rebuild", doc, manifest) view_builder.call("rebuild", doc, manifest)
_sync_grid_to_builder() _sync_grid_to_builder()
# Karte t_89c0ec95: der Rebuild baut terrain_view NEU (Default-Pref „an“)
# — auch die Höhenlinien brauchen ihren Nacheich (Gitter-Muster). Sonst
# kehrte z. B. nach Strg+Z die Dauersicht zurück, die Sly störte.
_sync_contours_to_builder()
_refresh_tree() _refresh_tree()
_recheck_terrain_mode() _recheck_terrain_mode()
if interaction != null: if interaction != null:
@ -2127,21 +2152,35 @@ func _sync_grid_to_builder() -> void:
grid_btn.set_pressed_no_signal(_grid_on) grid_btn.set_pressed_no_signal(_grid_on)
# --- Höhenlinien (Karte t_3ebe4086) ------------------------------------------ # --- Höhenlinien (Karte t_3ebe4086, Werkzeug-Kopplung t_89c0ec95) ------------
## Effektive Höhenlinien-Sichtbarkeit: FIX-Anforderung des Nutzers (L/Button)
## ODER das Terrain-Werkzeug (F1) ist aktiv. Bewusst KEIN _process-Poll —
## der Hook hängt am Werkzeug-Wechselpunkt (_set_tool_mode) und am Button/L.
func _contours_effective() -> bool:
return _contours_on or tool_mode == "terrain"
func _on_contours_toggled(pressed: bool) -> void: func _on_contours_toggled(pressed: bool) -> void:
_contours_on = pressed _contours_on = pressed
_sync_contours_to_builder() _sync_contours_to_builder()
if status_label != null:
_set_status("Höhenlinien %s — %s" % [
"FIXIERT AN" if _contours_on else "Fix aus",
"jetzt in jedem Werkzeug sichtbar (L oder Button schaltet zurück)."
if _contours_on else
"sichtbar nur noch im Terrain-Werkzeug (F1). L fixiert sie wieder."])
## Nach jedem Viewport-Rebuild: Nutzer-Wahl wieder anwenden — der Rebuild ## Nach jedem Viewport-Rebuild und nach JEDEM Werkzeug-Wechsel: die effektive
## baut das Terrain-Mesh (und damit dessen Shader-Uniform) neu. ## Wahl anwenden — der Rebuild baut das Terrain-Mesh (und damit dessen
## Shader-Uniform) neu, der Werkzeugwechsel blendet die Linien ein/aus.
func _sync_contours_to_builder() -> void: func _sync_contours_to_builder() -> void:
if view_builder == null: if view_builder == null:
return return
var terrain_view = view_builder.get("terrain_view") var terrain_view = view_builder.get("terrain_view")
if terrain_view != null and is_instance_valid(terrain_view): if terrain_view != null and is_instance_valid(terrain_view):
terrain_view.call("set_contours", _contours_on) terrain_view.call("set_contours", _contours_effective())
if contours_btn != null and contours_btn.button_pressed != _contours_on: if contours_btn != null and contours_btn.button_pressed != _contours_on:
contours_btn.set_pressed_no_signal(_contours_on) contours_btn.set_pressed_no_signal(_contours_on)

View file

@ -42,6 +42,7 @@ func _run_all() -> void:
_test_shortcut_undo() _test_shortcut_undo()
_test_terrain_hotkeys() _test_terrain_hotkeys()
_test_shortcuts_karte3() _test_shortcuts_karte3()
_test_contours_tool_coupling()
_finish() _finish()
@ -316,3 +317,87 @@ func _test_shortcuts_karte3() -> void:
# Aufräumen: Undo, damit spätere Gruppen (falls Testreihenfolge sich ändert) # Aufräumen: Undo, damit spätere Gruppen (falls Testreihenfolge sich ändert)
# nicht von diesem Objekt ausgehen. # nicht von diesem Objekt ausgehen.
main._unhandled_key_input(_press_key(KEY_Z, true)) main._unhandled_key_input(_press_key(KEY_Z, true))
## Karte t_89c0ec95: Höhenlinien NUR im Terrain-Werkzeug — Kopplung am
## Werkzeugwechsel (F1 ein, F2/F3/F4 aus), Fix über L / Button. Der Test
## drückt alles SYNCHRON durch _set_tool_mode bzw. _unhandled_key_input:
## die Sichtbarkeit kippt im selben Aufruf — der Beweis, dass kein
## _process-Poll nötig ist (0 Frames).
func _test_contours_tool_coupling() -> void:
print("Testgruppe: Höhenlinien-Werkzeug-Kopplung (t_89c0ec95)")
# Aufräumen aus der karte3-Gruppe: programmisches confirmed.emit() schließt
# das dirty-Dialog-Window NICHT — ein sichtbares Window sperrt das
# F/L-Tasten-Gate (ShortcutPolicy). Deshalb hier alle Windows zu.
for child in main.get_children():
if child is Window:
child.hide()
main._set_tool_mode("objects")
var terrain_view = main.view_builder.get("terrain_view")
_check(terrain_view != null, "Terrain-View existiert im Builder")
_check(str(main.get("tool_mode")) == "objects", "Start: Objekt-Werkzeug")
_check(not bool(terrain_view.get("_contours_pref")),
"Start: Höhenlinien AUS (kein Fix, kein Terrain-Werkzeug)")
# Regression zur obigen Root-Cause: Struktur-Änderung (Undo) baut das
# Terrain-Mesh NEU — die Linien dürfen NICHT auf Default „an“ zurück-
# springen (vor t_89c0ec95 geschah genau das nach jedem Strg+Z).
var before_obj: Dictionary = main.history.snapshot(["objects"])
(main.doc["objects"] as Array).append(
{"id": "test_contour_objekt", "pos": [2.0, 0.0, 2.0], "scale": 1.0,
"rot_y_deg": 0.0})
main.history.commit("Test: Kontur-Objekt", before_obj,
main.history.snapshot(["objects"]))
main._do_undo()
terrain_view = main.view_builder.get("terrain_view") # Rebuild → neue View
_check(terrain_view != null, "Undo: Terrain-View frisch vorhanden")
_check(not bool(terrain_view.get("_contours_pref")),
"Struktur-Änderung (Undo + Rebuild): Höhenlinien bleiben AUS im Objekt-Werkzeug")
# F1 → Terrain: Linien EIN, synchron im Wechselpunkt.
main._unhandled_key_input(_press_key(KEY_F1, false))
_check(str(main.get("tool_mode")) == "terrain", "F1: Terrain-Werkzeug an")
_check(bool(terrain_view.get("_contours_pref")),
"F1: Höhenlinien EIN (synchron, 0 Frames Poll)")
# Jedes andere Werkzeug: Linien wieder AUS.
main._unhandled_key_input(_press_key(KEY_F2, false))
_check(str(main.get("tool_mode")) == "objects", "F2: zurück zum Objekt-Werkzeug")
_check(not bool(terrain_view.get("_contours_pref")), "F2: Höhenlinien AUS")
main._unhandled_key_input(_press_key(KEY_F3, false))
_check(not bool(terrain_view.get("_contours_pref")), "F3 (Bauen): Höhenlinien AUS")
main._unhandled_key_input(_press_key(KEY_F4, false))
_check(not bool(terrain_view.get("_contours_pref")), "F4 (Spawns): Höhenlinien AUS")
main._unhandled_key_input(_press_key(KEY_F2, false))
# L = Fixieren: sichtbar sogar AUSSERHALB des Terrain-Werkzeugs.
main._unhandled_key_input(_press_key(KEY_L, false))
_check(bool(terrain_view.get("_contours_pref")),
"L: Höhenlinien FIXIERT AN (sichtbar im Objekt-Werkzeug)")
_check(main.contours_btn.button_pressed,
"L: Button „≈ Höhenlinien“ mitgesynced (pressed)")
_check(str(main.status_label.text).contains("FIXIERT"),
"L: Statuszeile meldet Fix AN")
# Fix bleibt über Werkzeugwechsel bestehen …
main._unhandled_key_input(_press_key(KEY_F1, false))
_check(bool(terrain_view.get("_contours_pref")), "Fix an: F1 lässt Linien an")
# … aber ein Werkzeugwechsel KANN bei Fix-an nie ausblenden. L im Terrain-
# Werkzeug löst den Fix: Linien bleiben (Werkzeug-Kopplung trägt weiter).
main._unhandled_key_input(_press_key(KEY_L, false))
_check(not bool(main.get("_contours_on")), "L im Terrain: Fix gelöst")
_check(bool(terrain_view.get("_contours_pref")),
"L im Terrain: Linien bleiben AN (Werkzeug-Kopplung trägt)")
_check(not main.contours_btn.button_pressed,
"L im Terrain: Button-Fix mitgesynced (unpressed)")
main._unhandled_key_input(_press_key(KEY_F2, false))
_check(not bool(terrain_view.get("_contours_pref")),
"F2 nach Fix-Lösung: Höhenlinien wieder AUS")
# Button-Weg (ohne L): Drücken des Buttons fixiert ditto.
main.contours_btn.set_pressed(true) # feuert toggled → _on_contours_toggled
_check(bool(terrain_view.get("_contours_pref")),
"Button: Fix AN fixiert Linien im Objekt-Werkzeug")
main.contours_btn.set_pressed(false)
_check(not bool(terrain_view.get("_contours_pref")),
"Button: Fix AUS blendet zurück (nur Terrain-Werkzeug)")

View file

@ -14,6 +14,7 @@ func _init() -> void:
_test_inputmap_actions() _test_inputmap_actions()
_test_fly_key_conflicts() _test_fly_key_conflicts()
_test_inputmap_actions_3() _test_inputmap_actions_3()
_test_contours_toggle()
_test_policy_3() _test_policy_3()
_test_fly_math() _test_fly_math()
_test_esc_policy() _test_esc_policy()
@ -306,6 +307,33 @@ func _test_inputmap_actions_3() -> void:
_check(ok, "%s → physische Taste %s" % [action, OS.get_keycode_string(int(f_keys[action]))]) _check(ok, "%s → physische Taste %s" % [action, OS.get_keycode_string(int(f_keys[action]))])
## Karte t_89c0ec95: L = Höhenlinien fixieren — Action-Registrierung +
## Kollisions-Freiheit (die nackte Taste L wird von keiner Editor-Action
## genutzt; der Haupt-Handler verlangt zusätzlich „ohne Strg“).
func _test_contours_toggle() -> void:
print("Testgruppe: Höhenlinien-Fix (Karte t_89c0ec95, Taste L)")
_check(InputMap.has_action("editor_contours_toggle"),
"Action existiert: editor_contours_toggle")
var l_ok := false
for ev in InputMap.action_get_events("editor_contours_toggle"):
var kev := ev as InputEventKey
if ev is InputEventKey and kev.physical_keycode == KEY_L:
l_ok = true
_check(l_ok, "editor_contours_toggle → physische Taste L")
var collision := false
for action in ShortcutKeys.ACTIONS:
if action == "editor_contours_toggle":
continue
for entry in ShortcutKeys.ACTIONS[action]:
if entry is int and int(entry) == KEY_L:
collision = true
elif entry is Dictionary and int(entry.get("key", KEY_NONE)) == KEY_L:
collision = true
_check(not collision, "Kollisions-Check: L ist sonst UNBESetzt (keine andere Action nutzt KEY_L)")
_check(not _matches(KEY_L, "editor_tool_terrain"), "L löst KEINEN Werkzeugwechsel aus")
_check(not _matches(KEY_L, "editor_help_overlay"), "L löst KEIN H aus")
## Karte 3/3: Pure Policy — F-Tasten-Gate (Textfeld/Dialog) + Dirty-Confirm. ## Karte 3/3: Pure Policy — F-Tasten-Gate (Textfeld/Dialog) + Dirty-Confirm.
func _test_policy_3() -> void: func _test_policy_3() -> void:
print("Testgruppe: ShortcutPolicy Karte 3/3 (F-Tasten-Gate, Dirty-Confirm)") print("Testgruppe: ShortcutPolicy Karte 3/3 (F-Tasten-Gate, Dirty-Confirm)")