class_name MainMenuController extends CanvasLayer ## Coordina navigazione e transizioni tra P1, P2a e P3a. signal mode_requested signal gym_requested signal exit_requested const HOME_SCENE := preload("res://menus/scenes/p1_home.tscn") const JUGGLE_SCENE := preload("res://menus/scenes/p2a_juggle_menu.tscn") const GYM_SCENE := preload("res://menus/scenes/p3a_gym_menu.tscn") var screen_root: Control var fade: ColorRect var menu_audio: MenuAudio var current_screen: Control var _transitioning := false var _capture_enabled := false var _capture_settled := false func _ready() -> void: process_mode = Node.PROCESS_MODE_ALWAYS layer = 20 _capture_enabled = OS.get_cmdline_user_args().has("--capture-menus") _capture_settled = OS.get_cmdline_user_args().has("--capture-settled") _build_shell() visible = false func _build_shell() -> void: var root := Control.new() root.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) root.mouse_filter = Control.MOUSE_FILTER_STOP add_child(root) screen_root = Control.new() screen_root.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) root.add_child(screen_root) fade = ColorRect.new() fade.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) fade.color = Color("#1d1720") fade.modulate.a = 0.0 # Il fade รจ trasparente a riposo: non deve intercettare click o touch dei menu. fade.mouse_filter = Control.MOUSE_FILTER_IGNORE root.add_child(fade) menu_audio = MenuAudio.new() add_child(menu_audio) func show_home() -> void: _show_direct(HOME_SCENE, "p1") func show_juggle() -> void: _show_direct(JUGGLE_SCENE, "p2a") func show_gym() -> void: _show_direct(GYM_SCENE, "p3a") func hide_menu() -> void: visible = false get_tree().paused = false func _show_direct(scene: PackedScene, capture_label: String) -> void: visible = true get_tree().paused = true _replace_screen(scene) _capture_after_frame(capture_label) func _navigate(scene: PackedScene, capture_label: String, focal: Control = null) -> void: if _transitioning: return _transitioning = true # Durante la transizione impedisce input duplicati; torna IGNORE al termine. fade.mouse_filter = Control.MOUSE_FILTER_STOP menu_audio.play_tone(660.0) var tween := create_tween() tween.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS) if focal: focal.pivot_offset = focal.size * 0.5 tween.tween_property(focal, "scale", Vector2(1.08, 1.08), 0.16).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT) tween.parallel().tween_property(fade, "modulate:a", 0.92, 0.24) tween.tween_callback(func(): _replace_screen(scene)) tween.tween_property(fade, "modulate:a", 0.0, 0.30) tween.tween_callback(func(): _transitioning = false fade.mouse_filter = Control.MOUSE_FILTER_IGNORE _capture_after_frame(capture_label) ) func _replace_screen(scene: PackedScene) -> void: if is_instance_valid(current_screen): current_screen.queue_free() current_screen = scene.instantiate() screen_root.add_child(current_screen) _bind_screen(current_screen) func _bind_screen(screen: Control) -> void: if screen is P1HomeScreen: screen.juggle_requested.connect(func(focal: Control): _navigate(JUGGLE_SCENE, "p2a", focal)) screen.gym_requested.connect(func(focal: Control): _navigate(GYM_SCENE, "p3a", focal)) screen.sign_drop_started.connect(menu_audio.play_sign_drop) screen.sign_landed.connect(menu_audio.play_sign_bounce) screen.exit_requested.connect(func(): menu_audio.play_tone(220.0) exit_requested.emit() ) elif screen is P2AJuggleMenuScreen: screen.back_requested.connect(func(): _navigate(HOME_SCENE, "p1")) screen.mode_requested.connect(func(): mode_requested.emit()) screen.feedback_requested.connect(menu_audio.play_tone) elif screen is P3AGymMenuScreen: screen.back_requested.connect(func(): _navigate(HOME_SCENE, "p1")) screen.game_requested.connect(func(): gym_requested.emit()) screen.feedback_requested.connect(menu_audio.play_tone) func _capture_after_frame(label: String) -> void: if not _capture_enabled: return await RenderingServer.frame_post_draw if _capture_settled: await get_tree().create_timer(1.5, true, false, true).timeout var image := get_viewport().get_texture().get_image() image.save_png("/tmp/autgame_menu_%s.png" % label)