extends RefCounted class_name MoveMath ## Shortcuts-Mathe für Karte 2/3 (t_55257792) — bewusst pure Funktionen ## (kein Knoten, keine Kamera): Pfeiltasten-Raster-Schritt + Terrain- ## Pinselgrößen-Zyklus. tests/test_shortcuts.gd prüft headless; main.gd und ## interaction.gd sind nur die dünnen Anwender. ## ## Pfeiltasten-Konvention (Editor-Üblichkeit): „↑" bewegt die Auswahl VON der ## Kamera WEG (in Blickrichtung, horizontal), „↓" auf sie zu, links/rechts ## entsprechend quer. Die Blickrichtung wird auf die NÄCHSTE Weltachse ## gerastet (Godot-Editor-Konvention) — eine Pfeiltaste verschiebt also immer ## exakt entlang X oder Z, nie diagonal. const NUDGE_STEP_M := 2.0 # eine Rasterzelle pro Tastendruck (Karte 2/3) ## Pfeil-Richtung → Welt-Delta (2 m). yaw_deg = Kamera-Gierwinkel (Orbit ODER ## Flug), fwd = +1 (↑) / −1 (↓), side = +1 (rechts) / −1 (links). ## Die horizontale Blickrichtung (FlyMath.forward_from_euler(yaw, 0)) wird auf ## die nächste Weltachse gerastet: |z| >= |x| → Z-Achse, sonst X-Achse ## (Gleichstand → Z, deterministisch). Rechts = Blickrichtung × oben gekreuzt. static func nudge_delta(yaw_deg: float, fwd: int, side: int) -> Vector3: var f := forward_from_euler(yaw_deg, 0.0) var axis := Vector3.ZERO if absf(f.z) >= absf(f.x): axis = Vector3(0.0, 0.0, -1.0) if f.z <= 0.0 else Vector3(0.0, 0.0, 1.0) else: axis = Vector3(-1.0, 0.0, 0.0) if f.x <= 0.0 else Vector3(1.0, 0.0, 0.0) var right := axis.cross(Vector3.UP) return (axis * float(fwd) + right * float(side)) * NUDGE_STEP_M ## Horizontale Blickrichtung (nur Yaw — identische Formel wie FlyMath, hier ## kopiert statt Abhängigkeit, damit die Datei ohne FlyMath-Load testbar bleibt). static func forward_from_euler(yaw_deg: float, _pitch_deg: float) -> Vector3: var yaw := deg_to_rad(yaw_deg) return Vector3(-sin(yaw), 0.0, -cos(yaw)) # ------------------------------------------------- Terrain-Pinsel-Presets ---- ## Pinselgröße-Zyklus durch die 3 Presets (Klein 4 m / Mittel 12 m / Groß 32 m, ## wie die Buttons im Terrain-Panel). up = ] (vergrößern), down = [ (verkleinern). ## Bei einem FREIEN Slider-Wert (nutzergezogen) geht ] zum nächsten Preset ## ÜBER dem Wert, [ zum nächsten DARUNTER — am Rand wird zyklisch gewrappt. ## Rückgabe: der neue Radius in Metern. static func brush_next_preset(current_m: float, up: bool) -> float: var presets := [4.0, 12.0, 32.0] if up: for r in presets: if r > current_m + 0.001: return r return presets[0] # zyklisch: über dem größten → wieder Klein # Abwärts: das NÄCHSTE Preset UNTER dem Wert (größtes darunter) — # rückwärts iterieren, sonst fände die Schleife immer Klein zuerst. var i := presets.size() - 1 while i >= 0: if presets[i] < current_m - 0.001: return presets[i] i -= 1 return presets[presets.size() - 1] # zyklisch: unter dem kleinsten → Groß