extends Control const SHIP_SELECTION_SCENE := preload("res://scenes/ui/ship_selection.tscn") const GAME_SCENE := "res://scenes/game/game.tscn" @onready var start_button: Button = %StartButton @onready var exit_button: Button = %ExitButton var _ship_panel: Control var _panel_open := false var _launching := false var _drawer_tween: Tween var _guide: Control var _instruction_button: Button var _continue_button: Button var _message: CanvasLayer var _modal: CanvasLayer func _style_menu() -> void: $Background.mouse_filter = Control.MOUSE_FILTER_IGNORE $Shade.mouse_filter = Control.MOUSE_FILTER_IGNORE var atmosphere := Control.new() atmosphere.name = "MenuAtmosphere" atmosphere.set_script(preload("res://scripts/ui/menu_atmosphere.gd")) add_child(atmosphere) move_child(atmosphere, $MenuLayout.get_index()) var layout := $MenuLayout as VBoxContainer layout.add_theme_constant_override("separation", 10) $MenuLayout/Spacer.hide() var eyebrow := Label.new() eyebrow.text = "DZIENNIK POKŁADOWY / NOWA WYPRAWA" eyebrow.add_theme_font_override("font", ThemeDB.fallback_font) eyebrow.add_theme_font_size_override("font_size", 11) eyebrow.add_theme_color_override("font_color", Color("91dbea")) layout.add_child(eyebrow) layout.move_child(eyebrow, 0) var title := $MenuLayout/Title as Label title.add_theme_font_size_override("font_size", 46) title.add_theme_color_override("font_color", Color("f4ead9")) var subtitle := Label.new() subtitle.text = "Nieznany kosmos. Niepowtarzalny łup." subtitle.add_theme_font_override("font", ThemeDB.fallback_font) subtitle.add_theme_font_size_override("font_size", 15) subtitle.add_theme_color_override("font_color", Color("a9bcc8")) layout.add_child(subtitle) layout.move_child(subtitle, title.get_index() + 1) var space := Control.new() space.custom_minimum_size.y = 10 layout.add_child(space) layout.move_child(space, subtitle.get_index() + 1) _instruction_button = Button.new() _instruction_button.name = "InstructionsButton" layout.add_child(_instruction_button) layout.move_child(_instruction_button, start_button.get_index() + 1) _continue_button = Button.new() _continue_button.name = "ContinueButton" layout.add_child(_continue_button) layout.move_child(_continue_button, start_button.get_index()) var entries := [ [start_button, "NOWA WYPRAWA", "Wybierz statek i ruszaj w nieznane", "01", true], [_instruction_button, "INSTRUKCJA", "Pierwszy lot? Zacznij tutaj", "02", false], [_continue_button, "KONTYNUUJ", "Wczytaj ostatnią wyprawę", "00", false], [$MenuLayout/SaveButton, "WCZYTAJ GRĘ", "Wybierz wyprawę z archiwum zapisów", "03", false], [$MenuLayout/OptionsButton, "OPCJE", "Dźwięk, obraz i język", "04", false], [exit_button, "WYJŚCIE", "Zakończ grę", "05", false], ] for entry in entries: var button: Button = entry[0] button.set_script(preload("res://scripts/ui/main_menu_button.gd")) button.call("configure", entry[1], entry[2], entry[3], entry[4]) _continue_button.disabled = not GameState.has_save() _continue_button.pressed.connect(_continue_game) $MenuLayout/SaveButton.pressed.connect(_show_save) $MenuLayout/OptionsButton.pressed.connect(_open_options) GameSettings.settings_changed.connect(_refresh_language) _guide = Control.new() _guide.set_script(preload("res://scripts/ui/player_guide.gd")) add_child(_guide) _instruction_button.pressed.connect(func() -> void: _guide.call("open")) _guide.connect("closed", _instruction_button.grab_focus) resized.connect(_layout_menu) _layout_menu.call_deferred() func _layout_menu() -> void: var layout := $MenuLayout as VBoxContainer layout.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT) var factor := minf(1.0, minf((size.y - 100.0) / maxf(580.0, layout.get_combined_minimum_size().y), (size.x - 64.0) / 420.0)) layout.scale = Vector2.ONE * factor layout.size = Vector2(420, layout.get_combined_minimum_size().y) layout.position = Vector2(maxf(32.0, size.x * 0.065), maxf(68.0, (size.y - layout.size.y * factor) * 0.5)) func _ready() -> void: start_button.pressed.connect(_start_game) exit_button.pressed.connect(_exit_game) _ship_panel = SHIP_SELECTION_SCENE.instantiate() as Control _ship_panel.name = "ShipSelectionPanel" _ship_panel.hide() add_child(_ship_panel) _ship_panel.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT) _ship_panel.connect("ship_selected", _launch_game) _ship_panel.connect("close_requested", _close_ship_panel) resized.connect(_layout_ship_panel) _layout_ship_panel() _style_menu() func _start_game() -> void: if _panel_open or _launching: return if _drawer_tween != null and _drawer_tween.is_running(): _drawer_tween.kill() _panel_open = true start_button.disabled = true _ship_panel.position.x = size.x _ship_panel.show() _drawer_tween = create_tween() _drawer_tween.tween_property(_ship_panel, "position:x", size.x - _ship_panel.size.x, 0.3).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) func _layout_ship_panel() -> void: if _ship_panel == null: return if _drawer_tween != null and _drawer_tween.is_running(): _drawer_tween.kill() _ship_panel.size = Vector2(minf(820.0, size.x), size.y) _ship_panel.position = Vector2(size.x - _ship_panel.size.x if _panel_open else size.x, 0) func _close_ship_panel() -> void: if not _panel_open or _launching: return _panel_open = false start_button.disabled = false if _drawer_tween != null and _drawer_tween.is_running(): _drawer_tween.kill() _drawer_tween = create_tween() _drawer_tween.tween_property(_ship_panel, "position:x", size.x, 0.2).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN) _drawer_tween.tween_callback(_ship_panel.hide) func _launch_game() -> void: if _launching: return _launching = true GameState.start_new_run() get_tree().change_scene_to_file(GAME_SCENE) func _exit_game() -> void: get_tree().quit() func _continue_game() -> void: if _launching: return if not GameState.continue_game(): _show_message(tr("Brak poprawnego zapisu gry.")) return _launching = true get_tree().paused = false var error := get_tree().change_scene_to_file(GAME_SCENE) if error != OK: _launching = false _show_message(error_string(error)) func _open_options() -> void: if is_instance_valid(_modal): return _modal = CanvasLayer.new() _modal.set_script(preload("res://scripts/ui/options_dialog.gd")) add_child(_modal) func _show_save() -> void: if is_instance_valid(_modal): return _modal = CanvasLayer.new() _modal.set_script(preload("res://scripts/ui/save_browser.gd")) _modal.connect("load_requested",_load_selected) add_child(_modal) func _load_selected(id: String) -> void: if _launching: return if not GameState.load_game(id): _modal._status.text = tr("Brak poprawnego zapisu gry.") _modal._status.show() return _launching = true get_tree().paused = false var error := get_tree().change_scene_to_file(GAME_SCENE) if error != OK: _launching = false _show_message(error_string(error)) func _show_message(message: String) -> void: if is_instance_valid(_message): _message.queue_free() _message = CanvasLayer.new() _message.set_script(preload("res://scripts/ui/menu_modal.gd")) _message.heading = "ZAPIS ROZGRYWKI" _message.subtitle = message _message.preferred_size = Vector2(600,320) add_child(_message) preload("res://scripts/ui/menu_modal.gd").button(_message.footer,tr("Zamknij"),_message._close,true) func _refresh_language() -> void: for button in $MenuLayout.get_children(): if button is Button: button.queue_redraw()