extends SceneTree ## Rendered QA for the movement-fidelity pass. ## Captures rear views of both thrust modes and side views of reverse/braking. var _frames := 0 var _out_dir := "." var _player: Node = null var _model: Node = null var _jets: PlayerJetVFX = null var _camera: Camera3D = null var _phase := 0 var _phase_frame := 0 func _initialize() -> void: var args := OS.get_cmdline_user_args() if not args.is_empty(): _out_dir = args[0] if not _out_dir.is_absolute_path(): _out_dir = ProjectSettings.globalize_path(_out_dir) var err := DirAccess.make_dir_recursive_absolute(_out_dir) if err != OK: printerr("jet_pose_capture: could not create output directory") quit(err) return change_scene_to_file("res://ui/main_menu/main_menu.tscn") func _process(_delta: float) -> bool: _frames += 1 if _frames == 35: var skins = root.get_node_or_null("SkinManager") if skins: skins.set_active_skin("miku") var network = root.get_node_or_null("NetworkManager") if network and network.has_method("start_singleplayer_match"): network.start_singleplayer_match(GameMode.DEATHMATCH) change_scene_to_file("res://scenes/maps/test_level/test_level.tscn") return false if _frames < 145: return false if _frames == 145: for candidate in root.find_children("*", "CharacterBody3D", true, false): if candidate.has_method("get_visual_model") \ and candidate.is_multiplayer_authority(): _player = candidate break if not _player: printerr("jet_pose_capture: player not found") return true _player.set_third_person(true) _model = _player.get_visual_model() _jets = _player.get_node_or_null("JetVFX") if not _model or not _jets: printerr("jet_pose_capture: model or jet rig not found") return true _player.set_physics_process(false) _player.set_process(false) _player.global_position = Vector3(0, 1.2, 14) _player.rotation = Vector3.ZERO _model.set_owner_visible(true) _jets.set_render_enabled(true) _jets.set_visual_model(_model) _camera = Camera3D.new() _camera.cull_mask &= ~(1 << 19) current_scene.add_child(_camera) _camera.current = true _side_camera() return false _phase_frame += 1 match _phase: 0: _model.update_state("ground", 8.0, false) _model.set_locomotion(0.0, -1.0, 0.0) if _phase_frame == 48: _snap("backward_lean") _next_phase() 1: _model.set_locomotion(0.0, 1.0, 0.0) _model.update_state("ground", 12.0 if _phase_frame < 12 else 5.0, false) if _phase_frame == 18: _snap("brake_pose") _next_phase() _rear_camera() 2: _model.update_state("dash", 14.0, false) _model.set_locomotion(0.0, 1.0, 0.0) _jets.set_dash(true, Vector2(0.0, 1.0)) if _phase_frame == 32: _snap("dash_jets") _next_phase() 3: _model.update_state("air", 5.0, false) _model.set_locomotion(0.0, 1.0, 0.0) _jets.set_dash(false, Vector2.ZERO) if _phase_frame == 1: _jets.burst_double_jump() if _phase_frame == 7: _snap("double_jump_jets") unload_current_scene() _next_phase() _: if _phase_frame > 60: print("JET_POSE_CAPTURE PASS") return true return false func _next_phase() -> void: _phase += 1 _phase_frame = 0 func _side_camera() -> void: _camera.global_position = _player.global_position + Vector3(2.7, 0.9, 0.0) _camera.look_at(_player.global_position + Vector3(0.0, 0.75, 0.0), Vector3.UP) func _rear_camera() -> void: _camera.global_position = _player.global_position + Vector3(2.15, 1.0, 2.8) _camera.look_at(_player.global_position + Vector3(0.0, 0.72, 0.0), Vector3.UP) func _snap(tag: String) -> void: var path := _out_dir.path_join(tag + ".png") var err := root.get_viewport().get_texture().get_image().save_png(path) if err == OK: print("jet_pose_capture: saved ", path) else: printerr("jet_pose_capture: failed to save ", path)