using Core.Lifecycle; using Data.CardSystem; using Pixelplacement; using Pixelplacement.TweenSystem; using TMPro; using UnityEngine; namespace UI.CardSystem { /// /// Manages a notification dot that displays a count (e.g., booster packs) /// Can be reused across different UI elements that need to show numeric notifications /// Automatically syncs with CardSystemManager to display booster pack count /// public class BoosterNotificationDot : ManagedBehaviour { [Header("UI References")] [SerializeField] private GameObject dotBackground; [SerializeField] private TextMeshProUGUI countText; [Header("Settings")] [SerializeField] private bool hideWhenZero = true; [SerializeField] private bool useAnimation = false; [SerializeField] private string textPrefix = ""; [SerializeField] private string textSuffix = ""; [SerializeField] private Color textColor = Color.white; [Header("Animation")] [SerializeField] private bool useTween = true; [SerializeField] private float pulseDuration = 0.3f; [SerializeField] private float pulseScale = 1.2f; // Optional animator reference [SerializeField] private Animator animator; [SerializeField] private string animationTrigger = "Update"; // Current count value private int _currentCount; private Vector3 _originalScale; private TweenBase _activeTween; internal override void OnManagedStart() { // Store original scale for pulse animation if (dotBackground != null) { _originalScale = dotBackground.transform.localScale; } // Apply text color if (countText != null) { countText.color = textColor; } // Subscribe to CardSystemManager events (managers are guaranteed to be initialized) if (CardSystemManager.Instance != null) { CardSystemManager.Instance.OnBoosterCountChanged += OnBoosterCountChanged; // Poll initial count and display it int initialCount = CardSystemManager.Instance.GetBoosterPackCount(); SetCount(initialCount); } else { // If CardSystemManager isn't available yet, set to default count SetCount(_currentCount); } } protected override void OnDestroy() { // Unsubscribe from CardSystemManager events to prevent memory leaks if (CardSystemManager.Instance != null) { CardSystemManager.Instance.OnBoosterCountChanged -= OnBoosterCountChanged; } // Call base implementation base.OnDestroy(); } /// /// Callback when booster count changes in CardSystemManager /// private void OnBoosterCountChanged(int newCount) { SetCount(newCount); } /// /// Sets the count displayed on the notification dot /// Also handles visibility based on settings /// public void SetCount(int count) { bool countChanged = count != _currentCount; _currentCount = count; // Update text if (countText != null) { countText.text = textPrefix + count.ToString() + textSuffix; } // Handle visibility if (hideWhenZero) { SetVisibility(count > 0); } // Play animation if value changed and animation is enabled if (countChanged && count > 0) { if (useAnimation) { Animate(); } } } /// /// Gets the current count value /// public int GetCount() { return _currentCount; } /// /// Set text formatting options /// public void SetFormatting(string prefix, string suffix, Color color) { textPrefix = prefix; textSuffix = suffix; textColor = color; if (countText != null) { countText.color = color; // Update text with new formatting countText.text = textPrefix + _currentCount.ToString() + textSuffix; } } /// /// Explicitly control the notification dot visibility /// public void SetVisibility(bool isVisible) { if (dotBackground != null) { dotBackground.SetActive(isVisible); } if (countText != null) { countText.gameObject.SetActive(isVisible); } } /// /// Show the notification dot /// public void Show() { SetVisibility(true); } /// /// Hide the notification dot /// public void Hide() { SetVisibility(false); } /// /// Play animation manually - either using Animator or Tween /// public void Animate() { if (useAnimation) { if (animator != null) { animator.SetTrigger(animationTrigger); } else if (useTween && dotBackground != null) { // Cancel any existing tweens on this transform if(_activeTween != null) _activeTween.Cancel(); // Reset to original scale dotBackground.transform.localScale = _originalScale; // Pulse animation using Tween _activeTween = Tween.LocalScale(dotBackground.transform, _originalScale * pulseScale, pulseDuration/2, 0, Tween.EaseOut, Tween.LoopType.None, null, () => { // Scale back to original size Tween.LocalScale(dotBackground.transform, _originalScale, pulseDuration/2, 0, Tween.EaseIn); }, obeyTimescale: false); } } } } }