Settings has a Theme row listing Settings.THEMES: Classic (main_theme.tres, still the default) and Original web (original_web_theme.tres), which looks like MusicFrontend: orange-bordered buttons, a #333 header and popups, #424242 panels, #4e4e4e alternating rows, a yellow playing song and a light grey player bar. Picking one sets the root window's theme at once and saves it as theme_id in settings.cfg, and it is applied at start. The popup backdrop and score graph follow a theme switch. The top bar has its own TopBarBackground style. test_theme.gd checks that every theme has everything main_theme.tres has. The screenshot tool takes a theme id. Closes #42 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
65 lines
2.5 KiB
GDScript
65 lines
2.5 KiB
GDScript
extends SceneTree
|
|
## Takes a screenshot of the main window in every UiTour state, against a fake server.
|
|
##
|
|
## Usage:
|
|
## MUSICPLAYER_CONFIG_DIR=$(mktemp -d) godot --path . -s tools/take_screenshots.gd -- <dir>
|
|
## [<theme id>]
|
|
##
|
|
## Setting [code]MUSICPLAYER_CONFIG_DIR[/code] keeps your saved quiz settings out of the
|
|
## pictures.
|
|
##
|
|
## Writes [code]<state>.png[/code] for each state and [code]layout.json[/code] with where
|
|
## every node is in each state. With [code]--headless[/code] only the layout is written.
|
|
## Compare two runs with [code]tools/compare_screenshots.py[/code].
|
|
##
|
|
## The pictures use the default theme, or the theme with the given id from
|
|
## [code]Settings.THEMES[/code], e.g. [code]original_web[/code].
|
|
|
|
const SIZE: Vector2i = Vector2i(1920, 1080)
|
|
|
|
|
|
func _initialize() -> void:
|
|
_take.call_deferred()
|
|
|
|
|
|
func _take() -> void:
|
|
var args: PackedStringArray = OS.get_cmdline_user_args()
|
|
var out_dir: String = args[0] if !args.is_empty() else "user://screenshots"
|
|
DirAccess.make_dir_recursive_absolute(out_dir)
|
|
var draws: bool = DisplayServer.get_name() != "headless"
|
|
|
|
# Loaded here, not named as a class: autoloads such as Playlist do not exist yet
|
|
# when this script is compiled
|
|
var ui_tour: GDScript = load("res://tests/fakes/ui_tour.gd")
|
|
ui_tour.prepare_autoloads()
|
|
var server: RefCounted = ui_tour.make_server().install()
|
|
|
|
# Drawn at the layout size, so the pictures do not depend on the screen size
|
|
var viewport: SubViewport = SubViewport.new()
|
|
viewport.size = SIZE
|
|
viewport.gui_embed_subwindows = true
|
|
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
|
root.add_child(viewport)
|
|
var main: Control = load("res://main/MainWindow.tscn").instantiate()
|
|
if args.size() > 1:
|
|
# The game sets the root window's theme, which the viewport here is not under
|
|
var settings: Node = root.get_node("Settings")
|
|
main.theme = load(settings.theme_entry(args[1]).path)
|
|
viewport.add_child(main)
|
|
|
|
var layout: Dictionary = {}
|
|
var save_state: Callable = func(state: String, popup: Node) -> void:
|
|
layout[state] = ui_tour.dump_layout(main, main if popup == null else popup)
|
|
if draws:
|
|
await RenderingServer.frame_post_draw
|
|
viewport.get_texture().get_image().save_png(out_dir.path_join(state + ".png"))
|
|
print("Saved state ", state)
|
|
await ui_tour.new(main).run(save_state)
|
|
|
|
var file: FileAccess = FileAccess.open(out_dir.path_join("layout.json"), FileAccess.WRITE)
|
|
file.store_string(JSON.stringify(layout, " ", true))
|
|
file.close()
|
|
server.uninstall()
|
|
main.queue_free()
|
|
quit()
|