Add a repeatable screenshot capture and compare smoke

Both capture helpers now accept --out=res://docs/screenshots, and
tools/check_screenshots.sh renders the staged set (using xvfb-run when headless)
before running screen_designs.py compare. Record the judge result: 7 match,
4 review, 0 diff. Headless 226/226 and the smoke both pass in a clean worktree.
This commit is contained in:
zwitschi committed 2026-11-01 16:43:10 +01:00
1 parent b39fee6176
commit d96f53c285
6 files changed
+159 -171

No files matched your search

+7 -3
View File
@@ -1,11 +1,12 @@
extends SceneTree
## Dev helper: render every generated prop side by side on a plain backdrop and
## save user://screenshots/10-prop-gallery.png. The image feeds
## save user://screenshots/10-prop-gallery.png by default. The image feeds
## `tools/screen_designs.py compare` so a prop regression is visible.
##
## Usage: godot --path . --script res://src/test/capture_prop_gallery.gd
## godot --path . --script res://src/test/capture_prop_gallery.gd -- --out=res://docs/screenshots
const OUT_DIR := "user://screenshots"
var out_dir := "user://screenshots"
const MODEL_DIR := "res://assets/models/generated/"
const LIBRARY_DIR := "res://assets/models/blender/props/"
const PROPS := ["bollard", "bench", "trash_bin", "planter_box",
@@ -15,6 +16,9 @@ const SPACING := 1.9
var frames := 0
func _initialize() -> void:
for arg in OS.get_cmdline_user_args():
if arg.begins_with("--out="):
out_dir = arg.trim_prefix("--out=")
root.size = Vector2i(1280, 720)
_build_stage()
@@ -102,7 +106,7 @@ func _process(_delta: float) -> bool:
if dir == null or not dir.dir_exists("screenshots"):
dir.make_dir_recursive("screenshots")
var image := root.get_texture().get_image()
var err := image.save_png(OUT_DIR.path_join("10-prop-gallery.png"))
var err := image.save_png(out_dir.path_join("10-prop-gallery.png"))
print("10-prop-gallery.png -> err=%d (%dx%d)" % [err, image.get_width(), image.get_height()])
quit(0)
return true
+10 -6
View File
@@ -1,10 +1,11 @@
extends SceneTree
## Dev helper: run the game windowed and capture staged screenshots for the
## README (day set + LATE-night set with street lamps and flashlight).
## Saves 1280x720 PNGs to user://screenshots/.
## Saves 1280x720 PNGs to user://screenshots/ by default.
## Usage: godot --path . --script res://src/test/capture_screenshots.gd
## godot --path . --script res://src/test/capture_screenshots.gd -- --out=res://docs/screenshots
const OUT_DIR := "user://screenshots"
var out_dir := "user://screenshots"
const MAX_FRAMES := 3600 # hard cap (~60s)
var frames := 0
@@ -16,6 +17,9 @@ var camera_staged := false
var wand_attempts := 0
func _initialize() -> void:
for arg in OS.get_cmdline_user_args():
if arg.begins_with("--out="):
out_dir = arg.trim_prefix("--out=")
root.size = Vector2i(1280, 720)
var packed: PackedScene = load("res://scenes/main.tscn")
var inst: Node = packed.instantiate()
@@ -231,9 +235,9 @@ func _face_target() -> void:
gm.guard.head.rotation.x = deg_to_rad(-4.0)
func _shoot(file_name: String) -> void:
var dir := DirAccess.open("user://")
if dir == null or not dir.dir_exists("screenshots"):
dir.make_dir_recursive("screenshots")
var dir := DirAccess.open(out_dir)
if dir == null:
DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path(out_dir))
var img: Image = root.get_texture().get_image()
var err := img.save_png(OUT_DIR.path_join(file_name))
var err := img.save_png(out_dir.path_join(file_name))
print("%s -> err=%d (%dx%d)" % [file_name, err, img.get_width(), img.get_height()])