Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- доработан flow призовой витрины и связанного UI: добавлены `PrizeStandButtonView` и `RulesPrizeListPage`, обновлены `PrizeStandController`, `PrizeStandPrize`, `PrizeStandModal`, `PrizeStandSettingsModal`, `LevelPrizeSettingsModal`, `QRCodeSettingsModal`, `BalanceDisplay`, `ButtonTextFocusColor` и связанные prefab'ы, чтобы улучшить настройку, навигацию, отображение кнопок и prize flow - расширена система настроек и сохранения значений: `OptionPicker` получил отдельный формат `ValueSelector`, обновлены `SettingsDatabase`, `SettingEntryDrawer`, `SettingUIItem`, `SettingsUIGenerator`, `ValueSelectorRow` и `MainSettingsDatabase.asset`, а сохранение option picker-значений, включая `gameplay.gameDifficulty`, исправлено и синхронизировано с остальными настройками - добавлены универсальные спавнеры сущностей: реализованы `EntitySpawner` и `EntitySpawnerManager` с поддержкой весов префабов, точек спавна, заполнения по проценту, ограничений на количество и автоспавна при инициализации - доработана логика игрового спавна и сложности: процент инициализационного спавна может зависеть от настройки `gameplay.gameDifficulty` с градациями 25/50/75/100, в одном цикле массового спавна повторно не используется та же точка, а gizmo спавнера теперь показывает только сами точки без линий - упрощена работа в редакторе Unity и добавлены editor-инструменты: в `GameManager` лицензия пропускается при запуске в `UNITY_EDITOR`, а `HierarchySelectionCounter`, `HierarchySelectionCountOverlay` и `HierarchyBulkRenamerWindow` добавляют подсчет выделения, realtime overlay в `SceneView` и массовое переименование объектов по правилам нумерации из Unity Project Settings - синхронизированы сцены, ресурсы и UI-ассеты под новый flow: обновлены `MainMenu`, `Level UI`, уровни `1-1` и `1-2`, строки настроек, кнопки, TMP/font assets, изображения UI, `prizes.json` и recovery-данные после правок интерфейса и логики - очищены и переразложены часть внешних и служебных ресурсов: удалён пакет `Lava_Flowing_Shader`, переименованы/заменены отдельные UI-prefab'ы и добавлены сопутствующие проектные артефакты, которые сейчас используются обновлённой конфигурацией проекта
223 lines
7.5 KiB
C#
223 lines
7.5 KiB
C#
using RR.Common.Managers;
|
||
using RR.Common.Settings;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
|
||
namespace RR.Common.UI
|
||
{
|
||
/// <summary>
|
||
/// UI компонент для отображения текущего баланса игрока.
|
||
/// Автоматически обновляется при изменении баланса.
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Обработчик изменения настроек
|
||
/// </summary>
|
||
private void OnSettingsChanged()
|
||
{
|
||
if (_settingsManager != null)
|
||
{
|
||
_currency = _settingsManager.GetString("payment.currency");
|
||
|
||
// Обновляем отображение с новой валютой
|
||
if (_balanceManager != null)
|
||
{
|
||
UpdateBalanceDisplay(_balanceManager.CurrentBalance);
|
||
}
|
||
else
|
||
{
|
||
UpdateBalanceDisplay(0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Обработчик изменения баланса
|
||
/// </summary>
|
||
private void OnBalanceChanged(int newBalance)
|
||
{
|
||
UpdateBalanceDisplay(newBalance);
|
||
|
||
if (animateOnChange && balanceText != null)
|
||
{
|
||
AnimateBalanceChange();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Обновляет текст баланса
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Анимирует изменение баланса (масштабирование)
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Принудительное обновление отображения (для отладки)
|
||
/// </summary>
|
||
public void ForceUpdate()
|
||
{
|
||
if (_balanceManager != null)
|
||
{
|
||
UpdateBalanceDisplay(_balanceManager.CurrentBalance);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Изменить формат отображения текста
|
||
/// </summary>
|
||
public void SetTextFormat(string format)
|
||
{
|
||
textFormat = format;
|
||
if (_balanceManager != null)
|
||
{
|
||
UpdateBalanceDisplay(_balanceManager.CurrentBalance);
|
||
}
|
||
}
|
||
|
||
#if UNITY_EDITOR
|
||
/// <summary>
|
||
/// Для предварительного просмотра в редакторе
|
||
/// </summary>
|
||
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
|
||
}
|
||
}
|
||
|