178 lines
5.0 KiB
C#

using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class IntView : MonoBehaviour, ISettingView
{
[Header("Layout ссылки")]
[SerializeField] private TextMeshProUGUI ValueLabel;
[SerializeField] private GameObject LeftArrow;
[SerializeField] private GameObject RightArrow;
[Header("Ускоренное переключение")]
[SerializeField] private float initialDelay = 0.5f; // Задержка перед началом ускорения
[SerializeField] private float minRepeatDelay = 0.05f; // Минимальная задержка между изменениями
[SerializeField] private float accelerationSpeed = 0.95f; // Скорость ускорения (чем меньше, тем быстрее)
[Header("Звук")]
[SerializeField] private bool UseSound = true;
[SerializeField] private AudioClip SwitchClip;
[SerializeField] private AudioSource Source;
// Кэш значений настройки
private int minValue;
private int maxValue;
private int currentValue;
private int step = 1;
// Состояние ускоренного переключения
private Coroutine accelerationCoroutine;
private int currentDirection = 0; // -1 = влево, 0 = нет, 1 = вправо
public SettingDTO CachedSetting { get; private set; }
public void Initialize(SettingDTO setting)
{
CachedSetting = setting;
CacheSettingValues(setting);
if (Source != null && SwitchClip != null)
Source.clip = SwitchClip;
UpdateUI();
}
public void TakeInput(int direction)
{
if (direction != 0)
{
if (currentDirection == direction)
return;
currentDirection = direction;
ChangeValue(currentDirection);
if (accelerationCoroutine != null)
StopCoroutine(accelerationCoroutine);
accelerationCoroutine = StartCoroutine(AcceleratedSwitching());
}
else
{
if (accelerationCoroutine != null)
{
StopCoroutine(accelerationCoroutine);
accelerationCoroutine = null;
}
currentDirection = 0;
if (UseSound && Source != null && Source.isPlaying)
Source.Stop();
}
}
private IEnumerator AcceleratedSwitching()
{
float delay = initialDelay;
yield return new WaitForSeconds(delay);
// Ускоренное переключение
while (currentDirection != 0)
{
ChangeValue(currentDirection);
delay = Mathf.Max(minRepeatDelay, delay * accelerationSpeed);
yield return new WaitForSeconds(delay);
}
}
private void ChangeValue(int direction)
{
if (direction == 0) return;
int newValue = currentValue + step * (int)Mathf.Sign(direction);
newValue = Mathf.Clamp(newValue, minValue, maxValue);
if (newValue == currentValue)
{
return;
}
currentValue = newValue;
CachedSetting.IntValue = currentValue;
if (UseSound)
PlaySound();
UpdateUI();
}
private void UpdateUI()
{
if (ValueLabel != null)
ValueLabel.text = currentValue.ToString();
UpdateArrows();
}
private void UpdateArrows()
{
LeftArrow.SetActive(currentValue > minValue);
RightArrow.SetActive(currentValue < maxValue);
}
private void PlaySound()
{
if (!UseSound || Source == null) return;
// Динамический питч в зависимости от скорости переключения
if (accelerationCoroutine != null)
{
// При ускоренном переключении повышаем питч
float pitchMultiplier = Mathf.Lerp(1f, 2f,
(initialDelay - Mathf.Max(minRepeatDelay,
initialDelay * Mathf.Pow(accelerationSpeed, 10))) / initialDelay);
Source.pitch = Mathf.Clamp(0.8f + pitchMultiplier * 0.5f, 0.8f, 1.5f);
}
else
{
Source.pitch = 1f;
}
Source.PlayOneShot(SwitchClip);
}
private void CacheSettingValues(SettingDTO setting)
{
minValue = setting.IntMin;
maxValue = setting.IntMax;
currentValue = setting.IntValue;
step = setting.IntStep;
if (step <= 0)
{
Debug.LogWarning($"Step is zero or negative ({step}), setting to 1", this);
step = 1;
}
if (minValue >= maxValue)
{
Debug.LogWarning($"Invalid range: min={minValue}, max={maxValue}", this);
}
}
private void OnDestroy()
{
if (accelerationCoroutine != null)
StopCoroutine(accelerationCoroutine);
if (Source != null && Source.isPlaying)
Source.Stop();
}
}