diff --git a/Assets/Prefabs/Managers/PlayerHUD.prefab b/Assets/Prefabs/Managers/PlayerHUD.prefab index b6661425..d10dc50c 100644 --- a/Assets/Prefabs/Managers/PlayerHUD.prefab +++ b/Assets/Prefabs/Managers/PlayerHUD.prefab @@ -1185,6 +1185,7 @@ MonoBehaviour: CinematicBackground: {fileID: 1256355336041814197} eagleEye: {fileID: 8093509920149135307} ramaSjangButton: {fileID: 4599222264323240281} + scrabBookButton: {fileID: 2880351836456325619} cinematicSprites: {fileID: 0} cinematicBackgroundSprites: {fileID: 0} currentCinematicPlayer: {fileID: 0} diff --git a/Assets/Scripts/UI/CardSystem/MinigameBoosterGiver.cs b/Assets/Scripts/UI/CardSystem/MinigameBoosterGiver.cs index c395d718..1ba5e86a 100644 --- a/Assets/Scripts/UI/CardSystem/MinigameBoosterGiver.cs +++ b/Assets/Scripts/UI/CardSystem/MinigameBoosterGiver.cs @@ -10,7 +10,8 @@ namespace UI.CardSystem /// /// Singleton UI component for granting booster packs from minigames. /// Displays a booster pack with glow effect, waits for user to click continue, - /// then animates the pack flying to bottom-left corner before granting the reward. + /// then shows the scrapbook button and animates the pack flying to it before granting the reward. + /// The scrapbook button is automatically hidden after the animation completes. /// public class MinigameBoosterGiver : MonoBehaviour { @@ -187,23 +188,61 @@ namespace UI.CardSystem yield break; } - // Calculate bottom-left corner position in local space - RectTransform canvasRect = GetComponentInParent()?.GetComponent(); - Vector3 targetPosition; - - if (canvasRect != null) + // Show scrapbook button temporarily using HUD visibility context + PlayerHudManager.HudVisibilityContext hudContext = null; + GameObject scrapbookButton = null; + + scrapbookButton = PlayerHudManager.Instance.GetScrabookButton(); + if (scrapbookButton != null) { - // Convert bottom-left corner with offset to local position - Vector2 bottomLeft = new Vector2(-canvasRect.rect.width / 2f, -canvasRect.rect.height / 2f); - targetPosition = bottomLeft + targetBottomLeftOffset; + hudContext = PlayerHudManager.Instance.ShowElementTemporarily(scrapbookButton); } else { - // Fallback if no canvas found - targetPosition = _boosterInitialPosition + new Vector3(-500f, -500f, 0f); + Debug.LogWarning("[MinigameBoosterGiver] Scrapbook button not found in PlayerHudManager."); } - // Tween to bottom-left corner + // Calculate target position - use scrapbook button position if available + Vector3 targetPosition; + + if (scrapbookButton != null) + { + // Get the scrapbook button's position in the same coordinate space as boosterImage + RectTransform scrapbookRect = scrapbookButton.GetComponent(); + if (scrapbookRect != null) + { + // Convert scrapbook button's world position to local position relative to boosterImage's parent + Canvas canvas = GetComponentInParent(); + if (canvas != null && canvas.renderMode == RenderMode.ScreenSpaceOverlay) + { + // For overlay canvas, convert screen position to local position + Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(null, scrapbookRect.position); + RectTransformUtility.ScreenPointToLocalPointInRectangle( + boosterImage.parent as RectTransform, + screenPos, + null, + out Vector2 localPoint); + targetPosition = localPoint; + } + else + { + // For world space or camera canvas + targetPosition = boosterImage.parent.InverseTransformPoint(scrapbookRect.position); + } + } + else + { + Debug.LogWarning("[MinigameBoosterGiver] Scrapbook button has no RectTransform, using fallback position."); + targetPosition = GetFallbackPosition(); + } + } + else + { + // Fallback to bottom-left corner + targetPosition = GetFallbackPosition(); + } + + // Tween to scrapbook button position Tween.LocalPosition(boosterImage, targetPosition, disappearDuration, 0f, Tween.EaseInBack); // Scale down @@ -224,6 +263,9 @@ namespace UI.CardSystem Debug.LogWarning("[MinigameBoosterGiver] CardSystemManager not found, cannot grant booster pack."); } + // Hide scrapbook button by disposing the context + hudContext?.Dispose(); + // Hide the visual if (visualContainer != null) { @@ -237,6 +279,22 @@ namespace UI.CardSystem // Clear sequence reference _currentSequence = null; } + + private Vector3 GetFallbackPosition() + { + RectTransform canvasRect = GetComponentInParent()?.GetComponent(); + if (canvasRect != null) + { + // Convert bottom-left corner with offset to local position + Vector2 bottomLeft = new Vector2(-canvasRect.rect.width / 2f, -canvasRect.rect.height / 2f); + return bottomLeft + targetBottomLeftOffset; + } + else + { + // Ultimate fallback if no canvas found + return _boosterInitialPosition + new Vector3(-500f, -500f, 0f); + } + } } } diff --git a/Assets/Scripts/UI/PlayerHudManager.cs b/Assets/Scripts/UI/PlayerHudManager.cs index 770584ec..6b00c084 100644 --- a/Assets/Scripts/UI/PlayerHudManager.cs +++ b/Assets/Scripts/UI/PlayerHudManager.cs @@ -7,6 +7,7 @@ using UnityEngine.Playables; using UnityEngine.UI; using System.Linq; using System.Collections.Generic; +using System; namespace UI { @@ -19,6 +20,73 @@ namespace UI { public enum UIMode { Overworld, Puzzle, Minigame, HideAll }; + /// + /// Context object for managing temporary HUD element visibility. + /// Automatically restores previous visibility state when disposed. + /// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementTemporarily(myButton)) { ... } + /// + public class HudVisibilityContext : IDisposable + { + private readonly GameObject _element; + private readonly bool _previousState; + private bool _disposed; + + internal HudVisibilityContext(GameObject element, bool show) + { + _element = element; + _previousState = element.activeSelf; + _element.SetActive(show); + } + + public void Dispose() + { + if (_disposed) return; + _disposed = true; + + if (_element != null) + { + _element.SetActive(_previousState); + } + } + } + + /// + /// Multi-element visibility context for managing multiple HUD elements at once. + /// Automatically restores previous visibility states when disposed. + /// + public class MultiHudVisibilityContext : IDisposable + { + private readonly List<(GameObject element, bool previousState)> _elements; + private bool _disposed; + + internal MultiHudVisibilityContext(IEnumerable elements, bool show) + { + _elements = new List<(GameObject, bool)>(); + foreach (var element in elements) + { + if (element != null) + { + _elements.Add((element, element.activeSelf)); + element.SetActive(show); + } + } + } + + public void Dispose() + { + if (_disposed) return; + _disposed = true; + + foreach (var (element, previousState) in _elements) + { + if (element != null) + { + element.SetActive(previousState); + } + } + } + } + public UIMode currentUIMode; [Header("HUD Management")] @@ -33,6 +101,7 @@ namespace UI [Header("HUD Elements")] public GameObject eagleEye; public GameObject ramaSjangButton; + public GameObject scrabBookButton; [HideInInspector] public Image cinematicSprites; [HideInInspector] public Image cinematicBackgroundSprites; @@ -254,6 +323,9 @@ namespace UI if (visible) { eagleEye.SetActive(false); + ramaSjangButton.SetActive(false); + scrabBookButton.SetActive(false); + } break; case UIMode.HideAll: @@ -318,6 +390,64 @@ namespace UI UnityEngine.Debug.LogError("[PlayerHudManager] Cannot push page - UIPageController not found!"); } } + + #region HUD Element Getters + + public GameObject GetEagleEye() => eagleEye; + public GameObject GetRamaSjangButton() => ramaSjangButton; + public GameObject GetScrabookButton() => scrabBookButton; + + #endregion + + #region Context-Based Visibility Management + + /// + /// Temporarily shows a HUD element. Returns a context object that restores the previous state when disposed. + /// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementTemporarily(myButton)) { /* element is visible */ } + /// + public HudVisibilityContext ShowElementTemporarily(GameObject element) + { + if (element == null) + { + Logging.Warning("[PlayerHudManager] Attempted to show null element"); + return null; + } + return new HudVisibilityContext(element, true); + } + + /// + /// Temporarily hides a HUD element. Returns a context object that restores the previous state when disposed. + /// Usage: using (var ctx = PlayerHudManager.Instance.HideElementTemporarily(myButton)) { /* element is hidden */ } + /// + public HudVisibilityContext HideElementTemporarily(GameObject element) + { + if (element == null) + { + Logging.Warning("[PlayerHudManager] Attempted to hide null element"); + return null; + } + return new HudVisibilityContext(element, false); + } + + /// + /// Temporarily shows multiple HUD elements. Returns a context object that restores all previous states when disposed. + /// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementsTemporarily(button1, button2, button3)) { /* elements are visible */ } + /// + public MultiHudVisibilityContext ShowElementsTemporarily(params GameObject[] elements) + { + return new MultiHudVisibilityContext(elements, true); + } + + /// + /// Temporarily hides multiple HUD elements. Returns a context object that restores all previous states when disposed. + /// Usage: using (var ctx = PlayerHudManager.Instance.HideElementsTemporarily(button1, button2, button3)) { /* elements are hidden */ } + /// + public MultiHudVisibilityContext HideElementsTemporarily(params GameObject[] elements) + { + return new MultiHudVisibilityContext(elements, false); + } + + #endregion } }