first commit
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
extends CanvasLayer
|
||||
## Меню паузы. Кладётся внутрь игровой сцены и работает само по себе:
|
||||
## ловит действие «pause», останавливает дерево и переиспользует те же
|
||||
## экраны настроек и сохранений, что и главное меню.
|
||||
##
|
||||
## Слой обрабатывается всегда (process_mode = ALWAYS), поэтому анимации и
|
||||
## ввод продолжают работать, пока остальная игра стоит на паузе.
|
||||
|
||||
## Куда уходим по «В главное меню».
|
||||
@export_file("*.tscn") var main_menu_scene: String = "res://scenes/ui/main_menu.tscn"
|
||||
|
||||
signal opened
|
||||
signal closed
|
||||
|
||||
@onready var _saves: SaveManagerService = get_node("/root/SaveManager")
|
||||
@onready var _root: Control = $Root
|
||||
@onready var _card: Control = $Root/Center/Card
|
||||
@onready var _menu: VBoxContainer = $Root/Center/Card/Body/Menu
|
||||
@onready var _settings_screen: Control = $Root/SettingsScreen
|
||||
@onready var _save_screen: SaveMenuScreen = $Root/SaveScreen
|
||||
|
||||
## Режим курсора до паузы — игра могла держать его захваченным.
|
||||
var _previous_mouse_mode := Input.MOUSE_MODE_VISIBLE
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_root.visible = false
|
||||
for button: Button in _menu.get_children():
|
||||
# Мышь и клавиатура делят одну подсветку: наведение = фокус.
|
||||
button.mouse_entered.connect(button.grab_focus)
|
||||
button.pressed.connect(_on_menu_pressed.bind(button.name))
|
||||
_settings_screen.closed.connect(_focus_first_button)
|
||||
_save_screen.closed.connect(_focus_first_button)
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
# Вложенные экраны сами обрабатывают Esc и гасят событие — сюда оно не
|
||||
# дойдёт, но проверка оставлена на случай другой раскладки для «pause».
|
||||
if _settings_screen.visible or _save_screen.visible:
|
||||
return
|
||||
if not event.is_action_pressed("pause"):
|
||||
return
|
||||
toggle()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func toggle() -> void:
|
||||
if _root.visible:
|
||||
close()
|
||||
else:
|
||||
open()
|
||||
|
||||
|
||||
func open() -> void:
|
||||
# Миниатюру снимаем до показа меню, иначе в слот попадёт само меню.
|
||||
_saves.capture_thumbnail()
|
||||
|
||||
get_tree().paused = true
|
||||
_previous_mouse_mode = Input.mouse_mode
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
|
||||
_root.modulate.a = 0.0
|
||||
_root.visible = true
|
||||
# Контейнеры раскладываются только после того, как узел стал видимым.
|
||||
await get_tree().process_frame
|
||||
|
||||
_card.pivot_offset = _card.size * 0.5
|
||||
_card.scale = Vector2(0.96, 0.96)
|
||||
|
||||
var tween := create_tween().set_parallel(true).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC)
|
||||
tween.tween_property(_root, "modulate:a", 1.0, 0.15)
|
||||
tween.tween_property(_card, "scale", Vector2.ONE, 0.2)
|
||||
|
||||
_focus_first_button()
|
||||
opened.emit()
|
||||
|
||||
|
||||
func close() -> void:
|
||||
var tween := create_tween().set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_CUBIC)
|
||||
tween.tween_property(_root, "modulate:a", 0.0, 0.12)
|
||||
await tween.finished
|
||||
|
||||
_root.visible = false
|
||||
get_tree().paused = false
|
||||
Input.mouse_mode = _previous_mouse_mode
|
||||
closed.emit()
|
||||
|
||||
|
||||
func _on_menu_pressed(button_name: StringName) -> void:
|
||||
match String(button_name):
|
||||
"ResumeButton":
|
||||
close()
|
||||
"SaveButton":
|
||||
_save_screen.open(SaveMenuScreen.Mode.SAVE)
|
||||
"LoadButton":
|
||||
_save_screen.open(SaveMenuScreen.Mode.LOAD)
|
||||
"SettingsButton":
|
||||
_settings_screen.open()
|
||||
"MainMenuButton":
|
||||
_return_to_main_menu()
|
||||
"QuitButton":
|
||||
_quit()
|
||||
|
||||
|
||||
func _focus_first_button() -> void:
|
||||
for button: Button in _menu.get_children():
|
||||
if button.visible:
|
||||
button.grab_focus()
|
||||
return
|
||||
|
||||
|
||||
func _return_to_main_menu() -> void:
|
||||
get_tree().paused = false
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
_saves.end_session()
|
||||
get_tree().change_scene_to_file(main_menu_scene)
|
||||
|
||||
|
||||
func _quit() -> void:
|
||||
var tween := create_tween()
|
||||
tween.tween_property(_root, "modulate:a", 0.0, 0.2)
|
||||
await tween.finished
|
||||
get_tree().paused = false
|
||||
get_tree().quit()
|
||||
Reference in New Issue
Block a user