147 lines
5.2 KiB
GDScript
147 lines
5.2 KiB
GDScript
extends SceneTree
|
||
## Beweis-Probe (Karte t_639135dd, WEGWERF — nicht Teil der Suite):
|
||
## U6 dezente Auswahl — dasselbe Objekt (barrel_001, echtes GLB mit Textur) auf
|
||
## Sand und auf Fels, Auswahl-Markierung im Bild. Zwei Modi über Env:
|
||
## U6_MODUS=vorher → alter Baumzustand (Vollorange) — Beweis „vorher“
|
||
## U6_MODUS=nachher → neuer Baumzustand (Kontur, Textur sichtbar)
|
||
## Das Terrain ist eine echte Material-Schicht: linke Hälfte Sand (1),
|
||
## rechte Hälfte Fels (2) — das Objekt wird je Bild auf die eine oder
|
||
## andere Hälfte gesetzt.
|
||
## Aufruf: xvfb-run -a godot4 --path . --rendering-driver opengl3 \
|
||
## -s res://tests/probe_u6_render.gd (mit ../scopedvr-client)
|
||
|
||
const SAND := 1
|
||
const FELS := 2
|
||
|
||
|
||
func _initialize() -> void:
|
||
_run.call_deferred()
|
||
|
||
|
||
func _mats_halbe(res: int) -> PackedByteArray:
|
||
# Linke Kartenhälfte (x < Mitte) Sand, rechte Fels — Zeile für Zeile.
|
||
var mats := PackedByteArray()
|
||
mats.resize(res * res)
|
||
var i := 0
|
||
for z in res:
|
||
for x in res:
|
||
mats[i] = SAND if x < res / 2 else FELS
|
||
i += 1
|
||
return mats
|
||
|
||
|
||
func _x_von_material(material: int, size: float) -> float:
|
||
# Objekt-Anker je Hälfte: Sand links (−35 % Größe), Fels rechts (+35 %).
|
||
return -0.35 * size if material == SAND else 0.35 * size
|
||
|
||
|
||
func _shot(pfad: String) -> void:
|
||
await process_frame
|
||
await RenderingServer.frame_post_draw
|
||
var img := root.get_viewport().get_texture().get_image()
|
||
img.save_png(pfad)
|
||
print("Bild: %s (%dx%d)" % [pfad, img.get_width(), img.get_height()])
|
||
|
||
|
||
## „Modelle fehlen“-AcceptDialog schließen (kommt erst nach 2 Frames von
|
||
## utils/modelle_status.gd — mehrfach probieren, mit Wartezeit dazwischen).
|
||
func _dismiss_dialogs() -> void:
|
||
for i in 6:
|
||
await process_frame
|
||
var stack: Array = [root]
|
||
while not stack.is_empty():
|
||
var n: Node = stack.pop_back()
|
||
if n is AcceptDialog:
|
||
(n as AcceptDialog).hide()
|
||
n.queue_free()
|
||
stack.append_array(n.get_children())
|
||
|
||
|
||
## UI-Panels ausblenden: die 3D-Ansicht bekommt fast das ganze Fenster —
|
||
## das Beweisbild zeigt die Kontur groß statt im schmalen Streifen. Vom
|
||
## SubViewport-Container aufwärts werden alle GESCHWISTER versteckt.
|
||
func _maximiere_3d(main: Node) -> void:
|
||
var vp_container: Node = null
|
||
var stack: Array = [main]
|
||
while not stack.is_empty():
|
||
var n: Node = stack.pop_back()
|
||
if n is SubViewportContainer:
|
||
vp_container = n
|
||
break
|
||
stack.append_array(n.get_children())
|
||
if vp_container == null:
|
||
return
|
||
var laeufer: Node = vp_container
|
||
while laeufer != null and laeufer != main:
|
||
var elter: Node = laeufer.get_parent()
|
||
if elter == null:
|
||
break
|
||
for kind in elter.get_children():
|
||
if kind != laeufer and kind is Control:
|
||
(kind as Control).visible = false
|
||
laeufer = elter
|
||
|
||
|
||
func _run() -> void:
|
||
var modus := OS.get_environment("U6_MODUS")
|
||
if modus.is_empty():
|
||
modus = "nachher"
|
||
var material := SAND if OS.get_environment("U6_BODEN") != "fels" else FELS
|
||
var scene: PackedScene = load("res://core/scenes/main.tscn")
|
||
var main = scene.instantiate()
|
||
root.add_child(main)
|
||
await process_frame
|
||
await process_frame
|
||
await _dismiss_dialogs()
|
||
_maximiere_3d(main)
|
||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
||
DisplayServer.window_set_size(Vector2i(2328, 1310))
|
||
# Echte Karte: flaches Terrain, Material-Schicht Sand/Fels.
|
||
var size := 1024.0
|
||
var res := 129
|
||
var doc: Dictionary = SvmapDocument.create_new("U6Probe", size, "mittag")
|
||
var terrain: Dictionary = doc.get("terrain", {})
|
||
terrain["materials_r8_b64"] = SvmapIO.encode_materials(_mats_halbe(res))
|
||
var x := _x_von_material(material, size)
|
||
(doc["objects"] as Array).append({
|
||
"id": "barrel_001", "pos": [x, 0.0, 0.0], "scale": 1.0, "rot_y_deg": 20.0,
|
||
})
|
||
main.doc = doc
|
||
main.call("_after_structure_change")
|
||
await process_frame
|
||
await process_frame
|
||
var cam = main.get("camera")
|
||
if cam != null:
|
||
# Nah dran: Distanz 5 m, Pivot 1,2 m westlich vom Fass — das Fass
|
||
# füllt sichtbar Fläche und sitzt nicht hinter dem Pivot-Gizmo.
|
||
cam.set("distance", 5.0)
|
||
cam.position = Vector3(x + 2.5, 1.8, 4.0)
|
||
cam.call("focus_on", Vector3(x - 1.2, 0.6, 0.0))
|
||
await process_frame
|
||
await process_frame
|
||
# Objekt über die ECHTE Auswahl anwählen (wie ein Klick ins Editor-UI).
|
||
main.interaction.call("select_object", 0)
|
||
await process_frame
|
||
await process_frame
|
||
# Zustands-Beleg in der Konsole (je Modus die passende Beobachtung).
|
||
var builder = main.get("view_builder")
|
||
var marker: Node3D = builder.object_markers[0]
|
||
var mi := marker.get_child(0) as MeshInstance3D
|
||
if cam != null:
|
||
print("PRUEF cam: pos=%s target=%s fly=%s dist=%s" % [
|
||
str(cam.position), str(cam.get("target")),
|
||
str(cam.call("fly_active")), str(cam.get("distance"))])
|
||
var hat_outline: bool = marker.has_meta("outline") \
|
||
and is_instance_valid(marker.get_meta("outline"))
|
||
print("PRUEF modus=%s boden=%s glb=%s material_override=%s outline=%s" % [
|
||
modus, "sand" if material == SAND else "fels",
|
||
str(bool(marker.get_meta("glb", false))),
|
||
str(mi.material_override != null), str(hat_outline)])
|
||
var dir := OS.get_environment("U6_DIR")
|
||
if dir.is_empty():
|
||
dir = "/tmp/u6_beweise"
|
||
DirAccess.make_dir_recursive_absolute(dir)
|
||
var name := "u6_%s_%s.png" % [modus, "sand" if material == SAND else "fels"]
|
||
await _shot(dir.path_join(name))
|
||
print("PROBE_U6_%s_%s" % [modus.to_upper(), "OK"])
|
||
quit(0)
|