using System.Collections; using TMPro; using UnityEngine; using UnityEngine.UI; public class IntView : MonoBehaviour, ISettingView { [Header("Layout ссылки")] [SerializeField] private TextMeshProUGUI ValueLabel; [SerializeField] private Image LeftArrow; [SerializeField] private Image RightArrow; [SerializeField] private Color NormalColor; [SerializeField] private Color InactiveColor; [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}"; ValueLabel.text = $"{currentValue}"; } UpdateArrows(); } private void UpdateArrows() { LeftArrow.color = currentValue > minValue ? NormalColor : InactiveColor; RightArrow.color = currentValue < maxValue ? NormalColor : InactiveColor; } 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(); } }