124 lines
5.2 KiB
GDScript
124 lines
5.2 KiB
GDScript
extends SceneTree
|
|
## M4-Beweis (t_ffa207b1): Bau-Teile + Spawn-Zonen werden im Symmetrie-Modus
|
|
## gespiegelt. Ein Blick von oben auf eine 256-m-Karte: links Original
|
|
## (Fundament + Wand, blaue Zone), rechts der Zwilling (gleiche kind_id,
|
|
## gespiegelte Drehung; rote Zone im Gegner-Team).
|
|
##
|
|
## xvfb-run -a /opt/data/home/bin/godot4 --rendering-driver opengl3 --path . \
|
|
## --resolution 1600x900 -s res://tests/probe_m4_mirror_render.gd
|
|
##
|
|
## Ausgabe: /tmp/m4_mirror_beweis.png + Prüfzeilen (Zwillinge vorhanden,
|
|
## Positionen gespiegelt). Nur DER Beweis-Lauf nutzt die echte Code-Kette
|
|
## (BuildOps.place_mirrored / SpawnTool.spawn_mirror_add) — genau wie die Suite.
|
|
|
|
const SpawnTool := preload("res://core/editor/spawn_tool.gd")
|
|
|
|
const POINT := SymmetryCore.Mode.POINT
|
|
|
|
|
|
func _initialize() -> void:
|
|
var manifest: Dictionary = JSON.parse_string(FileAccess.get_file_as_string("res://library/objects.json"))
|
|
var doc: Dictionary = SvmapDocument.create_new("M4-Symmetrie-Beweis", 256.0, "mittag")
|
|
|
|
# --- Bau-Teile: Original West, Zwilling Ost (echte M4-Code-Kette) --------
|
|
var fund := BuildOps.make_piece("fundament", Vector3(-21.0, 0.0, 3.0), 0.0)
|
|
BuildOps.ensure_block(doc).append(fund)
|
|
var fund_msg: String = BuildOps.place_mirrored(doc, fund, POINT)
|
|
var wand := BuildOps.make_piece("wand", Vector3(-20.0, 0.2, -2.0), 90.0)
|
|
BuildOps.ensure_block(doc).append(wand)
|
|
var wand_msg: String = BuildOps.place_mirrored(doc, wand, POINT)
|
|
|
|
# --- Spawn: blaue Zone West → rote Zwilling-Zone Ost ---------------------
|
|
var point := SpawnOps.add_zone(doc, 0, -100.0, 30.0)
|
|
var spawn_res: Dictionary = SpawnTool.spawn_mirror_add(doc, 0, str(point["id"]), POINT)
|
|
|
|
# --- Prüfzeilen (echte Werte, keine Behauptungen) -------------------------
|
|
var fehler: Array = []
|
|
_check(BuildOps.piece_count(doc) == 4, "4 Bauteile (2 Paare)", fehler)
|
|
_check(fund_msg == "" and wand_msg == "", "beide Bau-Teile still gespiegelt", fehler)
|
|
var twin_fund := _piece_at_pos(doc, 21.0)
|
|
_check(not twin_fund.is_empty(), "Fundament-Zwilling bei +21", fehler)
|
|
var twin_wand := _wand_twin(doc)
|
|
_check(not twin_wand.is_empty(), "Wand-Zwilling vorhanden", fehler)
|
|
if not twin_wand.is_empty():
|
|
var rot: float = float(twin_wand.get("rot", 0.0))
|
|
_check(SymmetryCore.sym_of(wand) == SymmetryCore.sym_of(twin_wand), "Wand-Paar via sym gekoppelt", fehler)
|
|
print("WAND-ZWILLING: pos=%.1f/%.1f rot=%.0f (Original 90° → gespiegelt %.0f)" % [
|
|
(float(twin_wand["pos"][0])), float(twin_wand["pos"][2]), rot, rot])
|
|
_check(bool(spawn_res["ok"]), "Spawn gespiegelt: %s" % str(spawn_res["status"]), fehler)
|
|
_check(SpawnOps.count_points(doc, 1) == 5, "Team Rot: 4 Default + 1 Zwilling", fehler)
|
|
print("BAU-TEILE: %d | SPAWN-STATUS: %s" % [BuildOps.piece_count(doc), str(spawn_res["status"])])
|
|
|
|
# --- Render ---------------------------------------------------------------
|
|
var bauer: Node3D = load("res://core/viewport/map_view_builder.gd").new()
|
|
root.add_child(bauer)
|
|
await process_frame
|
|
bauer.rebuild(doc, manifest)
|
|
await process_frame
|
|
|
|
# Symmetrie-Achse sichtbar machen (dünne halbtransparente Linie bei x = 0).
|
|
var achse := MeshInstance3D.new()
|
|
var achse_mesh := BoxMesh.new()
|
|
achse_mesh.size = Vector3(0.3, 3.0, 90.0)
|
|
achse.mesh = achse_mesh
|
|
var achse_mat := StandardMaterial3D.new()
|
|
achse_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
|
achse_mat.albedo_color = Color(1.0, 0.95, 0.2, 0.55)
|
|
achse_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
|
achse.material_override = achse_mat
|
|
achse.position = Vector3(0.0, 1.5, 0.0)
|
|
root.add_child(achse)
|
|
|
|
var cam := Camera3D.new()
|
|
cam.fov = 55.0
|
|
root.add_child(cam)
|
|
cam.current = true
|
|
cam.make_current()
|
|
|
|
# Bild 1: TOTAL — gespiegelte Spawn-Zonen (blau links, rot rechts).
|
|
cam.position = Vector3(0.0, 120.0, 130.0)
|
|
await process_frame
|
|
cam.look_at(Vector3(0.0, 0.0, -10.0), Vector3(0.0, 0.0, -1.0))
|
|
await process_frame
|
|
await process_frame
|
|
await RenderingServer.frame_post_draw
|
|
root.get_texture().get_image().save_png("/tmp/m4_beweis_spawns.png")
|
|
|
|
# Bild 2: NAH — Bauteil-Paar links/rechts der Achse (beide voll im Rahmen).
|
|
cam.position = Vector3(0.0, 14.0, 36.0)
|
|
await process_frame
|
|
cam.look_at(Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, -1.0))
|
|
await process_frame
|
|
await process_frame
|
|
await RenderingServer.frame_post_draw
|
|
root.get_texture().get_image().save_png("/tmp/m4_beweis_bauteile.png")
|
|
for f in fehler:
|
|
print(" FEHLER: %s" % f)
|
|
print("PROBE_M4_MIRROR_%s" % ("FAIL" if not fehler.is_empty() else "OK"))
|
|
quit(1 if not fehler.is_empty() else 0)
|
|
|
|
|
|
func _check(cond: bool, label: String, fehler: Array) -> void:
|
|
print(" %s: %s" % ["ok" if cond else "FEHLER", label])
|
|
if not cond:
|
|
fehler.append(label)
|
|
|
|
|
|
func _piece_at_pos(doc: Dictionary, x: float) -> Dictionary:
|
|
for t in BuildOps.pieces(doc):
|
|
if not (t is Dictionary):
|
|
continue
|
|
var pos: Array = (t as Dictionary).get("pos", [0.0, 0.0, 0.0])
|
|
if absf(float(pos[0]) - x) < 0.01 and str((t as Dictionary).get("id", "")) == "fundament":
|
|
return t as Dictionary
|
|
return {}
|
|
|
|
|
|
func _wand_twin(doc: Dictionary) -> Dictionary:
|
|
for t in BuildOps.pieces(doc):
|
|
if not (t is Dictionary):
|
|
continue
|
|
var pos: Array = (t as Dictionary).get("pos", [0.0, 0.0, 0.0])
|
|
if str((t as Dictionary).get("id", "")) == "wand" and float(pos[0]) > 0.0:
|
|
return t as Dictionary
|
|
return {}
|