Operator-Nachbesserung nach dem Eigenstaendigkeits-Beweis (exportierte App, kein Client/Godot im Dateisystem): - SRC_TEX wird GESUCHT statt fest verdrahtet: SCOPEDVR_TEX_DIR -> assets/textures/military_desert -> assets/textures -> Ordner der Demonstration_Textures*.png unter assets/. Findet er nichts, gibt es einen HINWEIS samt Loesung (SCOPEDVR_TEX_DIR=/pfad). - Texturen werden FLACH nach models/textures/<name>.png gespiegelt — die App sucht sie dort; im Client liegen sie verschachtelt. - Modell-Spiegel schliesst den Unterordner textures/ aus (skip_top): vorher galt er als 'ueberfluessig' und wurde bei JEDEM Lauf geloescht, der Textur-Spiegel legte ihn neu an -> Endlosschleife, --check nie sauber. Belegt: 2. Lauf 0 Aenderungen, --check Exit 0; exportierte App findet baum_kiefer_1/stein_mittel_1 aus models/, fehlende_glbs=0, ERGEBNIS: OK. |
||
|---|---|---|
| addons/modular_builder | ||
| docs | ||
| library | ||
| scenes | ||
| src | ||
| tests | ||
| theme | ||
| tools | ||
| utils | ||
| .gitignore | ||
| ADDON_LIZENZ.txt | ||
| export_presets.cfg | ||
| icon.svg | ||
| icon.svg.import | ||
| project.godot | ||
| README.md | ||
| README_INSTALL.md | ||
ScopedVR Map Editor
Standalone-PC-App zum Bauen von ScopedVR-Maps. Technisches Fundament: Godot 4.x (MIT-Lizenz, lizenzfrei, keine Fremd-Abhängigkeit). Creator sehen/brauchen Godot NIE — die App ist das Produkt (PLAN.md, Entscheidung 14).
⭐ Chef-Grundsatz (Sly, 15.10.): MAXIMALE NUTZERFREUNDLICHKEIT
„Der soll auf jeden Fall so nutzerfreundlich sein, wie es nur geht, damit echt richtig easy ist Maps zu bauen und es auch Spaß macht!"
Konkret heißt das für JEDE Editor-Karte:
- Deutsch, große Buttons, Klartext-Beschriftungen — kein Fachchinesisch.
- Klick statt Konsole: gewünschte Aktion per Maus erreichbar (ziehen, drehen, klicken), ohne Tastenkürzel auswendig zu lernen (Kürzel dürfen optional sein).
- Sofortiges visuelles Feedback (Objekt leuchtet beim Anfassen, Vorschau vor dem Platzieren, Undo mit STRG+Z).
- Die App hilft: ungültige Aktionen erklären WARUM („Spawn-Zone fehlt noch für Team Rot — klicke auf den Boden, um sie zu setzen").
- Test-Benchmark: Sly baut ohne Anleitung in < 10 Minuten eine kleine Map.
Philosophie (Entscheidung 20 — GESCHLOSSENER Baukasten)
- Objekte kommen ausschließlich aus der Spiel-Asset-Bibliothek (geprüfte Poly-Budgets).
- KEINE freien Mesh-Imports. Konsistenz + Performance statt unbegrenzter Freiheit.
- Performance-Prüfung ist eingebaut (Objekt-Count-/Poly-Limits), nicht optional.
MVP-Werkzeuge (Reihenfolge = Karten-Kette)
- Terrain — Höhenfeld bearbeiten (heben/senken/glätten), Sniper-Distanzen 100–800 m (Entscheidung 7).
- Objekt-Platzierung — Bibliothek-Browser, platzieren/drehen/verschieben.
- Spawn-Zonen — pro Team (TDM), Validierung gegen Regeln.
- Map-Metadaten — Name, Autor, Version, Wetter-Preset (mittag/abend/regen/nacht, siehe Weather-System 9ebe8ef/a296986).
- Performance-Check — Objekt-Count/Poly-Budget gegen die FPS-Baseline.
- Export —
.svmap-Paket (Format: docs/map_format.md im scopedvr-match-server Repo, Karte t_74976e9f).
Architektur (MVP)
- Godot 4.x Desktop-App (die Editor-UI IST Godot-Control-UI — pragmatisches MVP).
- Map-Datenmodell = 1:1 das svmap-Format (kein internes Zwischenformat → kein Konverter).
- Speichern/Laden direkt auf .svmap; Export = Kopie + Validierung.
Milestone-Zuordnung
M2 (siehe PLAN.md §6): Map-Paket-Format → Editor-MVP → erste offizielle Map (offenes Gelände) → Map-Repo/Release-Workflow über Forgejo (M3).
Status (M2, Karte t_40d855d0 — UX-Fundament FERTIG)
UX-Fundament auf dem App-Skelett (t_5badf371), nach dem Chef-Grundsatz gebaut:
(Unverändert darunter: svmap laden/speichern V1–V14 mit Prüfsummen-Interop,
Neue-Map-Dialog mit 4 Pflicht-Spawns pro Team, Orbit-Viewport mit Gitter/
Boden/Wetter-Stimmung — siehe Commit 84bc081 und svmap_io.gd.)
- Undo/Redo (
src/editor/action_history.gd): zentrale ActionHistory über die svmap-Ober-Blöcke (objects/terrain/spawn_zones— tiefe Kopien vor und nach jeder Änderung, merge_tags gegen Mausrad-Tick-Fluten, Max-Stufe 100). Strg+Z / Strg+Y UND große Buttons „↩ Rückgängig / ↪ Wiederholen" oben. Spätere Werkzeuge melden sich mitsnapshot(keys)vor undcommit(desc, before, after)nach der Änderung an — Terrain-Strokes und Spawn-Zonen landen damit automatisch in derselben History. - Objekt-Platzierung mit Ghost-Preview (
src/editor/interaction.gd): Bibliothek links (deutsche Namen + Poly-Zahl), Klick startet den Platzier-Modus — eine transparente Vorschau schwebt am Cursor auf dem Boden (Höhe kommt aus dem Terrain), Klick setzt, ESC bricht ab (Rechte Maustaste = Flug, das Objekt bleibt in der Hand — Karte t_2470de89), Mausrad dreht die Vorschau VOR dem Setzen (15°-Raster). Modus bleibt an für schnelles Mehrfachsetzen. Poly-Budget wird VOR dem Platzieren geprüft. - Auswahl-Anfassen: Klick wählt ein Objekt (orange + Emission), Ziehen verschiebt es (auf Terrain-Höhe geclampt in der Map), R-Taste ODER Mausrad dreht (15°-Raster, Shift+R zurück), Entf löscht. Auch über den Objekt-Baum wählbar (beide Wege bleiben synchron). Panel „Auswahl“ rechts zeigt Position/ Richtung + Bedienhinweise.
- Helfende Meldungen: Statusleiste unten erklärt nach jeder Aktion den NÄCHSTEN Schritt („Klicke in die Karte“, „Strg+Z holt es zurück“, Budget-Warnung ab 80 %). Fehler-Dialoge bleiben Klartext, keine Godot-Texte im sichtbaren UI.
- Deutsche, große UI: Schrift 16 px Basis (≥ 14 px überall), Buttons/ Klickflächen ≥ 40 px Höhe, Mausrad-Konflikt gelöst: Rad dreht Objekt/ Vorschau, wenn eines aktiv ist — sonst zoomt es die Kamera.
- Tests:
tests/test_ux.gd(History-Roundtrips setzen/löschen/verschieben/ drehen, Merge-Tag-Verhalten, Alias-Sicherheit der Snapshots, Kapazität, Terrain-Höhen-Abfrage, Platzhalter-Meshes). Lauf:godot --headless --path . --script res://tests/test_ux.gd
Bekannte Falle (15.10. live passiert): Nach git pull mit NEUEN
class_name-Skripten (z. B. action_history.gd) muss einmal
godot --headless --import laufen, bevor die GUI gestartet wird — sonst ist
der globale Klassen-Cache (.godot/) alt, main.gd wirft „Identifier not
declared" und das Fenster startet ohne UI. Symptom: Parse-Errors im App-Log
trotz grünem Test-Lauf (der ja selbst mit importiertem Cache lief).
Bibliothek: library/objects.json ist die Editor-Kopie der offiziellen
Registry aus dem Match-Server-Repo — neue Objekte DORT registrieren und hier
synchron ziehen (IDs sind der Vertrag, Entscheidung 20).
Status (M2, Karte t_3a998ae4 — Objekt-Bibliothek FERTIG)
Auf dem Terrain-Werkzeug (t_9aba04f1) aufgebaut, nach dem Chef-Grundsatz:
- Bibliothek-Browser mit Gruppen (
src/editor/library_browser.gd): Die 11 etablierten Objekte auslibrary/objects.json, sortiert in deutsche Klapp-Gruppen (Kisten & Barrieren / Bauwerke / Natur + automatisch „Sonstiges" für neue, noch ungruppierte IDs). Jeder Button zeigt ein 128-px-Thumbnail (library/thumbs/*.png— einmalig mitxvfb-run -a godot4 --rendering-driver opengl3 --path . --script res://tools/gen_thumbs.gdgerendert und committed; fehlt ein PNG, fällt der Button sauber aufs Text-Layout zurück). Deutsche Namen wohnen jetzt inLibraryBrowser(ohne UI → headless testbar). - Snap to Ground (
src/editor/object_ops.gd): Ein Klick auf „⚡ Alles auf den Boden setzen" holt ALLE schwebenden Objekte auf die Terrain-Höhe (z. B. nach dem Terrain-Formen) — EIN Undo-Eintrag für die ganze Aktion. Objekte, die schon auf dem Boden stehen, bleiben unangetastet. - Raster-Snap (1 m): CheckButton in den Objekt-Werkzeugen — beim Platzieren UND Ziehen rasten X/Z auf ganze Meter (Höhe folgt weiter dem Terrain). AUS = freies Platzieren wie bisher.
- svmap-Roundtrip: Objekte (Bibliotheks-ID + Pos/Rot/Scale) überleben
Speichern/Laden identisch, save→load→save bleibt byte-identisch
(
tests/test_library.gd). - Tests:
tests/test_library.gd(Bibliothek laden, Gruppen komplett/ überschneidungsfrei, Thumbnails 128×128, Raster-Snap, Snap-to-Ground + je Undo für setzen/drehen/verschieben/löschen über ALLE 11 Objekte, svmap-Roundtrip mit Objekten + Poly-Budget aus dem Katalog). - Desktop-Smoke:
godot … -- --library-demo [ordner] [--library-demo-quit]fährt Bibliothek/Platzierung/Schweben/Snap programmatisch durch und speichert Screenshots.
Noch offen (folgende Karten der MVP-Kette): Performance-Check-UI, Export-Workflow.
Status (M2, Karte t_c4162c5d — Spawn-Zonen FERTIG)
Auf der Objekt-Bibliothek (t_3a998ae4) aufgebaut, nach dem Chef-Grundsatz:
- Spawn-Zonen malen (
src/editor/spawn_tool.gd): Werkzeug „🚩 Spawn-Zonen malen“ — Team Blau 🔵 / Team Rot 🔴 (TDM-Konvention: IDs A…/B…, mapformat § spawn_zones), Klick setzt eine farbige flache Kreis-Zone auf dem Terrain (Vorschau-Kreis folgt der Maus), Radius 2–30 m per Regler. Zone anklicken → auswählen + ziehen (Terrain-Höhe bleibt), Entf löscht, Strg+Z nimmt JEDE Operation zurück (jede Zone = EIN History-Eintrag, Radius-Slider-Ticks sind merge-gekoppelt). - Live-Validierung (
src/editor/spawn_ops.gd): Block „Spawn-Check“ rechts bleibt STÄNDIG sichtbar und spiegelt exakt die Loader-Regeln (V11: ≥ 4 Spawn-Punkte pro Team · V7: Objekt-IDs in der Bibliothek) — z. B. „✅ Spawns Team Blau: 4 · ❌ Spawns Team Rot: 2 (mindestens 4 nötig)“ + Klartext-Hinweis, WIE die Zone ergänzt wird. Fehler zeigt der Editor VOR dem Export, nicht erst beim Speichern. - Map-Fertig-Check: Button „✅ Karte prüfen“ oben — Klartext-Liste
✅/❌ (Name, Autor, beide Teams, Objekt-IDs, Poly-Budget) in einem
Fenster; fehlt etwas, wackelt (Shake-Tween) der Button und die
Statusleiste sagt „Map ist noch nicht bereit — siehe Warnungen“.
Der harte Gate bleibt das Speichern (
SvmapIO.save_to_file— dieselbe_validate_core-Funktion, EINE Implementierung, kein Drift). - Export-Signierung: unverändert der eine Code-Pfad — Editor-Speichern
ruft
SvmapIO.sign_map(SHA-256 über kanonisierte Payload). Abnahme mit ECHTEM Server-Loader: Editor-Export durchSvmapLoader.parse_and_validateaus scopedvr-match-server gejagt → ok=true inkl. V13-Prüfsummen-Check (kein Copy-Paste-Drift, Interop bewiesen). - Radius-Persistenz: Der Zonen-Radius ist KEIN Formatfeld (spawn_zones
speichert Punkte) — er wohnt als
design_notes.spawn_radius_min der Map (Loader prüft design_notes nicht → rundtrip-sicher). Zonen sitzen AUF dem Terrain (terrain_height_at), egal wie hügelig die Map ist. - Tests:
tests/test_spawns.gd(52 Checks: setzen/ändern/löschen + je Undo/Redo mit Radius, Merge-Tags, Live-Status ✅/❌, ready_report grün/rot, Export→Re-Import identisch + byte-identischer Roundtrip, Zone auf Terrain-Höhe). Parse-Check: 23 Scripts, 0 Fehler. - Desktop-Smoke:
godot … -- --spawns-demo [ordner] [--spawns-demo-quit]fährt Zonen-Übersicht → Live-Check-Alarm → Undo → „Karte prüfen“ programmatisch durch und speichert Screenshots.
Status (M2, Karte t_7567a06f — Objekt-Ops: Duplizieren + Hoch/Runter + Spiegeln)
Auf dem UX-Fundament (t_40d855d0) und der Objekt-Bibliothek (t_3a998ae4) aufgebaut, nach dem Chef-Grundsatz (Klick statt Konsole, deutsche UI, Undo für alles):
- Duplizieren (
⧉ Duplizieren-Button + Strg+D): Die Kopie des ausgewählten Objekts hängt +2 m in X versetzt daneben (Rasterversatz, Karte t_c46d31c2; Füßpunkt-Höhe unverändert, mit Raster-Snap eingerastet, wenn an) und ist DIREKT angewählt — sie lässt sich gleich weiterziehen/drehen/löschen. Drehung, Größe und Höhe werden übernommen. Bei Mehrfachauswahl werden ALLE Objekte kopiert (EIN Undo-Schritt). Poly-Budget und Objekt-Limit werden VOR dem Kopieren geprüft (Klartext-Meldung, was zu tun ist). EIN Undo-Schritt. - Anheben/Absenken (
▲ Anheben / ▼ Absenken+ Bild↑/Bild↓): Objekte ändern die Höhe in 0,25-m-Schritten. MEHRERE Klicks in Serie = EIN Undo-Schritt. Design-Entscheidungen, dokumentiert:- Die Höhe wohnt direkt in
object.pos.y— das svmap-Format erlaubt freie y-Werte innerhalb der Match-Grenzen (Loader-Regel V9), deshalb ist KEIN Extra-Feld im Dateiformat nötig und die Loader-Kompatibilität bleibt unangetastet (bewiesen intests/test_ux.gd: Erhöhtes Objekt überlebt gespeichern → laden intakt (Höhe bleibt exakt)). - Absenken stoppt an der Terrain-Höhe am Objektstandort — nichts wird
in Hügel begraben. Steckt ein Objekt im Boden (z. B. nach dem
Terrain-Formen), bewegt Absenken es NICHT, und die Statusleiste erklärt,
dass
▲ Anhebenoder⚡ Alles auf den Boden setzenhilft. - Anheben hat als Obergrenze die Match-Grenze
bounds.max.y— höher passt der Server nicht (V9). - Ziehen behält die Höhe: Ein angehobenes Objekt schwebt beim Verschieben in derselben Höhe über dem (neuen) Boden weiter; bodennah bleibt bodennah.
- Die Auswahl-Anzeige zeigt die Höhe mit („+0,25 m über dem Boden“).
- Die Höhe wohnt direkt in
- Spiegeln (
⇄ Links↔Rechts/⇅ Vor↔Zurück): Das Objekt wird AN SEINER STelle gespiegelt — Position bleibt, die Blickrichtung dreht:- links↔rechts (Welt-X-Spiegelung):
rot_y_deg → −rot - vor↔zurück (Welt-Z-Spiegelung):
rot_y_deg → 180° − rot(Herleitung im Quellcode: gespiegelter Richtungs-Vektor = gespiegelter Winkel; jede Spiegelung ist dadurch selbstinvers — zweimal spiegeln = Ausgangszustand.) Die Rotation wird mitgespiegelt, wie bestellt. Bewusst NICHT um die Kartemitte gespiegelt: das würde das Objekt quer über die Map springen lassen — überraschend für Einsteiger. Klartext in Buttons + Tooltip.
- links↔rechts (Welt-X-Spiegelung):
- Alles über ActionHistory: Snapshot vor/nach JEDE Aktion (Duplizieren = EIN Schritt, Anheben-Serie = EIN Schritt via Merge-Tag, Spiegeln = EIN Schritt). Statusleiste erklärt nach jeder Aktion den nächsten Schritt und die Grenzen auf Deutsch.
- Tests:
tests/test_ux.gdauf 90 Checks erweitert (42 neu): Duplizieren (Raster/ohne Raster/Undo-Roundtrip/Index-Schutz), Anheben/ Absenken (Schrittweite, Boden-Stopp, Deckel bounds.max, versteckt-Regel, Merge-Tags), Spiegeln (X/Z-Mapping, Selbstinvers, Position unverändert), svmap-Roundtrip mit angehobener Höhe.godot … --quit-aftersmoke: UI baut alle neuen Buttons fehlerfrei.
Status (M2, Karte t_f6f29d86 — Auswahl-System FERTIG)
Mehrfachauswahl + Gruppieren + Gruppen-Verschieben, auf dem UX-Fundament (t_40d855d0) aufgebaut, nach dem Chef-Grundsatz:
- Mehrfachauswahl (
src/editor/interaction.gd): Umschalt+Klick fügt ein Objekt hinzu/entfernt es, Rahmen-Aufziehen (Rubberband) über leeren Boden wählt ALLE Objekte im Rahmen (Umschalt + Rahmen = zusätzliche zur Auswahl). Loser Klick auf leere Fläche hebt die Auswahl auf. ALLE markierten Objekte färben sich orange, das Auswahl-Panel rechts listet sie namentlich auf (ab 9: „… und N weitere“). Projektions-Mathe liegt insrc/editor/selection_math.gd(headless getestet). - Gruppieren: Buttons „🔗 Gruppieren / ⛓ Gruppe lösen“ im Auswahl-Panel
- Kürzel Strg+G / Strg+Umschalt+G. Eine Gruppe braucht ≥ 2 Objekte. Gruppen-Mitglieder ziehen und drehen GEMEINSAM — ein Griff an ein Gruppen-Mitglied nimmt automatisch die ganze Gruppe (und markiert sie), die relative Anordnung bleibt exakt erhalten. Drehen geschieht um den Gruppen-Mittelpunkt. „Gruppe lösen“ befreit ALLE Mitglieder (auch die nicht mitgewählten), Strg+Z baut sie wieder zusammen.
- ENTSCHIEDUNG Gruppen-Persistenz: Gruppen-Zugehörigkeit liegt als
OPTIONALES Objekt-Feld
"group"(int ≥ 0, abwesend = ungruppiert) DIREKT im svmap-Format — nicht als Editor-Sitzungsstatus. Damit überleben Gruppen Speichern/Laden UND Undo/Redo (ActionHistory kopiert den objects-Block tief, das Feld reist mit). Loader-Kompatibilität nachgewiesen (scopedvr-match-serversrc/maps/svmap_loader.gd): V4 prüft nur Pflichtfelder, unbekannte Objekt-Keys werden nicht abgelehnt, die SHA-256-Prüfsumme läuft über das ganze kanonisierte Dict (Feld reist automatisch mit). Alte Maps ohne Feld bleiben 1:1 ladbar,format_versionbleibt 1 — KEIN Version-Bump, KEINE Server-Loader-Änderung nötig. Format-Doku-Anpassung (map_format.md im Server-Repo) als Folge-Karte. - Gruppen-Verschieben + Undo: Ziehen einer Mehrfachauswahl oder Gruppe bewegt ALLE beteiligten Objekte (Terrain-Clamp PRO Objekt: X/Z bleiben in der Map, Y = Terrain-Höhe an der neuen Stelle) — EINE Aktion = EIN ActionHistory-Schritt (auch gemeinsames Drehen, Mausrad-Ticks derselben Auswahl sind merge-gekoppelt). Löschen löscht die ganze Auswahl in EINEM Schritt.
- Tests:
tests/test_ux.gderweitert auf 52 Checks (Gruppen- gruppieren/lösen/IDs, gemeinsames Verschieben mit Terrain-Clamp, Drehen um die Mitte mit Anordnungs-Erhalt, EIN-Schritt-Undo/Redo, svmap-Roundtrip inkl. Prüfsumme + alte-Map-Kompatibilität, Rubberband-Projektion inkl. Kamera-Rückseiten-Filter). Kompletterun_tests.sh-Suite grün (206 Checks). - Desktop-Smoke:
godot … -- --groups-demo [ordner] [--groups-demo-quit]fährt Mehrfachauswahl → Gruppieren → gemeinsames Ziehen/Drehen → Undo programmatisch durch und speichert Screenshots.
Karte testen (M2, Karte t_b84af40f — FERTIG)
Button „▶ Karte testen“ oben (auch im Datei-Menü) startet die AKTUELLE Map — auch ungespeicherte! — sofort als Spiel in einem EIGENEN Fenster. Der Editor bleibt offen. Im Spiel: WASD laufen, Maus umsehen, Shift sprinten, Leertaste springen, ESC beendet das Test-Fenster sauber (kein Prozess-Kill nötig).
- Temp-Export (
src/editor/test_run.gd): Die Map wird nachuser://testrun/<name>.svmapexportiert (deterministischer Name aus dem Map-Namen, erneuter Testlauf überschreibt) — über dieselbeSvmapIO.save_to_file-Validierung wie das echte Speichern. Ist die Map noch nicht lauffähig (z. B. Spawn-Zonen fehlen), kommt der Klartext-Block mit den fehlenden Punkten, GESTARTET wird nichts. - Client-Suche (erste Treffer-Zeile gewinnt):
- Konfigurationsdatei
user://scopedvr_editor.cfg:[test] client_dir="/pfad/zu/scopedvr-client" godot_path="/pfad/zu/godot" ; nur nötig, wenn der Editor NICHT über Godot läuft - Klon neben dem Editor:
<Editor-Ordner>/../scopedvr-client(erkennbar anproject.godot).
- Konfigurationsdatei
- Start: Der Client läuft als eigener Godot-Prozess
(
godot --path <client> -- --testmap <map.svmap> --mock-master) — kein Master, kein Match-Server, alles lokal. Godot-Binary = das, unter dem der Editor selbst läuft. - Tests:
tests/test_testrun.gd(14 Checks: Temp-Export mit Roundtrip, ungültige Map blockiert, Client-Suche inkl. Konfig-Vorrang, Godot-Findung, exakte Argumentliste). Parse-Check umfassttest_run.gd.
Status (M2, Karte t_c46d31c2 — Tastatur-Shortcuts 1/3: Navigation + Auswahl + Löschen FERTIG)
Tastenkürzel-Karte 1 von 3 (Sly-Freigabe 16.10., finale Belegung).
docs/tasten.md ist jetzt die deutsche Source of truth für ALLE
Shortcut-Karten — Karten 2/3 ergänzen dort.
- Konventionen (alle Karten): Tastaturcode-basiert — InputMap-Actions mit
PHYSISCHEN
KEY_*-Konstanten (src/editor/shortcut_keys.gd, registriert inmain._ready, idempotent). Physische Codes = deutsche (QWERTZ) und Windows-Layouts identisch, keine OS-Hardcodes. Jede Objekt-Operation = EIN ActionHistory-Eintrag (Ausnahme: reine Kamera-Aktionen). - Freelook-Flug: Rechte Maustaste GEDACHT halten = Umsehen + Flug
(W/S/A/D + Leertaste hoch/Shift runter, Strg = ×3, Alt = ×0,3, Mausrad =
Grundgeschwindigkeit DAUERHAFT). Umschalt+F = Flug dauerhaft togglen.
Orbit bleibt Default —
beim Flug-Exit werden Ziel/Winkel/Abstand aus Flugposition/Blickrichtung
zurückgerechnet (kein Kamera-Sprung, getestet). Mathe pur in
src/editor/fly_math.gd, Kamera dünn (src/viewport/orbit_camera.gd). Konflikt-Auflösung: RMB hat ABSOLUTEN Vorrang für den Flug — in JEDEM Werkzeugzustand (Terrain, Bauen, Spawn, Platzieren; Karte t_2470de89, keinrmb_filtermehr), Mausrad im Flug gehört dem Tempo (interaction blockt). - F = Auswahl ins Bild zentrieren — Orbit-Ziel wandert auf den Auswahl-
Mittelpunkt (Anker + halbe Mesh-Höhe,
SelectionMath.focus_center); im Flug dreht sich nur die Blickrichtung. - Esc = Prioritätskette Werkzeug verlassen → Ghost-Preview abbrechen →
Auswahl aufheben, als pure, headless-getestete Funktion
(
src/editor/shortcut_policy.gd). - Entf (DELETE) = Auswahl SOFORT löschen ohne Rückfrage (Sly-Yolo) — wirkt auf Szene-Auswahl UND Objektbaum-Markierung (Baum und Szene sind synchron), Strg+Z deckt es ab. War schon mehrfach-fähig, jetzt getestet (EIN Undo-Schritt holt ALLE zurück).
- Strg+D = Auswahl duplizieren: Kopie(n) +2 m in X (Rasterversatz),
Füßpunkt unverändert; bei Mehrfachauswahl ALLE Objekte mit EINEM
Undo-Schritt, Budget/Limit gesammelt VORHER geprüft
(
ObjectOps.duplicate_objects). - Strg+LMB = Mehrfachauswahl umschalten (Objektbaum: SELECT_MULTI + native Strg+Klick-Logik, spiegelt sich in die Viewport-Auswahl und umgekehrt). Bestandsaktionen (Löschen, Duplizieren, Ziehen, Gruppieren) wirken auf die GANZE Mehrfachauswahl.
- Tests:
tests/test_shortcuts.gdNEU (70 Checks: InputMap-Actions inkl. Idempotenz, Freelook-Mathe, Esc-Prioritäten, Duplizieren +2 m X mit Undo-Roundtrip, Entf-Mehrfachauswahl gegen die ECHTE interaction.gd, Focus-Mittelpunkt, Kamera Flug-Roundtrip). Alle 8 Suiten grün (571 Checks), Builder-Export 21/0, Parse-Check aller geänderten Scripts (tools/parse_check_shortcuts.sh).