extends SceneTree ## WEGWERF-Renderprobe (Karte t_eca890c5, K1b Startansicht = Karten-INHALT) — 3 Bilder 1600×900: ## (a) Map geladen → fit_to_document: INHALT (Kisten+Spawns) im Bild, Kisten gut sichtbar ## (b) MMT auf Objekt + 60 px ziehen → Objekt bleibt unterm Cursor, kein Sprung ## (c) Pos1 → GANZE Karte wieder im Bild (Statuszeile „Pos1: ganze Karte ins Bild.“) ## Ausführen: ## xvfb-run -a godot4 --path . --rendering-driver opengl3 -s res://tests/probe_k1b_render.gd ## Wegwerf-Probe (nicht im Repo-Commit — Datei-Grenzen der Karte), Beweise nach ## /opt/data/scopedvr/work/k1b_beweise/. var main: Control var camera: Camera3D var subvp: SubViewport var step := 0 func _initialize() -> void: _run.call_deferred() func _png(name: String) -> String: return "/opt/data/scopedvr/work/k1b_beweise/" + name func _shot(name: String) -> void: await process_frame await process_frame var img := subvp.get_texture().get_image() img.save_png(_png(name)) print("PROBE_PNG=%s (%dx%d)" % [_png(name), img.get_width(), img.get_height()]) func _find_subvp(node: Node) -> SubViewport: if node is SubViewport: return node as SubViewport for c in node.get_children(): var f := _find_subvp(c) if f != null: return f return null func _mouse(btn: int, pressed: bool, pos: Vector2) -> void: var ev := InputEventMouseButton.new() ev.button_index = btn as MouseButton ev.pressed = pressed ev.position = pos ev.global_position = pos subvp.push_input(ev) func _motion(pos: Vector2) -> void: var ev := InputEventMouseMotion.new() ev.position = pos ev.global_position = pos subvp.push_input(ev) func _key(code: Key) -> void: var key := InputEventKey.new() key.keycode = code key.physical_keycode = code key.pressed = true subvp.push_input(key) func _in_frustum(p: Vector3) -> bool: return camera.is_position_in_frustum(p) func _run() -> void: var scene: PackedScene = load("res://scenes/main.tscn") main = scene.instantiate() root.add_child(main) await process_frame await process_frame camera = main.get("camera") subvp = _find_subvp(main) var container: SubViewportContainer = subvp.get_parent() container.stretch = false subvp.size = Vector2i(1600, 900) await process_frame # Gleiche Test-Szene wie die Suite: 2 Kisten + Default-Spawns (1024er Map). var doc: Dictionary = SvmapDocument.create_new("K1b-Probe", 1024.0, "mittag") doc["objects"] = [ {"id": "box_001", "pos": [0.0, 0.0, 0.0], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "box_001", "pos": [450.0, 0.0, 450.0], "scale": 1.0, "rot_y_deg": 0.0}, ] main.set("doc", doc) main.call("_refresh_all") await process_frame await process_frame var builder = main.get("view_builder") var marker: Node3D = (builder.get("object_markers") as Array)[0] var center: Vector3 = marker.global_position + Vector3.UP * float(marker.get_meta("half_height", 0.0)) print("ZAHLEN (a) target=", camera.get("target"), " distance=", camera.get("distance")) print("ZAHLEN (a) Objekt ", center, " → px ", camera.unproject_position(center)) var ecken_sichtbar := 0 var fehlende := 0 for c in [Vector3(-512, -10, -512), Vector3(512, 80, -512), Vector3(-512, -10, 512), Vector3(512, 80, 512)]: if _in_frustum(c): ecken_sichtbar += 1 else: fehlende += 1 print("ZAHLEN (a) Map-Ecken im Frustum: %d/4 (fehlend=%d — STARTANSICHT ist INHALT, nicht ganze Map)" % [ecken_sichtbar, fehlende]) print("ZAHLEN (a) Kisten im Frustum: (0,0,0)=", _in_frustum(Vector3(0, 0.6, 0)), " (450,0.6,450)=", _in_frustum(Vector3(450, 0.6, 450))) print("ZAHLEN (a) Status: ", main.status_label.text) await _shot("k1b_a_startansicht_inhalt.png") # --- (b) MMT auf Objekt + 60 px ziehen (K1-Prüfung bleibt intakt) -------- var press: Vector2 = camera.unproject_position(center) print("ZAHLEN (b) Objekt bei ", center, " → px ", press) _motion(press) _mouse(MOUSE_BUTTON_MIDDLE, true, press) await process_frame var dist_vor: float = float(camera.get("distance")) _motion(press + Vector2(60, 0)) await process_frame _motion(press + Vector2(60, 0)) _mouse(MOUSE_BUTTON_MIDDLE, false, press + Vector2(60, 0)) await process_frame var dist_nach: float = float(camera.get("distance")) print("ZAHLEN (b) Abstand Kamera↔Objekt vor/nach 60px-Drehen: ", camera.position.distance_to(center), " / ", camera.position.distance_to(center), " (Δ=", absf(dist_nach - dist_vor), ") Objekt im Bild=", _in_frustum(center)) await _shot("k1b_b_drehen_objekt.png") # --- (c) Pos1: GANZE Karte wieder ---------------------------------------- _key(KEY_HOME) await process_frame await process_frame var alle := true for c in [Vector3(-512, -10, -512), Vector3(512, 80, -512), Vector3(-512, -10, 512), Vector3(512, 80, 512)]: if not _in_frustum(c): alle = false print("ZAHLEN (c) nach Pos1: Map-Ecken im Frustum %s (8-Extrem-Punkte geprüft über 4 obere+4 … simpel: 4)", ["ALLE" if alle else "FEHLEND"]) print("ZAHLEN (c) target=", camera.get("target"), " distance=", camera.get("distance")) print("ZAHLEN (c) Status: ", main.status_label.text) await _shot("k1b_c_pos1_ganze_karte.png") print("PROBE_FERTIG") quit(0)