extends SceneTree ## Repro harness for the "bull + matador invisible on phone" bug. Loads the shell with the ## arena level, waits for spawn, prints vis/pos for the skinned characters and dumps a real ## screenshot so the Compatibility (mobile/web) render path can be compared to Forward+. ## godot --rendering-method gl_compatibility --script tests/mobile_render_repro.gd ## godot --rendering-method forward_plus --script tests/mobile_render_repro.gd func _init() -> void: _run.call_deferred() func _report(nodes: Array, label: String) -> void: if nodes.is_empty(): print(" ", label, ": NONE") return var n := nodes[0] as Node3D print(" ", label, ": vis=", n.is_visible_in_tree(), " pos=", str(n.global_position.round())) # Walk to the skinned MeshInstance3D and report its state + AABB. _dump_meshes(n, " ") func _dump_meshes(node: Node, indent: String) -> void: if node is MeshInstance3D: var mi := node as MeshInstance3D var aabb := mi.get_aabb() var lod_count := 0 var surf := 0 if mi.mesh != null: surf = mi.mesh.get_surface_count() print(indent, "MeshInstance3D '", mi.name, "' vis=", mi.visible, " skin=", mi.skin != null, " gscale=", str(mi.global_transform.basis.get_scale()), "\n", indent, " aabb_pos=", aabb.position, " aabb_size=", aabb.size, " custom_aabb=", mi.custom_aabb.size, " surfaces=", surf) for c: Node in node.get_children(): _dump_meshes(c, indent) func _run() -> void: # Compatibility (OpenGL) has no RenderingDevice; Forward+/Mobile do. This reflects the # renderer actually chosen by --rendering-method, unlike the static project setting. var method := "gl_compatibility" if RenderingServer.get_rendering_device() == null else "forward_plus" print("=== RENDER REPRO method=", method, " gpu=", RenderingServer.get_video_adapter_name(), " ===") var run: Node = root.get_node("Run") run.ensure_run() run.debug_level_override = run.get_level(&"arena") var scene: Node = load("res://scene.tscn").instantiate() root.add_child(scene) current_scene = scene await create_timer(1.2).timeout print("bull + matador state:") _report(get_nodes_in_group(&"player"), "bull") _report(get_nodes_in_group(&"matador"), "matador") # Force a couple more draw frames, then grab the framebuffer. for i in 4: await process_frame var img := root.get_viewport().get_texture().get_image() var out := "tests/output/render_%s.png" % method DirAccess.make_dir_recursive_absolute("res://tests/output") img.save_png("res://" + out) print("screenshot -> ", out, " (", img.get_width(), "x", img.get_height(), ")") quit()