extends SceneTree # Reusable screenshot tool - NOT run via run_tests.sh (underscore prefix). # Loads a given scene, waits for a given number of frames to render, then # saves a PNG and quits. Must be run WITHOUT --headless (that forces # Godot's dummy/null renderer) - see tests/screenshot.sh for the full # invocation (Xvfb + Mesa softpipe; llvmpipe's JIT crashes with SIGILL in # this environment, softpipe's non-JIT rasterizer does not). # # Args (after `--`): [wait_frames] # [key=value ...] # # Any trailing key=value pairs are assigned onto the GameState autoload # BEFORE the scene is instantiated. Several scenes read GameState in # _ready() to decide what they draw - PlanetSurface.tscn picks its whole # surface profile from planet_definition_id - so without this the tool can # only ever photograph the default planet: # # ... -- res://PlanetSurface.tscn out.png 90 planet_definition_id=gas_giant var wait_frames: int = 60 var frames: int = 0 var scene_path: String var output_path: String var loaded_scene: Node func _initialize() -> void: var args: PackedStringArray = OS.get_cmdline_user_args() if args.size() < 2: printerr("usage: -- [wait_frames]") quit(1) return scene_path = args[0] output_path = args[1] if args.size() >= 3: wait_frames = int(args[2]) for i in range(3, args.size()): var pair: PackedStringArray = args[i].split("=", true, 1) if pair.size() != 2: printerr("expected key=value, got: %s" % args[i]) quit(1) return root.get_node("GameState").set(pair[0], pair[1]) var packed: PackedScene = load(scene_path) if packed == null: printerr("could not load scene: %s" % scene_path) quit(1) return loaded_scene = packed.instantiate() root.add_child(loaded_scene) func _process(_delta: float) -> bool: frames += 1 if frames < wait_frames: return false var img: Image = root.get_viewport().get_texture().get_image() var err: int = img.save_png(output_path) if err != OK: printerr("save_png failed with error %d" % err) quit(1) return true print("SCREENSHOT_SAVED: %s (%s)" % [output_path, str(img.get_size())]) quit(0) return true