using RR.Common.Managers; using RR.Common.Settings; using TMPro; using UnityEngine; namespace RR.Common.UI { /// /// UI компонент для отображения текущего баланса игрока. /// Автоматически обновляется при изменении баланса. /// public class BalanceDisplay : MonoBehaviour { [Header("Настройки отображения")] [SerializeField] private TextMeshProUGUI balanceText; [SerializeField] private TextMeshProUGUI currencyText; [SerializeField] private string textFormat = "Текущий баланс: {0}"; [SerializeField] private string currencyFormat = "{0}"; [Header("Опциональная анимация")] [SerializeField] private bool animateOnChange = true; [SerializeField] private float animationDuration = 0.3f; [SerializeField] private AnimationCurve scaleCurve = AnimationCurve.EaseInOut(0, 1, 1, 1); private BalanceManager _balanceManager; private SettingsManager _settingsManager; private Coroutine _animationCoroutine; private Vector3 _originalScale; private string _currency = ""; private void Awake() { if (balanceText != null) { _originalScale = balanceText.transform.localScale; } } private void Start() { _balanceManager = BalanceManager.Instance; _settingsManager = SettingsManager.Instance; // Загружаем валюту из настроек if (_settingsManager != null) { _currency = _settingsManager.GetString("payment.currency"); _settingsManager.OnSettingsLoaded += OnSettingsChanged; _settingsManager.OnSettingsSaved += OnSettingsChanged; } if (_balanceManager != null) { // Подписываемся на события изменения баланса _balanceManager.OnBalanceChanged.AddListener(OnBalanceChanged); // Устанавливаем начальное значение UpdateBalanceDisplay(_balanceManager.CurrentBalance); } else { Debug.LogWarning("[BalanceDisplay] BalanceManager not found! Balance display will not work."); UpdateBalanceDisplay(0); } } private void OnDestroy() { if (_balanceManager != null) { _balanceManager.OnBalanceChanged.RemoveListener(OnBalanceChanged); } if (_settingsManager != null) { _settingsManager.OnSettingsLoaded -= OnSettingsChanged; _settingsManager.OnSettingsSaved -= OnSettingsChanged; } } /// /// Обработчик изменения настроек /// private void OnSettingsChanged() { if (_settingsManager != null) { _currency = _settingsManager.GetString("payment.currency"); // Обновляем отображение с новой валютой if (_balanceManager != null) { UpdateBalanceDisplay(_balanceManager.CurrentBalance); } else { UpdateBalanceDisplay(0); } } } /// /// Обработчик изменения баланса /// private void OnBalanceChanged(int newBalance) { UpdateBalanceDisplay(newBalance); if (animateOnChange && balanceText != null) { AnimateBalanceChange(); } } /// /// Обновляет текст баланса /// private void UpdateBalanceDisplay(int balance) { if (balanceText != null) { string balanceStr = string.Format(textFormat, balance); // Если отдельный TMP для валюты не задан, сохраняем старое поведение. if (currencyText == null && !string.IsNullOrEmpty(_currency)) { balanceStr += " " + _currency; } balanceText.text = balanceStr; } if (currencyText != null) { currencyText.text = string.IsNullOrEmpty(_currency) ? string.Empty : string.Format(currencyFormat, _currency); } } /// /// Анимирует изменение баланса (масштабирование) /// private void AnimateBalanceChange() { if (_animationCoroutine != null) { StopCoroutine(_animationCoroutine); } _animationCoroutine = StartCoroutine(ScaleAnimation()); } private System.Collections.IEnumerator ScaleAnimation() { float elapsed = 0f; while (elapsed < animationDuration) { elapsed += Time.unscaledDeltaTime; float t = elapsed / animationDuration; // Применяем кривую анимации float scaleMultiplier = scaleCurve.Evaluate(t); // Небольшое увеличение и возврат к исходному размеру float scale = Mathf.Lerp(1.2f, 1f, t); balanceText.transform.localScale = _originalScale * scale * scaleMultiplier; yield return null; } // Гарантируем возврат к исходному масштабу balanceText.transform.localScale = _originalScale; _animationCoroutine = null; } /// /// Принудительное обновление отображения (для отладки) /// public void ForceUpdate() { if (_balanceManager != null) { UpdateBalanceDisplay(_balanceManager.CurrentBalance); } } /// /// Изменить формат отображения текста /// public void SetTextFormat(string format) { textFormat = format; if (_balanceManager != null) { UpdateBalanceDisplay(_balanceManager.CurrentBalance); } } #if UNITY_EDITOR /// /// Для предварительного просмотра в редакторе /// private void OnValidate() { if (Application.isPlaying) return; if (balanceText != null) { balanceText.text = string.Format(textFormat, 0); } if (currencyText != null) { currencyText.text = string.Format(currencyFormat, "₽"); } } #endif } }