scopedvr-map-editor/tests/probe_platzierung_ident.gd

106 lines
4.2 KiB
GDScript

extends SceneTree
## Identitäts-Vertrag, PLATZIERUNG (Karte t_e166e656): dieselben Objekte
## (15°-/45°-Kippung + Legacy-Fallback) laufen durch alle DREI Loader —
## A) Editor (SvmapIO.objekt_rotation + KolliderBau.hindernis_aabb)
## B) Client (svmap_world._objekt_rotation + hindernis_aabb)
## C) Server (svmap_loader._objekt_rotation + hindernis_aabb)
## Jeder druckt `IDENT <name>=<wert>`-Zeilen; der Runner (run_platzierung_
## identitaet.sh) verlangt IDENTISCHE Zeilen über alle drei Projekte.
## Das Skript liegt im EDITOR-Repo und wird je Projekt gefahren:
## godot4 --headless --path <projekt> -s <abs>/tests/probe_platzierung_ident.gd
##
## Bewusst load() statt class_name: das Skript läuft in DREI Projekten —
## fremde class_name-Referenzen wären schon PARSE-Fehler im falschen Projekt.
const OBJEKTE := [
# Kippen 15° + Y-Drehung + scale 1.5 (Sly-Abnahme-Fall, klein gewählt).
{"id": "probe_a", "pos": [5.0, 3.0, 2.0], "rot_y_deg": 30.0, "scale": 1.5,
"rot": [15.0, 30.0, 0.0]},
# Kippen 45° um Z (Stein-Anhalt-Fall).
{"id": "probe_b", "pos": [-2.0, 1.0, 7.0], "rot_y_deg": 0.0, "scale": 1.0,
"rot": [0.0, 0.0, 45.0]},
# Legacy-Fallback: KEIN rot-Feld → rot_y_deg = 37 (alte Karte unverändert).
{"id": "probe_c", "pos": [0.0, 0.0, 0.0], "rot_y_deg": 37.0, "scale": 2.0},
]
const COL := {"shape": "box", "size": [2.0, 4.0, 3.0]}
## ALLES Trimesh (t_ff7fc919): dieselben gekippten Fälle gegen einen echten
## Trimesh-Eintrag aus der Registry (Quelle-Datei — in ALLEN DREI Repos
## identisch synchronisiert) + der Fallback-Fall (Quelle fehlt → Mess-AABB
## aus size). Die AABB kommt bei Trimesh aus der Dreiecks-Suppe.
const COL_TRIMESH := {
"shape": "trimesh", "size": [4.9527, 1.105, 2.1942],
"quelle": "kollisions/barrier_006.json",
}
const COL_TRIMESH_FEHLT := {
"shape": "trimesh", "size": [2.0, 4.0, 3.0],
"quelle": "kollisions/gibts_nicht.json",
}
## Skript-Pfade je Projekt (config/name → Loader-Skripte).
const SKRIPTE := {
"ScopedVR Map Editor": {
"rotation": "res://src/svmap/svmap_io.gd",
"hindernis": "res://src/svmap/kollider_bau.gd",
"rot_funktion": "objekt_rotation",
},
"ScopedVR": {
"rotation": "res://scripts/world/svmap_world.gd",
"hindernis": "res://scripts/world/svmap_world.gd",
"rot_funktion": "_objekt_rotation",
},
"ScopedVR Match-Server": {
"rotation": "res://src/maps/svmap_loader.gd",
"hindernis": "res://src/maps/svmap_loader.gd",
"rot_funktion": "_objekt_rotation",
},
}
func _initialize() -> void:
# Im -s-Modus liefert ProjectSettings config/name teils null — stattdessen
# die project.godot direkt lesen (config/name="...").
var projekt := ""
var fa := FileAccess.open("res://project.godot", FileAccess.READ)
if fa != null:
for zeile in fa.get_as_text().split("\n"):
var t := zeile.strip_edges()
if t.begins_with("config/name="):
projekt = t.trim_prefix("config/name=").strip_edges().trim_prefix("\"").trim_suffix("\"")
break
var cfg: Dictionary = SKRIPTE.get(projekt, {})
if cfg.is_empty():
printerr("IDENT FAIL: unbekanntes Projekt ", projekt)
quit(1)
return
var rot_skr: Script = load(str(cfg["rotation"]))
var hin_skr: Script = load(str(cfg["hindernis"]))
if rot_skr == null or hin_skr == null:
printerr("IDENT FAIL: Loader-Skripte nicht ladbar in ", projekt)
quit(1)
return
var rot_funk: String = str(cfg["rot_funktion"])
for i in OBJEKTE.size():
var obj: Dictionary = OBJEKTE[i]
var rot: Vector3 = rot_skr.call(rot_funk, obj)
print("IDENT rot_%d=%s" % [i, _fmt(rot)])
var aabb: AABB = hin_skr.call("hindernis_aabb", obj, COL, float(obj.get("scale", 1.0)))
print("IDENT aabb_%d=%s" % [i, _fmt_aabb(aabb)])
# ALLES Trimesh (t_ff7fc919): dieselben Fälle gegen die Suppe.
print("IDENT aabb_tri_%d=%s" % [i, _fmt_aabb(
hin_skr.call("hindernis_aabb", obj, COL_TRIMESH, float(obj.get("scale", 1.0))))])
print("IDENT aabb_trifehlt_%d=%s" % [i, _fmt_aabb(
hin_skr.call("hindernis_aabb", obj, COL_TRIMESH_FEHLT, float(obj.get("scale", 1.0))))])
print("IDENT_PROJEKT=", projekt)
quit(0)
func _fmt(v: Vector3) -> String:
return "%.6f,%.6f,%.6f" % [v.x, v.y, v.z]
func _fmt_aabb(a: AABB) -> String:
return "%.6f,%.6f,%.6f|%.6f,%.6f,%.6f" % [
a.position.x, a.position.y, a.position.z, a.size.x, a.size.y, a.size.z]