- Bibliothek-Browser: 11 etablierte Objekte in deutschen Klapp-Gruppen (Kisten & Barrieren / Bauwerke / Natur, neue IDs wandern nach Sonstiges) - 128-px-Thumbnails einmalig gerendert (tools/gen_thumbs.gd, xvfb) und committed; fehlendes PNG = sauberer Text-Fallback (LibraryBrowser) - Snap to Ground: ein Klick setzt ALLE schwebenden Objekte auf Terrain-Höhe, EIN Undo-Eintrag (ObjectOps.snap_to_ground) - Raster-Snap (1 m): Toggle — rastet Platzieren und Ziehen auf ganze Meter - Deutsche Namen nach LibraryBrowser verschoben (headless testbar) - tests/test_library.gd: 47 Checks (Bibliothek, Gruppen, Thumbnails, Snap, CRUD+Undo über alle Objekte, svmap-Roundtrip byte-identisch, Poly-Budget) - Desktop-Smoke: --library-demo erzeugt Screenshots (lokal via xvfb verifiziert) - UI-Layout: linke Spalte min 909→797 px, Statusleiste wieder vollständig sichtbar
34 lines
1.4 KiB
GDScript
34 lines
1.4 KiB
GDScript
extends RefCounted
|
|
class_name ObjectOps
|
|
## Objekt-Operationen des Editors (Karte t_3a998ae4) — bewusst pure Funktionen
|
|
## (kein UI, kein Knoten): Snap-to-Ground und Raster-Snap. main.gd/interaction.gd
|
|
## rufen auf, tests/test_library.gd prüft headless.
|
|
|
|
const GRID_M := 1.0 # Raster-Snap-Weite (1 m — handhabbar für Objekte)
|
|
const FLOAT_EPSILON := 0.01 # ab dieser Abweichung gilt ein Objekt als "schwebend"
|
|
|
|
|
|
## ALLE Objekte auf die Terrain-Höhe setzen (Snap to Ground). Objekte hängen
|
|
## z. B. nach dem Terrain-Formen in der Luft — ein Klick holt sie runter.
|
|
## Rückgabe: Anzahl geänderter Objekte (0 = alles stand schon auf dem Boden).
|
|
static func snap_to_ground(doc: Dictionary) -> int:
|
|
var changed := 0
|
|
var objects: Array = doc.get("objects", [])
|
|
for obj in objects:
|
|
if not (obj is Dictionary):
|
|
continue
|
|
var pos: Array = obj.get("pos", [0.0, 0.0, 0.0])
|
|
if (pos as Array).size() != 3:
|
|
continue
|
|
var h := SvmapDocument.terrain_height_at(doc, float(pos[0]), float(pos[2]))
|
|
if absf(float(pos[1]) - h) > FLOAT_EPSILON:
|
|
obj["pos"] = [float(pos[0]), h, float(pos[2])]
|
|
changed += 1
|
|
return changed
|
|
|
|
|
|
## Eine Koordinate aufs Raster legen (Raster-Snap). grid_m <= 0 oder aus = no-op.
|
|
static func snap_coord(value: float, enabled: bool, grid_m := GRID_M) -> float:
|
|
if not enabled or grid_m <= 0.0:
|
|
return value
|
|
return roundf(value / grid_m) * grid_m
|