using UnityEngine; using UnityEngine.UI; using UnityEngine.InputSystem; using RR.Game2D.Core.Managers; namespace RR.Common.UI { /// /// Меню паузы. Наследуется от Modal для автоматического управления фокусом. /// Открывается/закрывается через GameManager.PauseStateChanged. /// public class PauseMenu : Modal { [Header("Управление паузой")] [SerializeField] private InputActionReference pauseToggle; [Header("Кнопки меню")] [SerializeField] private Button resumeButton; [SerializeField] private Button quitButton; [Header("Связь с другими элементами")] [SerializeField] private GameEndUIController bannerController; /// /// Флаг активности меню. Деактивируется когда показан баннер проигрыша/победы. /// public bool IsActive { get; private set; } = true; protected override void Awake() { // Настраиваем обработчики кнопок if (resumeButton) resumeButton.onClick.AddListener(OnResumeClicked); if (quitButton) quitButton.onClick.AddListener(OnQuitClicked); if (pauseToggle) pauseToggle.action.performed += OnPauseToggle; // Устанавливаем первый выбранный элемент SetFirstSelected(resumeButton); if (GameManager.Instance != null) GameManager.Instance.PauseStateChanged += HandlePauseChanged; if (bannerController) { bannerController.WinBannerShown += _ => { IsActive = false; }; bannerController.LoseBannerShown += _ => { IsActive = false; }; bannerController.BannerDismissed += () => { IsActive = true; }; } // Изначально скрыто - не вызываем base.Awake(), делаем это вручную gameObject.SetActive(false); } private void OnPauseToggle(InputAction.CallbackContext ctx) { // Блокируем паузу если меню неактивно (например, показан баннер проигрыша/победы) if (!IsActive) return; // Блокируем паузу если открыто любое другое модальное окно if (!_isOpen && IsAnyOtherModalOpen()) return; GameManager.Instance.TogglePause(); } private void OnDestroy() { if (pauseToggle) pauseToggle.action.performed -= OnPauseToggle; if (GameManager.Instance != null) GameManager.Instance.PauseStateChanged -= HandlePauseChanged; } /// /// Обработка события паузы от GameManager. /// private void HandlePauseChanged(bool paused) { if (!IsActive) return; // Не показываем меню паузы, если открыто другое модальное окно if (paused && IsAnyOtherModalOpen()) return; if (paused) Open(); else Close(); } /// /// Проверяет, открыто ли какое-либо модальное окно, кроме самого PauseMenu. /// private bool IsAnyOtherModalOpen() { var mm = ModalManager.Instance; if (mm == null) return false; // Если открытых окон нет — точно нет других if (!mm.HasOpenModals) return false; // Если текущее окно — мы сами, значит других нет if (mm.CurrentModal == this) return false; return true; } /// /// Переопределяем Close, чтобы при закрытии также снимать паузу. /// public override void Close() { // Блокируем закрытие если меню неактивно (показан баннер) if (!IsActive) return; base.Close(); // Если игра ещё на паузе, снимаем её if (GameManager.Instance != null && GameManager.Instance.IsPaused) { GameManager.Instance.SetPause(false); } } /// /// Метод для возобновления игры. /// public static void OnResumeClicked() { // Блокируем если меню неактивно (показан баннер) var pauseMenu = FindFirstObjectByType(); if (pauseMenu != null && !pauseMenu.IsActive) return; GameManager.Instance.TogglePause(); } /// /// Метод для выхода в главное меню. /// public void OnQuitClicked() { GameManager.Instance.SetPause(false); GameManager.Instance.LoadScene("MainMenu", false); } } }