farming-simulator/scripts/ui/pause_menu.gd
Dmitrii Bykov f8040fb399
Some checks failed
Godot CI / Import + smoke test (push) Failing after 13s
полная мета-структура игры: 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

115 lines
3.4 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()