90 lines
2.9 KiB
GDScript
90 lines
2.9 KiB
GDScript
extends SceneTree
|
|
|
|
## Dev tool: launch with rendering, screenshot the main menu and a level,
|
|
## then quit. Run:
|
|
## godot --path . -s res://debug/visual_capture.gd -- <output_dir> [scene_path]
|
|
## Screenshots land in <output_dir>/shot_menu.png, shot_level.png, shot_tp_run.png
|
|
## and shot_aerial.png. scene_path defaults to the test level.
|
|
|
|
var _frames := 0
|
|
var _out_dir := "."
|
|
var _scene := "res://scenes/maps/test_level/test_level.tscn"
|
|
|
|
|
|
func _initialize() -> void:
|
|
var args := OS.get_cmdline_user_args()
|
|
if args.size() > 0:
|
|
_out_dir = args[0]
|
|
if args.size() > 1:
|
|
_scene = args[1]
|
|
if not _out_dir.is_absolute_path():
|
|
_out_dir = ProjectSettings.globalize_path(_out_dir)
|
|
var mkdir_error := DirAccess.make_dir_recursive_absolute(_out_dir)
|
|
if mkdir_error != OK:
|
|
printerr("visual_capture: could not create '%s' (error %d)" % [
|
|
_out_dir, mkdir_error])
|
|
quit(mkdir_error)
|
|
return
|
|
change_scene_to_file("res://ui/main_menu/main_menu.tscn")
|
|
|
|
|
|
func _process(_delta: float) -> bool:
|
|
_frames += 1
|
|
if _frames == 60:
|
|
_shot("menu")
|
|
var nm = root.get_node_or_null("NetworkManager")
|
|
if nm and nm.has_method("start_singleplayer_match"):
|
|
nm.start_singleplayer_match(GameMode.DEATHMATCH)
|
|
change_scene_to_file(_scene)
|
|
elif _frames == 240:
|
|
_shot("level")
|
|
# Third person + run forward, to eyeball model grounding and animation
|
|
for p in root.find_children("*", "CharacterBody3D", true, false):
|
|
if p.has_method("set_third_person") and p.is_multiplayer_authority():
|
|
p.set_third_person(true)
|
|
Input.action_press("move_forward")
|
|
elif _frames == 300:
|
|
_shot("tp_run")
|
|
Input.action_release("move_forward")
|
|
elif _frames == 338:
|
|
_shot("tp_idle")
|
|
# Aerial overview of the whole map
|
|
var cam := root.get_camera_3d()
|
|
if cam:
|
|
var aerial := Camera3D.new()
|
|
current_scene.add_child(aerial)
|
|
if _scene.contains("neon_alley"):
|
|
aerial.far = 2000.0
|
|
aerial.global_position = Vector3(0, 400, 300)
|
|
else:
|
|
aerial.global_position = Vector3(0, 55, 42)
|
|
aerial.look_at(Vector3(0, 0, -5), Vector3.UP)
|
|
aerial.current = true
|
|
elif _frames == 340:
|
|
_shot("aerial")
|
|
# Fixed street-level view for deterministic style comparisons
|
|
var cam := root.get_camera_3d()
|
|
if cam:
|
|
cam.global_position = Vector3(3, 2.2, 20)
|
|
cam.look_at(Vector3(-8, 4, -18), Vector3.UP)
|
|
elif _frames == 360:
|
|
_shot("street")
|
|
# Let the loaded scene and RenderingServer resources drain before the
|
|
# process exits. Large CSG maps can still have deferred frees queued on
|
|
# the exact frame of the last screenshot.
|
|
unload_current_scene()
|
|
elif _frames == 480:
|
|
return true
|
|
return false
|
|
|
|
|
|
func _shot(tag: String) -> void:
|
|
var img := root.get_viewport().get_texture().get_image()
|
|
var path := _out_dir + "/shot_" + tag + ".png"
|
|
var save_error := img.save_png(path)
|
|
if save_error == OK:
|
|
print("visual_capture: saved ", path)
|
|
else:
|
|
printerr("visual_capture: could not save '%s' (error %d)" % [
|
|
path, save_error])
|