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; } } }