Files
beyond/Assets/Scripts/UI/ScalableSliderController.cs
2024-11-20 15:21:28 +01:00

159 lines
5.9 KiB
C#

using DG.Tweening;
using Sirenix.OdinInspector;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Beyond
{
public class ScalableSliderController : MonoBehaviour
{
[SerializeField]
private float maskTopOffset = -0.05f, maxHealthOffset = 1f, vesselRightOffset = 0.15f, fillBackgroundOffset = 0.1f, fillBackgroundTopOffset;
[SerializeField]
private float animationValueChangeThreshold = 0.05f, loadingEffectDelay = 0.5f, effectSpeed = 0.5f, flashDuration = 0.3f;
private float scale = 1f;
private float currentValue = 1f, currentAnimatedValue = 1f;
public Image barMask, barFill, barEffectMask, barFillEffect, barFillBackground, barVessel, barDecoration;
//for stamina
[SerializeField]
private bool useHeightAsWidth;
[SerializeField]
private bool flashBar = true;
private bool isAnimating = false;
[SerializeField]
private Vector2 barFillInitialSize;
private Color initialColor = new Color(1, 1, 1, 1), flashColor = new Color(1, 1, 1, 0);
[SerializeField]
private float baseSizeScale = 1f;
[Button]
public void Initialize()
{
if (useHeightAsWidth)
{
barFillInitialSize = new Vector2(barFill.rectTransform.sizeDelta.y - barFill.rectTransform.offsetMax.y, barFill.rectTransform.sizeDelta.x);
}
else
{
barFillInitialSize = barFill.rectTransform.sizeDelta;
}
}
private void OnEnable()
{
//cuz on cutscenes it could break
isAnimating = false;
SetValueWithEffectCoroutine(currentValue);
}
[Button]
public void SetScale(float scale)
{
this.scale = scale;
maxHealthOffset = barFillInitialSize.x * (baseSizeScale * scale - 1);
barMask.rectTransform.offsetMax = new Vector2(maxHealthOffset, maskTopOffset);
if (useHeightAsWidth)
{
barFill.rectTransform.sizeDelta = new Vector2(barFillInitialSize.y, (barFillInitialSize.x) * scale * baseSizeScale + barFill.rectTransform.offsetMax.y);
barFillEffect.rectTransform.sizeDelta = new Vector2(barFillInitialSize.y, (barFillInitialSize.x) * scale * baseSizeScale + barFill.rectTransform.offsetMax.y);
}
else
{
barFill.rectTransform.sizeDelta = new Vector2(barFillInitialSize.x * scale * baseSizeScale, barFillInitialSize.y);
barFillEffect.rectTransform.sizeDelta = new Vector2(barFillInitialSize.x * scale * baseSizeScale, barFillInitialSize.y);
}
barEffectMask.rectTransform.offsetMax = new Vector2(maxHealthOffset, maskTopOffset);
barFillBackground.rectTransform.sizeDelta = new Vector2(barFillInitialSize.x * scale * baseSizeScale - fillBackgroundOffset, fillBackgroundTopOffset);
barVessel.rectTransform.offsetMax = new Vector2(maxHealthOffset - vesselRightOffset, barVessel.rectTransform.offsetMax.y);
}
[ExecuteInEditMode]
[Button]
public void SetSliderValue(float value)
{
if (gameObject.activeInHierarchy)
{
StartCoroutine(SetValueWithEffectCoroutine(value));
}
}
[Button]
public void TakeDamage()
{
SetSliderValue(currentValue - 0.1f);
}
[Button]
public void HealDamage()
{
SetSliderValue(currentValue + 0.1f);
}
[ExecuteInEditMode]
private IEnumerator SetValueWithEffectCoroutine(float value)
{
float healthOffset = barFillInitialSize.x * (baseSizeScale * scale - 1);
float currentHealthOffset = healthOffset;
healthOffset -= (barFillInitialSize.x + healthOffset) * (1 - value);
float difference = currentValue - value;
if (flashBar && difference > animationValueChangeThreshold)
{
StartCoroutine(FlashBarColor());
}
currentValue = value;
barMask.rectTransform.offsetMax = new Vector2(healthOffset, maskTopOffset);
if ((difference < animationValueChangeThreshold) && !isAnimating)
{
currentAnimatedValue = currentValue;
barEffectMask.rectTransform.offsetMax = new Vector2(currentHealthOffset - (barFillInitialSize.x + currentHealthOffset) * (1 - currentAnimatedValue), maskTopOffset);
yield break;
}
isAnimating = true;
yield return new WaitForSeconds(loadingEffectDelay);
if (difference > animationValueChangeThreshold)
{
while (currentAnimatedValue > currentValue)
{
currentAnimatedValue -= Time.deltaTime * effectSpeed;
barEffectMask.rectTransform.offsetMax = new Vector2(currentHealthOffset - (barFillInitialSize.x + currentHealthOffset) * (1 - currentAnimatedValue), maskTopOffset);
yield return new WaitForEndOfFrame();
}
isAnimating = false;
}
}
private IEnumerator FlashBarColor()
{
float time = 0f;
while (time < flashDuration)
{
barFillBackground.color = Color.Lerp(Color.white, Color.black, time / flashDuration);
time += Time.deltaTime;
yield return new WaitForEndOfFrame();
}
time = 0f;
while (time < flashDuration)
{
barFillBackground.color = Color.Lerp(Color.black, Color.white, time / flashDuration);
time += Time.deltaTime;
yield return new WaitForEndOfFrame();
}
barFillBackground.color = Color.white;
}
}
}