283 lines
9.8 KiB
C#
283 lines
9.8 KiB
C#
using System;
|
|
using Core;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using Input;
|
|
using Bootstrap;
|
|
using UI.Core;
|
|
using Pixelplacement;
|
|
|
|
namespace UI
|
|
{
|
|
public class PauseMenu : UIPage
|
|
{
|
|
private static PauseMenu _instance;
|
|
private static bool _isQuitting;
|
|
|
|
/// <summary>
|
|
/// Singleton instance of the PauseMenu. No longer creates an instance if one doesn't exist.
|
|
/// </summary>
|
|
public static PauseMenu Instance => _instance;
|
|
|
|
[Header("UI References")]
|
|
[SerializeField] private GameObject pauseMenuPanel;
|
|
[SerializeField] private GameObject pauseButton;
|
|
[SerializeField] private CanvasGroup canvasGroup;
|
|
|
|
public event Action OnGamePaused;
|
|
public event Action OnGameResumed;
|
|
|
|
private bool _isPaused = false;
|
|
|
|
/// <summary>
|
|
/// Returns whether the game is currently paused
|
|
/// </summary>
|
|
public bool IsPaused => _isPaused;
|
|
|
|
private void Awake()
|
|
{
|
|
_instance = this;
|
|
|
|
// Ensure we have a CanvasGroup for transitions
|
|
if (canvasGroup == null)
|
|
canvasGroup = GetComponent<CanvasGroup>();
|
|
if (canvasGroup == null)
|
|
canvasGroup = gameObject.AddComponent<CanvasGroup>();
|
|
canvasGroup.alpha = 0f;
|
|
canvasGroup.interactable = false;
|
|
canvasGroup.blocksRaycasts = false;
|
|
gameObject.SetActive(false);
|
|
|
|
// Register for post-boot initialization
|
|
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
|
}
|
|
|
|
private void InitializePostBoot()
|
|
{
|
|
// Subscribe to scene loaded events
|
|
SceneManagerService.Instance.SceneLoadCompleted += SetPauseMenuByLevel;
|
|
|
|
// SceneManagerService subscription moved to InitializePostBoot
|
|
|
|
// Set initial state based on current scene
|
|
SetPauseMenuByLevel(SceneManager.GetActiveScene().name);
|
|
|
|
Logging.Debug("[PauseMenu] Subscribed to SceneManagerService events");
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
// Unsubscribe when destroyed
|
|
if (SceneManagerService.Instance != null)
|
|
{
|
|
SceneManagerService.Instance.SceneLoadCompleted -= SetPauseMenuByLevel;
|
|
}
|
|
}
|
|
|
|
void OnApplicationQuit()
|
|
{
|
|
_isQuitting = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the pause menu game object active or inactive based on the current level
|
|
/// </summary>
|
|
/// <param name="levelName">The name of the level/scene</param>
|
|
public void SetPauseMenuByLevel(string levelName)
|
|
{
|
|
HidePauseMenu(false);
|
|
// TODO: Implement level-based pause menu visibility logic if needed
|
|
/*if (string.IsNullOrEmpty(levelName))
|
|
return;
|
|
|
|
bool isStartingLevel = levelName.ToLower().Contains("startingscene");
|
|
|
|
if(isStartingLevel)
|
|
HidePauseMenu(false); // Ensure menu is hidden when switching to a game level
|
|
|
|
Logging.Debug($"[PauseMenu] Setting pause menu active: {!isStartingLevel} for scene: {levelName}");*/
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows the pause menu and hides the pause button. Sets input mode to UI.
|
|
/// </summary>
|
|
public void ShowPauseMenu()
|
|
{
|
|
if (_isPaused) return;
|
|
if (UIPageController.Instance != null)
|
|
{
|
|
UIPageController.Instance.PushPage(this);
|
|
}
|
|
else
|
|
{
|
|
// Fallback if no controller, just show
|
|
if (pauseMenuPanel != null)
|
|
pauseMenuPanel.SetActive(true);
|
|
gameObject.SetActive(true);
|
|
BeginPauseSideEffects();
|
|
// no animation fallback
|
|
if (canvasGroup != null)
|
|
{
|
|
canvasGroup.alpha = 1f;
|
|
canvasGroup.interactable = true;
|
|
canvasGroup.blocksRaycasts = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Hides the pause menu and shows the pause button. Sets input mode to Game.
|
|
/// </summary>
|
|
public void HidePauseMenu(bool resetInput = true)
|
|
{
|
|
if (!_isPaused)
|
|
{
|
|
// Ensure UI is hidden if somehow active without state
|
|
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
|
|
gameObject.SetActive(false);
|
|
return;
|
|
}
|
|
if (UIPageController.Instance != null && UIPageController.Instance.CurrentPage == this)
|
|
{
|
|
UIPageController.Instance.PopPage();
|
|
}
|
|
else
|
|
{
|
|
// Fallback if no controller, just hide
|
|
if (pauseMenuPanel != null)
|
|
pauseMenuPanel.SetActive(false);
|
|
if (pauseButton != null)
|
|
pauseButton.SetActive(true);
|
|
EndPauseSideEffects(resetInput);
|
|
if (canvasGroup != null)
|
|
{
|
|
canvasGroup.alpha = 0f;
|
|
canvasGroup.interactable = false;
|
|
canvasGroup.blocksRaycasts = false;
|
|
}
|
|
gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resumes the game by hiding the pause menu.
|
|
/// </summary>
|
|
public void ResumeGame()
|
|
{
|
|
HidePauseMenu();
|
|
}
|
|
|
|
private void BeginPauseSideEffects()
|
|
{
|
|
_isPaused = true;
|
|
if (pauseButton != null) pauseButton.SetActive(false);
|
|
InputManager.Instance.SetInputMode(InputMode.UI);
|
|
OnGamePaused?.Invoke();
|
|
Logging.Debug("[PauseMenu] Game Paused");
|
|
}
|
|
|
|
private void EndPauseSideEffects(bool invokeEvent)
|
|
{
|
|
_isPaused = false;
|
|
if (pauseButton != null) pauseButton.SetActive(true);
|
|
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
|
if (invokeEvent) OnGameResumed?.Invoke();
|
|
Logging.Debug("[PauseMenu] Game Resumed");
|
|
}
|
|
|
|
protected override void DoTransitionIn(Action onComplete)
|
|
{
|
|
// Ensure the panel root is active
|
|
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(true);
|
|
BeginPauseSideEffects();
|
|
|
|
if (canvasGroup != null)
|
|
{
|
|
canvasGroup.interactable = true;
|
|
canvasGroup.blocksRaycasts = true;
|
|
canvasGroup.alpha = 0f;
|
|
Tween.Value(0f, 1f, v => canvasGroup.alpha = v, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
|
|
}
|
|
else
|
|
{
|
|
onComplete?.Invoke();
|
|
}
|
|
}
|
|
|
|
protected override void DoTransitionOut(Action onComplete)
|
|
{
|
|
if (canvasGroup != null)
|
|
{
|
|
canvasGroup.interactable = false;
|
|
canvasGroup.blocksRaycasts = false;
|
|
Tween.Value(canvasGroup.alpha, 0f, v => canvasGroup.alpha = v, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, () =>
|
|
{
|
|
EndPauseSideEffects(true);
|
|
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
|
|
onComplete?.Invoke();
|
|
});
|
|
}
|
|
else
|
|
{
|
|
EndPauseSideEffects(true);
|
|
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
|
|
onComplete?.Invoke();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Exits to the main menu scene.
|
|
/// </summary>
|
|
public async void ExitToAppleHills()
|
|
{
|
|
// Replace with the actual scene name as set in Build Settings
|
|
var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%"));
|
|
await SceneManagerService.Instance.SwitchSceneAsync("AppleHillsOverworld", progress);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Exits the application.
|
|
/// </summary>
|
|
public void ExitGame()
|
|
{
|
|
#if UNITY_EDITOR
|
|
UnityEditor.EditorApplication.isPlaying = false;
|
|
#else
|
|
Application.Quit();
|
|
#endif
|
|
}
|
|
|
|
public async void ReloadLevel()
|
|
{
|
|
var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%"));
|
|
await SceneManagerService.Instance.ReloadCurrentScene(progress);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads a level based on the selection from a dropdown menu.
|
|
/// Connect this to a Dropdown's onValueChanged event and pass the selected option text.
|
|
/// </summary>
|
|
/// <param name="levelSelection">The selected level name or identifier from the dropdown</param>
|
|
public async void LoadLevel(int levelSelection)
|
|
{
|
|
// Hide the pause menu before loading a new level
|
|
HidePauseMenu();
|
|
|
|
// Replace with the actual scene name as set in Build Settings
|
|
var progress = new Progress<float>(p => Logging.Debug($"Loading progress: {p * 100:F0}%"));
|
|
switch (levelSelection)
|
|
{
|
|
case 0:
|
|
await SceneManagerService.Instance.SwitchSceneAsync("AppleHillsOverworld", progress);
|
|
break;
|
|
case 1:
|
|
await SceneManagerService.Instance.SwitchSceneAsync("Quarry", progress);
|
|
break;
|
|
case 2:
|
|
await SceneManagerService.Instance.SwitchSceneAsync("DivingForPictures", progress);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|