Unity_Utils/Canvases/Components/SliderUIComponent.cs

151 lines
4.1 KiB
C#

using System;
using System.Collections;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.UI;
namespace Canvases.Components
{
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
public class SliderUIComponent : UISelectableComponentBase
{
public event Action<float> OnValueChanged;
[Header("Association"), SerializeField, Required]
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;
public float Value
{
get => currentValue;
set
{
if (isChangeValueAnimated)
{
targetValue = value;
StartAnimation();
}
else
{
currentValue = value;
slider.value = value;
}
}
}
public float MaxValue
{
get => slider.maxValue;
set => slider.maxValue = value;
}
public Color BackgroundColor
{
set
{
if (backgroundImage != null)
{
backgroundImage.color = value;
}
}
}
public Color FillColor
{
set
{
if (fillImage != null)
{
initialColor = value;
fillImage.color = initialColor;
}
}
}
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>();
}
}
}