61 lines
2.8 KiB
GDScript
61 lines
2.8 KiB
GDScript
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ß
|