UX: ActionHistory restored Blöcke in-place (Alias-Sicherheit), Terrain-Test Koordinaten korrigiert

This commit is contained in:
Hermes (godot-vr) 2026-10-15 09:47:26 +00:00
parent 602cbc3402
commit ccf595de30
2 changed files with 31 additions and 7 deletions

View file

@ -79,12 +79,15 @@ func commit(desc: String, before: Dictionary, after: Dictionary, merge_tag: Stri
## Letzte Aktion zurücknehmen. Rückgabe: Beschreibung ("" = nichts da). ## Letzte Aktion zurücknehmen. Rückgabe: Beschreibung ("" = nichts da).
## Restore läuft IN-PLACE: doc["objects"] etc. behalten ihre Identität (Array/
## Dict-Objekt wird geleert und neu befüllt) — bezogene Referenzen (Tests,
## Ansichten) werden nicht zu Stale-Schnappschüssen.
func undo() -> String: func undo() -> String:
if not can_undo(): if not can_undo():
return "" return ""
var entry: Dictionary = entries[index] var entry: Dictionary = entries[index]
for key in entry["before"]: for key in entry["before"]:
doc[key] = entry["before"][key].duplicate(true) if entry["before"][key] != null else null _restore_block(key, entry["before"][key])
index -= 1 index -= 1
return str(entry.get("desc", "")) return str(entry.get("desc", ""))
@ -96,5 +99,25 @@ func redo() -> String:
index += 1 index += 1
var entry: Dictionary = entries[index] var entry: Dictionary = entries[index]
for key in entry["after"]: for key in entry["after"]:
doc[key] = entry["after"][key].duplicate(true) if entry["after"][key] != null else null _restore_block(key, entry["after"][key])
return str(entry.get("desc", "")) return str(entry.get("desc", ""))
func _restore_block(key: String, value: Variant) -> void:
if value == null:
doc.erase(key)
return
# Ganzen Block (Array/Dict) in-place neu befüllen — Identität bleibt erhalten.
var source: Variant = value.duplicate(true)
if source is Array:
var arr: Array = doc.get(key, [])
arr.clear()
arr.append_array(source)
doc[key] = arr
elif source is Dictionary:
var dict: Dictionary = doc.get(key, {})
dict.clear()
dict.merge(source)
doc[key] = dict
else:
doc[key] = source

View file

@ -212,10 +212,11 @@ func _test_terrain_height() -> void:
"heightmap_r16_b64": Marshalls.raw_to_base64(bytes), "heightmap_r16_b64": Marshalls.raw_to_base64(bytes),
} }
var doc2 := {"terrain": slope} var doc2 := {"terrain": slope}
_check(absf(SvmapDocument.terrain_height_at(doc2, 0.0, 0.0) - 0.0) < 0.5, "Gradient: Nordkante ≈ 0 m") _check(absf(SvmapDocument.terrain_height_at(doc2, 0.0, -80.0) - 0.0) < 0.5, "Gradient: Nordkante (z=-80) ≈ 0 m")
var mid := SvmapDocument.terrain_height_at(doc2, 0.0, 80.0) var mid := SvmapDocument.terrain_height_at(doc2, 0.0, 0.0)
_check(absf(mid - 50.0) < 1.0, "Gradient: Mitte ≈ 50 m (ist %.1f)" % mid) _check(absf(mid - 50.0) < 1.0, "Gradient: Mitte (z=0) ≈ 50 m (ist %.1f)" % mid)
_check(absf(SvmapDocument.terrain_height_at(doc2, 0.0, 160.0) - 100.0) < 0.5, "Gradient: Südkante ≈ 100 m") _check(absf(SvmapDocument.terrain_height_at(doc2, 0.0, 80.0) - 100.0) < 0.5, "Gradient: Südkante (z=+80) ≈ 100 m")
_check(absf(SvmapDocument.terrain_height_at(doc2, 0.0, 160.0) - 100.0) < 0.5, "Hinter der Kante wird geclampt (100 m)")
_check(absf(SvmapDocument.terrain_height_at(doc2, 5000.0, -900.0) - 0.0) < 0.6, "Außerhalb-Query wird geclampt (keine Abstürze)") _check(absf(SvmapDocument.terrain_height_at(doc2, 5000.0, -900.0) - 0.0) < 0.6, "Außerhalb-Query wird geclampt (keine Abstürze)")