chip-gameV3/Assets/Scripts/Settings/PrizeStockPanel.cs
sega 826ff5782a Доработать игровые режимы, призы и настройки
Добавить таймеры и шкалы прогресса, расширить призовую систему и контроль остатков, восстановить настройки и обновить таблицу призов главного меню.
2026-09-14 10:47:25 +03:00

291 lines
9.7 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using DG.Tweening;
using PrizeSystem;
using TMPro;
using UnityEngine;
public sealed class PrizeStockPanel : MonoBehaviour, IControlable
{
public event Action OnClosed;
[SerializeField] private CanvasGroup _canvasGroup;
[SerializeField] private TextMeshProUGUI _count;
[SerializeField] private MToggle _controlToggle;
[SerializeField] private TextMeshProUGUI[] _options;
[SerializeField] private TextMeshProUGUI _description;
[SerializeField] private TextMeshProUGUI _hint;
[SerializeField] private float _fadeDuration = 0.25f;
[SerializeField] private Color _normalOptionColor = Color.white;
[SerializeField] private Color _selectedOptionColor = new Color(1f, 0.85f, 0.1f, 1f);
[Header("Ускорение числового ввода")]
[SerializeField] private float _accelerationTime = 0.8f;
[SerializeField] private int _maximumStepMultiplier = 10;
[SerializeField] private float _initialRepeatInterval = 0.5f;
[SerializeField] private float _minimumRepeatInterval = 0.03f;
[SerializeField] private AnimationCurve _accelerationCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
private const int ToggleOptionIndex = 0;
private const int AddOptionIndex = 1;
private const int SetOptionIndex = 2;
private const int BackOptionIndex = 3;
private const int DefaultAddAmount = 10;
private const int MaximumCount = 999999;
private Tween _fadeTween;
private int _selectedOptionIndex;
private int _addAmount;
private int _setAmount;
private bool _editingNumber;
private bool _actionReleased;
private bool _isClosing;
private bool _numberInputHeld;
private int _heldNumberDirection;
private int _heldNumberBaseStep;
private float _numberHoldTime;
private float _lastNumberChangeTime;
public bool ControlsEnabled { get; set; }
private void OnDisable()
{
PrizeStockService.StateChanged -= Refresh;
_fadeTween?.Kill();
_fadeTween = null;
ControlsEnabled = false;
ResetNumberInputRepeat();
}
public void Open()
{
_fadeTween?.Kill();
transform.SetAsLastSibling();
_canvasGroup.alpha = 0f;
_canvasGroup.blocksRaycasts = true;
_selectedOptionIndex = ToggleOptionIndex;
_addAmount = DefaultAddAmount;
_setAmount = PrizeStockService.Count;
_editingNumber = false;
_actionReleased = false;
_isClosing = false;
ResetNumberInputRepeat();
ControlsEnabled = true;
PrizeStockService.StateChanged -= Refresh;
PrizeStockService.StateChanged += Refresh;
_controlToggle.DisplayImmediate(PrizeStockService.Enabled);
Refresh();
_fadeTween = _canvasGroup.DOFade(1f, _fadeDuration).SetEase(Ease.OutCubic).SetUpdate(true);
_fadeTween.PlayForward();
}
public void UpdateControls()
{
if (_isClosing)
return;
Vector2Int axis = In.GetAxis(JoystickSide.Both, InteractMode.Discrete);
bool actionPressed = In.GetAction(JoystickSide.Both, InteractMode.Discrete);
bool actionHeld = In.GetAction(JoystickSide.Both, InteractMode.Continious);
if (actionHeld == false)
_actionReleased = true;
if (_editingNumber)
{
UpdateNumberEditing();
if (_actionReleased && actionPressed)
ApplyNumberChange();
return;
}
if (axis.y != 0)
{
int direction = axis.y > 0 ? -1 : 1;
_selectedOptionIndex = (_selectedOptionIndex + direction + _options.Length) % _options.Length;
RefreshSelection();
}
if (_selectedOptionIndex == ToggleOptionIndex && axis.x != 0)
SetControlEnabled(axis.x > 0);
if (_actionReleased && actionPressed)
ExecuteSelectedOption();
}
private void ExecuteSelectedOption()
{
_actionReleased = false;
if (_selectedOptionIndex == ToggleOptionIndex)
{
SetControlEnabled(PrizeStockService.Enabled == false);
return;
}
if (_selectedOptionIndex == AddOptionIndex || _selectedOptionIndex == SetOptionIndex)
{
_editingNumber = true;
ResetNumberInputRepeat();
RefreshSelection();
return;
}
Close();
}
private void UpdateNumberEditing()
{
Vector2Int axis = In.GetAxis(JoystickSide.Both, InteractMode.Continious);
UpdateNumberEditing(axis, Time.unscaledTime, Time.unscaledDeltaTime);
}
private void UpdateNumberEditing(Vector2Int axis, float currentTime, float deltaTime)
{
int direction = axis.y != 0 ? axis.y : axis.x;
int baseStep = axis.y != 0 ? 10 : 1;
if (direction == 0)
{
ResetNumberInputRepeat();
return;
}
if (_numberInputHeld == false
|| direction != _heldNumberDirection
|| baseStep != _heldNumberBaseStep)
{
_numberInputHeld = true;
_heldNumberDirection = direction;
_heldNumberBaseStep = baseStep;
_numberHoldTime = 0f;
_lastNumberChangeTime = currentTime;
ChangeEditedNumber(direction * baseStep);
return;
}
_numberHoldTime += deltaTime;
float progress = Mathf.Clamp01(_numberHoldTime / Mathf.Max(_accelerationTime, 0.01f));
float acceleration = _accelerationCurve.Evaluate(progress);
int maximumStepMultiplier = Mathf.Max(_maximumStepMultiplier, 1);
int stepMultiplier = 1 + Mathf.RoundToInt(acceleration * (maximumStepMultiplier - 1));
float initialRepeatInterval = Mathf.Max(_initialRepeatInterval, 0.01f);
float minimumRepeatInterval = Mathf.Clamp(_minimumRepeatInterval, 0.01f, initialRepeatInterval);
float repeatInterval = Mathf.Lerp(initialRepeatInterval, minimumRepeatInterval, acceleration);
if (currentTime - _lastNumberChangeTime < repeatInterval)
return;
_lastNumberChangeTime = currentTime;
ChangeEditedNumber(direction * baseStep * stepMultiplier);
}
private void ChangeEditedNumber(int delta)
{
if (delta == 0)
return;
if (_selectedOptionIndex == AddOptionIndex)
_addAmount = Mathf.Clamp(_addAmount + delta, 1, MaximumCount);
else
_setAmount = Mathf.Clamp(_setAmount + delta, 0, MaximumCount);
Refresh();
}
private void ApplyNumberChange()
{
_actionReleased = false;
ResetNumberInputRepeat();
if (_selectedOptionIndex == AddOptionIndex)
{
PrizeStockService.Add(_addAmount);
_setAmount = PrizeStockService.Count;
}
else
{
PrizeStockService.SetCount(_setAmount);
}
_editingNumber = false;
Refresh();
}
private void SetControlEnabled(bool enabled)
{
if (PrizeStockService.Enabled == enabled)
return;
PrizeStockService.SetEnabled(enabled);
_controlToggle.SetValue(enabled);
Refresh();
}
private void Refresh()
{
_count.text = PrizeStockService.Count.ToString();
_options[0].text = PrizeStockService.Enabled
? "КОНТРОЛЬ ОСТАТКОВ: ВКЛЮЧЁН"
: "КОНТРОЛЬ ОСТАТКОВ: ВЫКЛЮЧЕН";
_options[1].text = $"ДОБАВИТЬ ПРИЗЫ: +{_addAmount}";
_options[2].text = $"УСТАНОВИТЬ КОЛИЧЕСТВО: {_setAmount}";
RefreshSelection();
}
private void RefreshSelection()
{
for (int i = 0; i < _options.Length; i++)
{
bool selected = i == _selectedOptionIndex;
_options[i].color = selected ? _selectedOptionColor : _normalOptionColor;
_options[i].rectTransform.localScale = selected ? Vector3.one * 1.06f : Vector3.one;
}
if (_editingNumber)
{
_description.text = _selectedOptionIndex == AddOptionIndex
? "Добавляет выбранное число к текущему остатку."
: "Заменяет текущий остаток выбранным значением.";
_hint.text = "УДЕРЖИВАЙТЕ ДЖОЙСТИК ДЛЯ УСКОРЕНИЯ КНОПКА: ПРИМЕНИТЬ";
return;
}
_description.text = _selectedOptionIndex switch
{
ToggleOptionIndex => "При выключении остаток не списывается, а предупреждение в меню скрыто.",
AddOptionIndex => "Увеличивает текущий остаток на выбранное количество.",
SetOptionIndex => "Присваивает счётчику указанное количество призов.",
_ => "Вернуться к списку настроек."
};
_hint.text = "ВВЕРХ / ВНИЗ: ВЫБОР КНОПКА: ОТКРЫТЬ ВЛЕВО / ВПРАВО: ПЕРЕКЛЮЧИТЬ";
}
private void ResetNumberInputRepeat()
{
_numberInputHeld = false;
_heldNumberDirection = 0;
_heldNumberBaseStep = 0;
_numberHoldTime = 0f;
_lastNumberChangeTime = 0f;
}
private void Close()
{
if (_isClosing)
return;
_isClosing = true;
ControlsEnabled = false;
_fadeTween?.Kill();
_fadeTween = _canvasGroup.DOFade(0f, _fadeDuration).SetEase(Ease.InCubic).SetUpdate(true);
_fadeTween.OnComplete(() =>
{
_canvasGroup.blocksRaycasts = false;
OnClosed?.Invoke();
});
_fadeTween.PlayForward();
}
}