using System; using System.Collections; using Data.CardSystem; using Pixelplacement; using UnityEngine; using UnityEngine.UI; 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. /// public class MinigameBoosterGiver : MonoBehaviour { public static MinigameBoosterGiver Instance { get; private set; } [Header("Visual References")] [SerializeField] private GameObject visualContainer; [SerializeField] private RectTransform boosterImage; [SerializeField] private RectTransform glowImage; [SerializeField] private Button continueButton; [Header("Animation Settings")] [SerializeField] private float hoverAmount = 20f; [SerializeField] private float hoverDuration = 1.5f; [SerializeField] private float glowPulseMin = 0.9f; [SerializeField] private float glowPulseMax = 1.1f; [SerializeField] private float glowPulseDuration = 1.2f; [Header("Disappear Animation")] [SerializeField] private Vector2 targetBottomLeftOffset = new Vector2(100f, 100f); [SerializeField] private float disappearDuration = 0.8f; [SerializeField] private float disappearScale = 0.2f; private Vector3 _boosterInitialPosition; private Vector3 _boosterInitialScale; private Vector3 _glowInitialScale; private Coroutine _currentSequence; private Action _onCompleteCallback; private void Awake() { // Singleton pattern if (Instance != null && Instance != this) { Debug.LogWarning("[MinigameBoosterGiver] Duplicate instance found. Destroying."); Destroy(gameObject); return; } Instance = this; // Cache initial values if (boosterImage != null) { _boosterInitialPosition = boosterImage.localPosition; _boosterInitialScale = boosterImage.localScale; } if (glowImage != null) { _glowInitialScale = glowImage.localScale; } // Setup button listener if (continueButton != null) { continueButton.onClick.AddListener(OnContinueClicked); } // Start hidden if (visualContainer != null) { visualContainer.SetActive(false); } } private void OnDestroy() { if (Instance == this) { Instance = null; } if (continueButton != null) { continueButton.onClick.RemoveListener(OnContinueClicked); } } /// /// Public API to give a booster pack. Displays UI, starts animations, and waits for user interaction. /// /// Optional callback when the sequence completes and pack is granted public void GiveBooster(Action onComplete = null) { if (_currentSequence != null) { Debug.LogWarning("[MinigameBoosterGiver] Already running a sequence. Ignoring new request."); return; } _onCompleteCallback = onComplete; _currentSequence = StartCoroutine(GiveBoosterSequence()); } private IEnumerator GiveBoosterSequence() { // Show the visual if (visualContainer != null) { visualContainer.SetActive(true); } // Reset positions and scales if (boosterImage != null) { boosterImage.localPosition = _boosterInitialPosition; boosterImage.localScale = _boosterInitialScale; } if (glowImage != null) { glowImage.localScale = _glowInitialScale; } // Enable the continue button if (continueButton != null) { continueButton.interactable = true; } // Start idle hovering animation on booster (ping-pong) if (boosterImage != null) { Vector3 hoverTarget = _boosterInitialPosition + Vector3.up * hoverAmount; Tween.LocalPosition(boosterImage, hoverTarget, hoverDuration, 0f, Tween.EaseLinear, Tween.LoopType.PingPong); } // Start pulsing animation on glow (ping-pong scale) if (glowImage != null) { Vector3 glowPulseScale = _glowInitialScale * glowPulseMax; Tween.LocalScale(glowImage, glowPulseScale, glowPulseDuration, 0f, Tween.EaseOut, Tween.LoopType.PingPong); } // Wait for button click (handled by OnContinueClicked) yield return null; } private void OnContinueClicked() { if (_currentSequence == null) { return; // Not in a sequence } // Disable button to prevent double-clicks if (continueButton != null) { continueButton.interactable = false; } // Stop the ongoing animations by stopping all tweens on these objects if (boosterImage != null) { Tween.Stop(boosterImage.GetInstanceID()); } if (glowImage != null) { Tween.Stop(glowImage.GetInstanceID()); // Fade out the glow Tween.LocalScale(glowImage, Vector3.zero, disappearDuration * 0.5f, 0f, Tween.EaseInBack); } // Start disappear animation StartCoroutine(DisappearSequence()); } private IEnumerator DisappearSequence() { if (boosterImage == null) { yield break; } // Calculate bottom-left corner position in local space RectTransform canvasRect = GetComponentInParent()?.GetComponent(); Vector3 targetPosition; if (canvasRect != 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; } else { // Fallback if no canvas found targetPosition = _boosterInitialPosition + new Vector3(-500f, -500f, 0f); } // Tween to bottom-left corner Tween.LocalPosition(boosterImage, targetPosition, disappearDuration, 0f, Tween.EaseInBack); // Scale down Vector3 targetScale = _boosterInitialScale * disappearScale; Tween.LocalScale(boosterImage, targetScale, disappearDuration, 0f, Tween.EaseInBack); // Wait for animation to complete yield return new WaitForSeconds(disappearDuration); // Grant the booster pack if (CardSystemManager.Instance != null) { CardSystemManager.Instance.AddBoosterPack(1); Debug.Log("[MinigameBoosterGiver] Booster pack granted!"); } else { Debug.LogWarning("[MinigameBoosterGiver] CardSystemManager not found, cannot grant booster pack."); } // Hide the visual if (visualContainer != null) { visualContainer.SetActive(false); } // Invoke completion callback _onCompleteCallback?.Invoke(); _onCompleteCallback = null; // Clear sequence reference _currentSequence = null; } } }