extends SceneTree ## D1-Render-Probe im MAP BUILDER (t_78746c97): 4 Wand-Objekte werden als ## Map-Dokument platziert und der Editor-Viewport gerendert — Sichtprüfung ## „stehen die Wände AUF dem Boden (Gitterebene y=0)?“. ## ## xvfb-run -a /opt/data/home/bin/godot4 --path . --rendering-driver opengl3 \ ## -s res://tests/probe_d1_walls_render.gd ## ## Ausgabe: PROBE_D1_EDITOR_OK / _FAIL + PNG im Scratch-Ordner. const OUT_PNG := "/opt/data/profiles/scopedvr-dev/cache/scratch/d1_editor_waende.png" const PLATZ := [ {"id": "wall_001", "pos": [-8.0, 0.0, 0.0], "rot_y_deg": 0.0}, {"id": "wall_010", "pos": [-3.0, 0.0, 0.0], "rot_y_deg": 25.0}, {"id": "wall_074", "pos": [3.0, 0.0, 0.0], "rot_y_deg": -25.0}, {"id": "wall_100", "pos": [8.0, 0.0, 0.0], "rot_y_deg": 90.0}, ] var fehler: Array = [] func _initialize() -> void: _run() func _run() -> void: await process_frame await process_frame var manifest: Dictionary = JSON.parse_string( FileAccess.get_file_as_string(SvmapIO.MANIFEST_PATH)) var lib: Dictionary = manifest.get("objects", {}) var walls := 0 for oid in lib.keys(): if str((lib[oid] as Dictionary).get("kategorie", "")) == "walls": walls += 1 print("Editor-Registry: %d Objekte, davon 'walls': %d" % [lib.size(), walls]) if walls != 50: fehler.append("Editor-Bibliothek hat %d Wände statt 50" % walls) var builder := Node3D.new() builder.set_script(load("res://src/viewport/map_view_builder.gd")) root.add_child(builder) var doc: Dictionary = SvmapDocument.create_new("D1 Waende", 64.0, "mittag") doc["objects"] = PLATZ builder.call("rebuild", doc, manifest) builder.call("set_grid_visible", true) await process_frame var fehlend: Array = builder.get("fehlende_glbs") print("fehlende_glbs (OIDs ohne echtes GLB): %s" % str(fehlend)) for oid in ["wall_001", "wall_010", "wall_074", "wall_100"]: if fehlend.has(oid): fehler.append("%s landet im Editor auf dem Platzhalter" % oid) var markers: Array = builder.get("object_markers") print("platzierte Objekt-Marker: %d" % markers.size()) if markers.size() != 4: fehler.append("erwartet 4 Marker, sind %d" % markers.size()) for i in markers.size(): var m: Node3D = markers[i] if m == null: fehler.append("Marker %d ist null" % i) continue var mi := m.get_child(0) as MeshInstance3D var aabb := mi.mesh.get_aabb() var unten := mi.global_position.y + aabb.position.y * mi.scale.y print(" %-10s meta_glb=%s unterkante=%.3f hoehe=%.2f dreiecke=%d" % [ str(m.get_meta("oid", "?")), str(bool(m.get_meta("glb", false))), unten, aabb.size.y * mi.scale.y, mi.mesh.get_faces().size() / 3]) if not bool(m.get_meta("glb", false)): fehler.append("Marker %d: meta glb = false (Platzhalter)" % i) if absf(unten) > 0.05: fehler.append("Marker %d: Unterkante %.3f m statt 0 (schwebt/versunken)" % [i, unten]) # --- Render --- var cam := Camera3D.new() builder.add_child(cam) cam.position = Vector3(0.0, 7.0, 17.0) cam.look_at(Vector3(0.0, 2.5, 0.0)) cam.current = true await process_frame await process_frame await RenderingServer.frame_post_draw var img := root.get_texture().get_image() img.save_png(OUT_PNG) print("PROBE_SAVED %s (%dx%d)" % [OUT_PNG, img.get_width(), img.get_height()]) for f in fehler: print(" FEHLER: %s" % f) print("PROBE_D1_EDITOR_%s" % ("FAIL" if not fehler.is_empty() else "OK")) quit(0 if fehler.is_empty() else 1)