Working pause menu re-worked with exlusive views

This commit is contained in:
Michal Pikulski
2025-10-24 10:41:27 +02:00
parent 7bb905eb6b
commit 1003c3f6ac
14 changed files with 878 additions and 116 deletions

View File

@@ -299,7 +299,7 @@ GameObject:
m_Component: m_Component:
- component: {fileID: 8855931927481658112} - component: {fileID: 8855931927481658112}
- component: {fileID: 5244731468946939147} - component: {fileID: 5244731468946939147}
- component: {fileID: 2860077094930428643} - component: {fileID: 7848685733999064403}
m_Layer: 5 m_Layer: 5
m_Name: Backback m_Name: Backback
m_TagString: Untagged m_TagString: Untagged
@@ -372,7 +372,7 @@ MonoBehaviour:
m_OnClick: m_OnClick:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
--- !u!114 &2860077094930428643 --- !u!114 &7848685733999064403
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
@@ -381,9 +381,9 @@ MonoBehaviour:
m_GameObject: {fileID: 7564017895147059150} m_GameObject: {fileID: 7564017895147059150}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e7ea50a695c58944799b4f27a9014301, type: 3} m_Script: {fileID: 11500000, guid: 494d0aedce9744308499355006071138, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: '::' m_EditorClassIdentifier: AppleHillsScripts::UI.DummyInput
--- !u!1 &8561999612656273135 --- !u!1 &8561999612656273135
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using AppleHills.Core.Interfaces; using AppleHills.Core.Interfaces;
using AppleHills.Core.Settings; using AppleHills.Core.Settings;
using Bootstrap; using Bootstrap;
using Input;
using UnityEngine; using UnityEngine;
namespace Core namespace Core
@@ -122,9 +123,9 @@ namespace Core
/// <param name="shouldPause">True to pause; false to resume</param> /// <param name="shouldPause">True to pause; false to resume</param>
private void ApplyPause(bool shouldPause) private void ApplyPause(bool shouldPause)
{ {
// Example: stop time // TODO: Do we want to stop time?
Time.timeScale = shouldPause ? 0f : 1f; // Time.timeScale = shouldPause ? 0f : 1f;
// Notify registered components // Notify registered components
foreach (var component in _pausableComponents) foreach (var component in _pausableComponents)
{ {
@@ -136,10 +137,18 @@ namespace Core
// Fire events // Fire events
if (shouldPause) if (shouldPause)
{
// TODO: Stop input here?
InputManager.Instance.SetInputMode(InputMode.UI);
OnGamePaused?.Invoke(); OnGamePaused?.Invoke();
}
else else
{
// TODO: Release input here?
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
OnGameResumed?.Invoke(); OnGameResumed?.Invoke();
}
Logging.Debug($"[GameManager] Game {(shouldPause ? "paused" : "resumed")}. Paused {_pausableComponents.Count} components."); Logging.Debug($"[GameManager] Game {(shouldPause ? "paused" : "resumed")}. Paused {_pausableComponents.Count} components.");
} }

View File

@@ -61,8 +61,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (GameManager.Instance.IsPaused) return; // Already paused
StopBubbleBehavior(); StopBubbleBehavior();
// Debug log for troubleshooting // Debug log for troubleshooting
@@ -74,8 +72,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!GameManager.Instance.IsPaused) return; // Already running
StartBubbleBehavior(); StartBubbleBehavior();
// Debug log for troubleshooting // Debug log for troubleshooting

View File

@@ -81,8 +81,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (GameManager.Instance.IsPaused) return; // Already paused
// Stop spawning coroutine // Stop spawning coroutine
if (_spawnCoroutine != null) if (_spawnCoroutine != null)
{ {
@@ -108,8 +106,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!GameManager.Instance.IsPaused) return; // Already running
// Restart spawning coroutine // Restart spawning coroutine
StartSpawningCoroutine(); StartSpawningCoroutine();

View File

@@ -804,8 +804,6 @@ namespace Minigames.DivingForPictures
public void DoPause(bool turnOffGameInput = true) public void DoPause(bool turnOffGameInput = true)
{ {
if (GameManager.Instance.IsPaused) return; // Already paused
// Pause all registered components // Pause all registered components
foreach (var component in _pausableComponents) foreach (var component in _pausableComponents)
{ {
@@ -824,8 +822,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!GameManager.Instance.IsPaused) return; // Already running
// Resume all registered components // Resume all registered components
foreach (var component in _pausableComponents) foreach (var component in _pausableComponents)
{ {

View File

@@ -137,8 +137,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (GameManager.Instance.IsPaused) return; // Already paused
StopObstacleCoroutines(); StopObstacleCoroutines();
Logging.Debug($"[FloatingObstacle] Paused obstacle: {name}"); Logging.Debug($"[FloatingObstacle] Paused obstacle: {name}");
@@ -149,8 +147,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!GameManager.Instance.IsPaused) return; // Already running
StartObstacleCoroutines(); StartObstacleCoroutines();
Logging.Debug($"[FloatingObstacle] Resumed obstacle: {name}"); Logging.Debug($"[FloatingObstacle] Resumed obstacle: {name}");

View File

@@ -121,8 +121,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (GameManager.Instance.IsPaused) return; // Already paused
// Stop spawning coroutine // Stop spawning coroutine
if (_spawnCoroutine != null) if (_spawnCoroutine != null)
{ {
@@ -151,9 +149,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!GameManager.Instance.IsPaused) return; // Already running
// Restart spawning coroutine if not in surfacing mode // Restart spawning coroutine if not in surfacing mode
if (!_isSurfacing) if (!_isSurfacing)
{ {

View File

@@ -286,8 +286,6 @@ namespace Minigames.DivingForPictures.Player
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (GameManager.Instance.IsPaused) return;
// If we're being paused, stop any active touch and tap impulse // If we're being paused, stop any active touch and tap impulse
_isTouchActive = false; _isTouchActive = false;
_tapImpulseStrength = 0f; _tapImpulseStrength = 0f;
@@ -300,7 +298,6 @@ namespace Minigames.DivingForPictures.Player
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!GameManager.Instance.IsPaused) return;
Logging.Debug("[PlayerController] Resumed"); Logging.Debug("[PlayerController] Resumed");
} }
#endregion #endregion

View File

@@ -185,8 +185,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
if (GameManager.Instance.IsPaused) return; // Already paused
// Stop all active coroutines but save their references // Stop all active coroutines but save their references
if (_movementCoroutine != null) if (_movementCoroutine != null)
{ {
@@ -220,8 +218,6 @@ namespace Minigames.DivingForPictures
/// </summary> /// </summary>
public void DoResume() public void DoResume()
{ {
if (!GameManager.Instance.IsPaused) return; // Already running
// Restart all necessary coroutines // Restart all necessary coroutines
StartMovementCoroutine(); StartMovementCoroutine();
StartTileDestructionCoroutine(); StartTileDestructionCoroutine();

View File

@@ -1,39 +0,0 @@
using UnityEngine;
namespace UI.CardSystem
{
public class BackpackInput : MonoBehaviour, ITouchInputConsumer
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void OnTap(Vector2 position)
{
return;
}
public void OnHoldStart(Vector2 position)
{
return;
}
public void OnHoldMove(Vector2 position)
{
return;
}
public void OnHoldEnd(Vector2 position)
{
return;
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: e7ea50a695c58944799b4f27a9014301

View File

@@ -44,9 +44,6 @@ namespace UI.CardSystem
backpackButton.onClick.AddListener(OnBackpackButtonClicked); backpackButton.onClick.AddListener(OnBackpackButtonClicked);
} }
// Initially show only the backpack icon
ShowOnlyBackpackIcon();
// Hide notification dot initially // Hide notification dot initially
if (boosterNotificationDot != null) if (boosterNotificationDot != null)
boosterNotificationDot.gameObject.SetActive(false); boosterNotificationDot.gameObject.SetActive(false);
@@ -57,6 +54,9 @@ namespace UI.CardSystem
private void InitializePostBoot() private void InitializePostBoot()
{ {
// Initially show only the backpack icon
ShowOnlyBackpackIcon();
// Initialize pages and hide them // Initialize pages and hide them
InitializePages(); InitializePages();
} }
@@ -142,10 +142,6 @@ namespace UI.CardSystem
if (notificationSound != null) if (notificationSound != null)
notificationSound.Play(); notificationSound.Play();
// Eat input so the characters don't walk around
var backpackInput = backpackIcon.gameObject.GetComponentInParent<BackpackInput>();
InputManager.Instance.RegisterOverrideConsumer(backpackInput);
PageController.PushPage(mainMenuPage); PageController.PushPage(mainMenuPage);
// Clear notification for unseen cards when opening menu // Clear notification for unseen cards when opening menu
@@ -159,6 +155,8 @@ namespace UI.CardSystem
{ {
backpackButton.gameObject.SetActive(false); backpackButton.gameObject.SetActive(false);
} }
GameManager.Instance.RequestPause(this);
} }
/// <summary> /// <summary>
@@ -170,8 +168,6 @@ namespace UI.CardSystem
if (newPage == null) if (newPage == null)
{ {
ShowOnlyBackpackIcon(); ShowOnlyBackpackIcon();
var backpackInput = backpackIcon.gameObject.GetComponentInParent<BackpackInput>();
InputManager.Instance.UnregisterOverrideConsumer(backpackInput);
} }
else else
{ {
@@ -225,6 +221,8 @@ namespace UI.CardSystem
boosterNotificationDot.gameObject.SetActive(hasBooters || _hasUnseenCards); boosterNotificationDot.gameObject.SetActive(hasBooters || _hasUnseenCards);
} }
} }
GameManager.Instance.ReleasePause(this);
} }
/// <summary> /// <summary>

View File

@@ -12,7 +12,6 @@ namespace UI
public class PauseMenu : UIPage public class PauseMenu : UIPage
{ {
private static PauseMenu _instance; private static PauseMenu _instance;
private static bool _isQuitting;
/// <summary> /// <summary>
/// Singleton instance of the PauseMenu. No longer creates an instance if one doesn't exist. /// Singleton instance of the PauseMenu. No longer creates an instance if one doesn't exist.
@@ -64,11 +63,6 @@ namespace UI
SceneManagerService.Instance.SceneLoadCompleted -= SetPauseMenuByLevel; SceneManagerService.Instance.SceneLoadCompleted -= SetPauseMenuByLevel;
} }
} }
void OnApplicationQuit()
{
_isQuitting = true;
}
/// <summary> /// <summary>
/// Sets the pause menu game object active or inactive based on the current level /// Sets the pause menu game object active or inactive based on the current level
@@ -76,7 +70,7 @@ namespace UI
/// <param name="levelName">The name of the level/scene</param> /// <param name="levelName">The name of the level/scene</param>
public void SetPauseMenuByLevel(string levelName) public void SetPauseMenuByLevel(string levelName)
{ {
HidePauseMenu(false); HidePauseMenu();
// TODO: Implement level-based pause menu visibility logic if needed // TODO: Implement level-based pause menu visibility logic if needed
/*if (string.IsNullOrEmpty(levelName)) /*if (string.IsNullOrEmpty(levelName))
return; return;
@@ -94,7 +88,6 @@ namespace UI
/// </summary> /// </summary>
public void ShowPauseMenu() public void ShowPauseMenu()
{ {
if (GameManager.Instance.IsPaused) return;
if (UIPageController.Instance != null) if (UIPageController.Instance != null)
{ {
UIPageController.Instance.PushPage(this); UIPageController.Instance.PushPage(this);
@@ -119,7 +112,7 @@ namespace UI
/// <summary> /// <summary>
/// Hides the pause menu and shows the pause button. Sets input mode to Game. /// Hides the pause menu and shows the pause button. Sets input mode to Game.
/// </summary> /// </summary>
public void HidePauseMenu(bool resetInput = true) public void HidePauseMenu()
{ {
if (!GameManager.Instance.IsPaused) if (!GameManager.Instance.IsPaused)
{ {
@@ -139,7 +132,7 @@ namespace UI
pauseMenuPanel.SetActive(false); pauseMenuPanel.SetActive(false);
if (pauseButton != null) if (pauseButton != null)
pauseButton.SetActive(true); pauseButton.SetActive(true);
EndPauseSideEffects(resetInput); EndPauseSideEffects();
if (canvasGroup != null) if (canvasGroup != null)
{ {
canvasGroup.alpha = 0f; canvasGroup.alpha = 0f;
@@ -161,15 +154,13 @@ namespace UI
private void BeginPauseSideEffects() private void BeginPauseSideEffects()
{ {
if (pauseButton != null) pauseButton.SetActive(false); if (pauseButton != null) pauseButton.SetActive(false);
InputManager.Instance.SetInputMode(InputMode.UI); GameManager.Instance.RequestPause(this);
GameManager.Instance.RequestPause(this);;
Logging.Debug("[PauseMenu] Game Paused"); Logging.Debug("[PauseMenu] Game Paused");
} }
private void EndPauseSideEffects(bool invokeEvent) private void EndPauseSideEffects()
{ {
if (pauseButton != null) pauseButton.SetActive(true); if (pauseButton != null) pauseButton.SetActive(true);
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
GameManager.Instance.ReleasePause(this); GameManager.Instance.ReleasePause(this);
Logging.Debug("[PauseMenu] Game Resumed"); Logging.Debug("[PauseMenu] Game Resumed");
} }
@@ -178,6 +169,8 @@ namespace UI
{ {
// Ensure the panel root is active // Ensure the panel root is active
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(true); if (pauseMenuPanel != null) pauseMenuPanel.SetActive(true);
// Pause side effects should run immediately (hide button, set input mode, etc.).
// The tween itself must run in unscaled time so it still animates while the game is paused.
BeginPauseSideEffects(); BeginPauseSideEffects();
if (canvasGroup != null) if (canvasGroup != null)
@@ -185,7 +178,16 @@ namespace UI
canvasGroup.interactable = true; canvasGroup.interactable = true;
canvasGroup.blocksRaycasts = true; canvasGroup.blocksRaycasts = true;
canvasGroup.alpha = 0f; canvasGroup.alpha = 0f;
Tween.Value(0f, 1f, v => canvasGroup.alpha = v, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete); // pass obeyTimescale = false so this tween runs even when Time.timeScale == 0
Tween.Value(0f, 1f, (v) =>
{
Logging.Debug($"[PauseMenu] Tweening pause menu alpha: {v}");
canvasGroup.alpha = v;
}, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, () =>
{
Logging.Debug("[PauseMenu] Finished tweening pause menu in.");
onComplete?.Invoke();
}, false);
} }
else else
{ {
@@ -199,16 +201,17 @@ namespace UI
{ {
canvasGroup.interactable = false; canvasGroup.interactable = false;
canvasGroup.blocksRaycasts = false; canvasGroup.blocksRaycasts = false;
// Run out-tween in unscaled time as well so the fade completes while paused.
Tween.Value(canvasGroup.alpha, 0f, v => canvasGroup.alpha = v, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, () => Tween.Value(canvasGroup.alpha, 0f, v => canvasGroup.alpha = v, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, () =>
{ {
EndPauseSideEffects(true); EndPauseSideEffects();
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false); if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
onComplete?.Invoke(); onComplete?.Invoke();
}); }, false);
} }
else else
{ {
EndPauseSideEffects(true); EndPauseSideEffects();
if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false); if (pauseMenuPanel != null) pauseMenuPanel.SetActive(false);
onComplete?.Invoke(); onComplete?.Invoke();
} }