farming-simulator/scripts/ui/pause_menu.gd

116 lines
3.4 KiB
GDScript3
Raw Normal View History

полная мета-структура игры: pause + settings + save/load PAUSE-МЕНЮ (autoload PauseMenu CanvasLayer): - ESC во время геймплея открывает оверлей с тёмным фоном и центральной панелью в Шиндовс-стиле. - 4 кнопки: Продолжить / Настройки / В главное меню / Сохранить и выйти. - process_mode = ALWAYS чтобы работать при tree.paused = true. - При закрытии меню в 3D-сценах автоматически возвращает Input.mouse_mode = CAPTURED. - В главном меню pause не активируется (_can_pause false). - set_input_as_handled блокирует FPV-контроллер от перехвата ESC одновременно. НАСТРОЙКИ (под-панель в Pause-меню): - Слайдер «Чувствительность мыши» 0.001-0.010 (по умолчанию 0.0025). - Слайдер «Громкость» 0-100% — связан с AudioServer Bus 0 Master через linear_to_db (audio ассетов пока нет, но шкала рабочая). - Кнопки Назад / Применить. Применить пишет в user://settings.json. - settings.json грузится автоматически при старте GameState._ready. SAVE/LOAD: - GameState.save_game(scene_path) → user://save01.json в JSON с player_name, прогрессом актов 1-2, ачивками, текущей сценой. - GameState.load_game() читает и восстанавливает state, заполняет last_scene_path для перехода. - has_save() / delete_save() помощники. - Кнопка «Продолжить» в главном меню активна только если есть save и грузит игрока в сохранённую сцену. - Кнопка «Новая игра» удаляет старый save и сбрасывает state. AUTO-SAVE: - При закрытии окна через X (NOTIFICATION_WM_CLOSE_REQUEST) — save_game перед quit. - Кнопка Q в FPV-контроллере — save+quit. - Кнопка «Сохранить и выйти» в pause-меню — save+quit. - Кнопка «В главное меню» — save перед переходом. FPV-КОНТРОЛЛЕР: - mouse_sensitivity больше не локальное @export, читается из GameState.mouse_sensitivity каждый mouse_motion event (применяется живьём после Apply). - _input → _unhandled_input чтобы PauseMenu мог перехватить ESC через set_input_as_handled. - Убран ESC-toggle захвата мыши (теперь это делает PauseMenu). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 18:28:58 +03:00
extends CanvasLayer
@onready var bg: ColorRect = $BG
@onready var main_panel: PanelContainer = $MainPanel
@onready var settings_panel: PanelContainer = $SettingsPanel
@onready var btn_resume: Button = $MainPanel/V/BtnResume
@onready var btn_settings: Button = $MainPanel/V/BtnSettings
@onready var btn_main: Button = $MainPanel/V/BtnMainMenu
@onready var btn_quit: Button = $MainPanel/V/BtnQuit
@onready var sens_slider: HSlider = $SettingsPanel/V/SensRow/Slider
@onready var sens_value: Label = $SettingsPanel/V/SensRow/Value
@onready var vol_slider: HSlider = $SettingsPanel/V/VolRow/Slider
@onready var vol_value: Label = $SettingsPanel/V/VolRow/Value
@onready var btn_apply: Button = $SettingsPanel/V/Buttons/Apply
@onready var btn_back: Button = $SettingsPanel/V/Buttons/Back
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
visible = false
main_panel.visible = true
settings_panel.visible = false
layer = 100
btn_resume.pressed.connect(_resume)
btn_settings.pressed.connect(_open_settings)
btn_main.pressed.connect(_to_main_menu)
btn_quit.pressed.connect(_quit)
btn_apply.pressed.connect(_apply_settings)
btn_back.pressed.connect(_close_settings)
sens_slider.value_changed.connect(func(_v: float) -> void: _update_value_labels())
vol_slider.value_changed.connect(func(_v: float) -> void: _update_value_labels())
func _input(event: InputEvent) -> void:
if event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE:
if visible:
if settings_panel.visible:
_close_settings()
else:
_resume()
get_viewport().set_input_as_handled()
elif _can_pause():
_open()
get_viewport().set_input_as_handled()
func _can_pause() -> bool:
var scene: Node = get_tree().current_scene
if scene == null:
return false
# Не паузим в главном меню
if scene.name == "MainMenu":
return false
return true
func _open() -> void:
visible = true
main_panel.visible = true
settings_panel.visible = false
get_tree().paused = true
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
btn_resume.grab_focus()
func _resume() -> void:
visible = false
get_tree().paused = false
# Восстановить захват мыши только для 3D-сцен (с FPV игроком)
var scene: Node = get_tree().current_scene
if scene != null and scene.has_node("PlayerFPV"):
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _open_settings() -> void:
sens_slider.value = GameState.mouse_sensitivity * 1000.0
vol_slider.value = GameState.master_volume * 100.0
_update_value_labels()
main_panel.visible = false
settings_panel.visible = true
btn_back.grab_focus()
func _close_settings() -> void:
settings_panel.visible = false
main_panel.visible = true
btn_resume.grab_focus()
func _update_value_labels() -> void:
sens_value.text = "%.4f" % (sens_slider.value / 1000.0)
vol_value.text = "%d%%" % int(vol_slider.value)
func _apply_settings() -> void:
GameState.mouse_sensitivity = sens_slider.value / 1000.0
GameState.master_volume = vol_slider.value / 100.0
GameState._apply_audio_volume()
GameState.save_settings()
_close_settings()
func _to_main_menu() -> void:
GameState.save_game(get_tree().current_scene.scene_file_path if get_tree().current_scene else "")
visible = false
get_tree().paused = false
SceneManager.go_main()
func _quit() -> void:
GameState.save_game(get_tree().current_scene.scene_file_path if get_tree().current_scene else "")
get_tree().quit()