2023-03-17 23:41:38 -04:00

161 lines
4.3 KiB
C#

using System;
using System.Collections;
using JetBrains.Annotations;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.UI;
#if ODIN_INSPECTOR
#endif
namespace JohnsonUtils.Canvases
{
public class SliderUIComponent : UISelectableComponentBase
{
[UsedImplicitly] public event Action<float> OnValueChanged;
#if ODIN_INSPECTOR
[Required]
#endif
[Header("Association"), SerializeField]
private Slider slider;
[SerializeField] private Image backgroundImage;
[SerializeField] private Image fillImage;
[SerializeField] private Image frame;
[Header("Animation"), SerializeField] private bool isChangeValueAnimated;
[SerializeField] [Range(0f, 1f)] private float animationSpeed = 0.05f;
[SerializeField] private Color valueIncreaseColor = Color.green;
[SerializeField] private Color valueDecreaseColor = Color.red;
private float _targetValue;
private float _currentValue;
private Coroutine _animationRoutine;
private Color _initialColor = Color.black;
[UsedImplicitly]
public float Value
{
get => _currentValue;
set
{
if (isChangeValueAnimated)
{
_targetValue = value;
StartAnimation();
}
else
{
_currentValue = value;
slider.value = value;
}
}
}
[UsedImplicitly]
public float MaxValue
{
get => slider.maxValue;
set => slider.maxValue = value;
}
[UsedImplicitly]
public Color BackgroundColor
{
set
{
if (backgroundImage != null)
{
backgroundImage.color = value;
}
}
}
[UsedImplicitly]
public Color FillColor
{
set
{
if (fillImage != null)
{
_initialColor = value;
fillImage.color = _initialColor;
}
}
}
[UsedImplicitly]
public Color FrameColor
{
set
{
if (frame != null)
{
frame.color = value;
}
}
}
private void Start()
{
Debug.Assert(slider, $"A {nameof(slider)} must be assigned to a {nameof(SliderUIComponent)}");
slider.onValueChanged.AddListener(OnSliderChanged);
}
protected override void SetSelectableGameObject() => Selectable = slider;
protected override void OnDestroy()
{
slider.onValueChanged.RemoveListener(OnSliderChanged);
base.OnDestroy();
}
private void StartAnimation()
{
if (_animationRoutine != null)
StopCoroutine(_animationRoutine);
_animationRoutine = StartCoroutine(AnimateValueChange(_targetValue > _currentValue));
}
private IEnumerator AnimateValueChange(bool isValueChangePositive)
{
if (isValueChangePositive)
{
fillImage.color = valueIncreaseColor;
while (_currentValue < _targetValue)
{
_currentValue += animationSpeed * Time.deltaTime;
slider.value = _currentValue;
yield return null;
}
}
else
{
fillImage.color = valueDecreaseColor;
while (_currentValue > _targetValue)
{
_currentValue -= animationSpeed * Time.deltaTime;
slider.value = _currentValue;
yield return null;
}
}
_currentValue = _targetValue;
slider.value = _currentValue;
fillImage.color = _initialColor;
}
private void OnSliderChanged(float value) => OnValueChanged?.Invoke(value);
private void OnValidate()
{
if (!slider)
slider = GetComponent<Slider>();
}
}
}