You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CrowdControl/Assets/Feel/MMTools/Tools/MMGUI/MMProgressBar.cs

939 lines
31 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using MoreMountains.Tools;
#if MM_TEXTMESHPRO
using TMPro;
#endif
using UnityEngine.Events;
using UnityEngine.Serialization;
namespace MoreMountains.Tools
{
/// <summary>
/// Add this bar to an object and link it to a bar (possibly the same object the script is on), and you'll be able to resize the bar object based on a current value, located between a min and max value.
/// See the HealthBar.cs script for a use case
/// </summary>
[MMRequiresConstantRepaint]
[AddComponentMenu("More Mountains/Tools/GUI/MMProgressBar")]
public class MMProgressBar : MMMonoBehaviour
{
public enum MMProgressBarStates {Idle, Decreasing, Increasing, InDecreasingDelay, InIncreasingDelay }
/// the possible fill modes
public enum FillModes { LocalScale, FillAmount, Width, Height, Anchor }
/// the possible directions for the fill (for local scale and fill amount only)
public enum BarDirections { LeftToRight, RightToLeft, UpToDown, DownToUp }
/// the possible timescales the bar can work on
public enum TimeScales { UnscaledTime, Time }
/// the possible ways to animate the bar fill
public enum BarFillModes { SpeedBased, FixedDuration }
[MMInspectorGroup("Bindings", true, 10)]
/// optional - the ID of the player associated to this bar
[Tooltip("optional - the ID of the player associated to this bar")]
public string PlayerID;
/// the main, foreground bar
[Tooltip("the main, foreground bar")]
public Transform ForegroundBar;
/// the delayed bar that will show when moving from a value to a new, lower value
[Tooltip("the delayed bar that will show when moving from a value to a new, lower value")]
[FormerlySerializedAs("DelayedBar")]
public Transform DelayedBarDecreasing;
/// the delayed bar that will show when moving from a value to a new, higher value
[Tooltip("the delayed bar that will show when moving from a value to a new, higher value")]
public Transform DelayedBarIncreasing;
[MMInspectorGroup("Fill Settings", true, 11)]
/// the local scale or fillamount value to reach when the value associated to the bar is at 0%
[FormerlySerializedAs("StartValue")]
[Range(0f,1f)]
[Tooltip("the local scale or fillamount value to reach when the value associated to the bar is at 0%")]
public float MinimumBarFillValue = 0f;
/// the local scale or fillamount value to reach when the bar is full
[FormerlySerializedAs("EndValue")]
[Range(0f,1f)]
[Tooltip("the local scale or fillamount value to reach when the bar is full")]
public float MaximumBarFillValue = 1f;
/// whether or not to initialize the value of the bar on start
[Tooltip("whether or not to initialize the value of the bar on start")]
public bool SetInitialFillValueOnStart = false;
/// the initial value of the bar
[MMCondition("SetInitialFillValueOnStart", true)]
[Range(0f,1f)]
[Tooltip("the initial value of the bar")]
public float InitialFillValue = 0f;
/// the direction this bar moves to
[Tooltip("the direction this bar moves to")]
public BarDirections BarDirection = BarDirections.LeftToRight;
/// the foreground bar's fill mode
[Tooltip("the foreground bar's fill mode")]
public FillModes FillMode = FillModes.LocalScale;
/// defines whether the bar will work on scaled or unscaled time (whether or not it'll keep moving if time is slowed down for example)
[Tooltip("defines whether the bar will work on scaled or unscaled time (whether or not it'll keep moving if time is slowed down for example)")]
public TimeScales TimeScale = TimeScales.UnscaledTime;
/// the selected fill animation mode
[Tooltip("the selected fill animation mode")]
public BarFillModes BarFillMode = BarFillModes.SpeedBased;
[MMInspectorGroup("Foreground Bar Settings", true, 12)]
/// whether or not the foreground bar should lerp
[Tooltip("whether or not the foreground bar should lerp")]
public bool LerpForegroundBar = true;
/// the speed at which to lerp the foreground bar
[Tooltip("the speed at which to lerp the foreground bar")]
[MMCondition("LerpForegroundBar", true)]
public float LerpForegroundBarSpeedDecreasing = 15f;
/// the speed at which to lerp the foreground bar if value is increasing
[Tooltip("the speed at which to lerp the foreground bar if value is increasing")]
[FormerlySerializedAs("LerpForegroundBarSpeed")]
[MMCondition("LerpForegroundBar", true)]
public float LerpForegroundBarSpeedIncreasing = 15f;
/// the speed at which to lerp the foreground bar if speed is decreasing
[Tooltip("the speed at which to lerp the foreground bar if speed is decreasing")]
[MMCondition("LerpForegroundBar", true)]
public float LerpForegroundBarDurationDecreasing = 0.2f;
/// the duration each update of the foreground bar should take (only if in fixed duration bar fill mode)
[Tooltip("the duration each update of the foreground bar should take (only if in fixed duration bar fill mode)")]
[MMCondition("LerpForegroundBar", true)]
public float LerpForegroundBarDurationIncreasing = 0.2f;
/// the curve to use when animating the foreground bar fill decreasing
[Tooltip("the curve to use when animating the foreground bar fill decreasing")]
[MMCondition("LerpForegroundBar", true)]
public AnimationCurve LerpForegroundBarCurveDecreasing = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
/// the curve to use when animating the foreground bar fill increasing
[Tooltip("the curve to use when animating the foreground bar fill increasing")]
[MMCondition("LerpForegroundBar", true)]
public AnimationCurve LerpForegroundBarCurveIncreasing = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
[MMInspectorGroup("Delayed Bar Decreasing", true, 13)]
/// the delay before the delayed bar moves (in seconds)
[Tooltip("the delay before the delayed bar moves (in seconds)")]
[FormerlySerializedAs("Delay")]
public float DecreasingDelay = 1f;
/// whether or not the delayed bar's animation should lerp
[Tooltip("whether or not the delayed bar's animation should lerp")]
[FormerlySerializedAs("LerpDelayedBar")]
public bool LerpDecreasingDelayedBar = true;
/// the speed at which to lerp the delayed bar
[Tooltip("the speed at which to lerp the delayed bar")]
[FormerlySerializedAs("LerpDelayedBarSpeed")]
[MMCondition("LerpDecreasingDelayedBar", true)]
public float LerpDecreasingDelayedBarSpeed = 15f;
/// the duration each update of the foreground bar should take (only if in fixed duration bar fill mode)
[Tooltip("the duration each update of the foreground bar should take (only if in fixed duration bar fill mode)")]
[FormerlySerializedAs("LerpDelayedBarDuration")]
[MMCondition("LerpDecreasingDelayedBar", true)]
public float LerpDecreasingDelayedBarDuration = 0.2f;
/// the curve to use when animating the delayed bar fill
[Tooltip("the curve to use when animating the delayed bar fill")]
[FormerlySerializedAs("LerpDelayedBarCurve")]
[MMCondition("LerpDecreasingDelayedBar", true)]
public AnimationCurve LerpDecreasingDelayedBarCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
[MMInspectorGroup("Delayed Bar Increasing", true, 18)]
/// the delay before the delayed bar moves (in seconds)
[Tooltip("the delay before the delayed bar moves (in seconds)")]
public float IncreasingDelay = 1f;
/// whether or not the delayed bar's animation should lerp
[Tooltip("whether or not the delayed bar's animation should lerp")]
public bool LerpIncreasingDelayedBar = true;
/// the speed at which to lerp the delayed bar
[Tooltip("the speed at which to lerp the delayed bar")]
[MMCondition("LerpIncreasingDelayedBar", true)]
public float LerpIncreasingDelayedBarSpeed = 15f;
/// the duration each update of the foreground bar should take (only if in fixed duration bar fill mode)
[Tooltip("the duration each update of the foreground bar should take (only if in fixed duration bar fill mode)")]
[MMCondition("LerpIncreasingDelayedBar", true)]
public float LerpIncreasingDelayedBarDuration = 0.2f;
/// the curve to use when animating the delayed bar fill
[Tooltip("the curve to use when animating the delayed bar fill")]
[MMCondition("LerpIncreasingDelayedBar", true)]
public AnimationCurve LerpIncreasingDelayedBarCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
[MMInspectorGroup("Bump", true, 14)]
/// whether or not the bar should "bump" when changing value
[Tooltip("whether or not the bar should 'bump' when changing value")]
public bool BumpScaleOnChange = true;
/// whether or not the bar should bump when its value increases
[Tooltip("whether or not the bar should bump when its value increases")]
public bool BumpOnIncrease = false;
/// whether or not the bar should bump when its value decreases
[Tooltip("whether or not the bar should bump when its value decreases")]
public bool BumpOnDecrease = false;
/// the duration of the bump animation
[Tooltip("the duration of the bump animation")]
public float BumpDuration = 0.2f;
/// whether or not the bar should flash when bumping
[Tooltip("whether or not the bar should flash when bumping")]
public bool ChangeColorWhenBumping = true;
/// whether or not to store the initial bar color before a bump
[Tooltip("whether or not to store the initial bar color before a bump")]
public bool StoreBarColorOnPlay = true;
/// the color to apply to the bar when bumping
[Tooltip("the color to apply to the bar when bumping")]
[MMCondition("ChangeColorWhenBumping", true)]
public Color BumpColor = Color.white;
/// the curve to map the bump animation on
[Tooltip("the curve to map the bump animation on")]
[FormerlySerializedAs("BumpAnimationCurve")]
public AnimationCurve BumpScaleAnimationCurve = new AnimationCurve(new Keyframe(1, 1), new Keyframe(0.3f, 1.05f), new Keyframe(1, 1));
/// the curve to map the bump animation color animation on
[Tooltip("the curve to map the bump animation color animation on")]
public AnimationCurve BumpColorAnimationCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.3f, 1f), new Keyframe(1, 0));
/// whether or not the bar is bumping right now
public bool Bumping { get; protected set; }
[MMInspectorGroup("Events", true, 16)]
/// an event to trigger every time the bar bumps
[Tooltip("an event to trigger every time the bar bumps")]
public UnityEvent OnBump;
/// an event to trigger every time the bar starts decreasing
[Tooltip("an event to trigger every time the bar starts decreasing")]
public UnityEvent OnBarMovementDecreasingStart;
/// an event to trigger every time the bar stops decreasing
[Tooltip("an event to trigger every time the bar stops decreasing")]
public UnityEvent OnBarMovementDecreasingStop;
/// an event to trigger every time the bar starts increasing
[Tooltip("an event to trigger every time the bar starts increasing")]
public UnityEvent OnBarMovementIncreasingStart;
/// an event to trigger every time the bar stops increasing
[Tooltip("an event to trigger every time the bar stops increasing")]
public UnityEvent OnBarMovementIncreasingStop;
[MMInspectorGroup("Text", true, 20)]
/// a Text object to update with the bar's value
[Tooltip("a Text object to update with the bar's value")]
public Text PercentageText;
#if MM_TEXTMESHPRO
/// a TMPro text object to update with the bar's value
[Tooltip("a TMPro text object to update with the bar's value")]
public TMP_Text PercentageTextMeshPro;
#endif
/// a prefix to always add to the bar's value display
[Tooltip("a prefix to always add to the bar's value display")]
public string TextPrefix;
/// a suffix to always add to the bar's value display
[Tooltip("a suffix to always add to the bar's value display")]
public string TextSuffix;
/// a value multiplier to always apply to the bar's value when displaying it
[Tooltip("a value multiplier to always apply to the bar's value when displaying it")]
public float TextValueMultiplier = 1f;
/// the format in which the text should display
[Tooltip("the format in which the text should display")]
public string TextFormat = "{000}";
/// whether or not to display the total after the current value
[Tooltip("whether or not to display the total after the current value")]
public bool DisplayTotal = false;
/// if DisplayTotal is true, the separator to put between the current value and the total
[Tooltip("if DisplayTotal is true, the separator to put between the current value and the total")]
[MMCondition("DisplayTotal", true)]
public string TotalSeparator = " / ";
[MMInspectorGroup("Debug", true, 15)]
/// the value the bar will move to if you press the DebugSet button
[Tooltip("the value the bar will move to if you press the DebugSet button")]
[Range(0f, 1f)]
public float DebugNewTargetValue;
[MMInspectorButton("DebugUpdateBar")]
public bool DebugUpdateBarButton;
[MMInspectorButton("DebugSetBar")]
public bool DebugSetBarButton;
[MMInspectorButton("Bump")]
public bool TestBumpButton;
[MMInspectorButton("Plus10Percent")]
public bool Plus10PercentButton;
[MMInspectorButton("Minus10Percent")]
public bool Minus10PercentButton;
[MMInspectorGroup("Debug Read Only", true, 19)]
/// the current progress of the bar, ideally read only
[Tooltip("the current progress of the bar, ideally read only")]
[Range(0f,1f)]
public float BarProgress;
/// the current progress of the bar, ideally read only
[Tooltip("the current progress of the bar, ideally read only")]
[Range(0f,1f)]
public float BarTarget;
/// the current progress of the delayed bar increasing
[Tooltip("the current progress of the delayed bar increasing")]
[Range(0f,1f)]
public float DelayedBarIncreasingProgress;
/// the current progress of the delayed bar decreasing
[Tooltip("the current progress of the delayed bar decreasing")]
[Range(0f,1f)]
public float DelayedBarDecreasingProgress;
protected bool _initialized;
protected Vector2 _initialBarSize;
protected Color _initialColor;
protected Vector3 _initialScale;
protected Image _foregroundImage;
protected Image _delayedDecreasingImage;
protected Image _delayedIncreasingImage;
protected Vector3 _targetLocalScale = Vector3.one;
protected float _newPercent;
protected float _percentLastTimeBarWasUpdated;
protected float _lastUpdateTimestamp;
protected float _time;
protected float _deltaTime;
protected int _direction;
protected Coroutine _coroutine;
protected bool _coroutineShouldRun = false;
protected bool _isDelayedBarIncreasingNotNull;
protected bool _isDelayedBarDecreasingNotNull;
protected bool _actualUpdate;
protected Vector2 _anchorVector;
protected float _delayedBarDecreasingProgress;
protected float _delayedBarIncreasingProgress;
protected MMProgressBarStates CurrentState = MMProgressBarStates.Idle;
protected string _updatedText;
protected string _totalText;
protected bool _isForegroundBarNotNull;
protected bool _isForegroundImageNotNull;
protected bool _isPercentageTextNotNull;
protected bool _isPercentageTextMeshProNotNull;
#region PUBLIC_API
/// <summary>
/// Updates the bar's values, using a normalized value
/// </summary>
/// <param name="normalizedValue"></param>
public virtual void UpdateBar01(float normalizedValue)
{
UpdateBar(Mathf.Clamp01(normalizedValue), 0f, 1f);
}
/// <summary>
/// Updates the bar's values based on the specified parameters
/// </summary>
/// <param name="currentValue">Current value.</param>
/// <param name="minValue">Minimum value.</param>
/// <param name="maxValue">Max value.</param>
public virtual void UpdateBar(float currentValue,float minValue,float maxValue)
{
if (!_initialized)
{
Initialization();
}
if (StoreBarColorOnPlay)
{
StoreInitialColor();
}
if (!this.gameObject.activeInHierarchy)
{
this.gameObject.SetActive(true);
}
_newPercent = MMMaths.Remap(currentValue, minValue, maxValue, MinimumBarFillValue, MaximumBarFillValue);
_actualUpdate = (BarTarget != _newPercent);
if (!_actualUpdate)
{
return;
}
if (CurrentState != MMProgressBarStates.Idle)
{
if ((CurrentState == MMProgressBarStates.Decreasing) ||
(CurrentState == MMProgressBarStates.InDecreasingDelay))
{
if (_newPercent >= BarTarget)
{
StopCoroutine(_coroutine);
SetBar01(BarTarget);
}
}
if ((CurrentState == MMProgressBarStates.Increasing) ||
(CurrentState == MMProgressBarStates.InIncreasingDelay))
{
if (_newPercent <= BarTarget)
{
StopCoroutine(_coroutine);
SetBar01(BarTarget);
}
}
}
_percentLastTimeBarWasUpdated = BarProgress;
_delayedBarDecreasingProgress = DelayedBarDecreasingProgress;
_delayedBarIncreasingProgress = DelayedBarIncreasingProgress;
BarTarget = _newPercent;
if ((_newPercent != _percentLastTimeBarWasUpdated) && !Bumping)
{
Bump();
}
DetermineDeltaTime();
_lastUpdateTimestamp = _time;
DetermineDirection();
if (_direction < 0)
{
OnBarMovementDecreasingStart?.Invoke();
}
else
{
OnBarMovementIncreasingStart?.Invoke();
}
if (_coroutine != null)
{
StopCoroutine(_coroutine);
}
_coroutineShouldRun = true;
if (this.gameObject.activeInHierarchy)
{
_coroutine = StartCoroutine(UpdateBarsCo());
}
else
{
SetBar(currentValue, minValue, maxValue);
}
UpdateText();
}
/// <summary>
/// Sets the bar value to the one specified
/// </summary>
/// <param name="currentValue"></param>
/// <param name="minValue"></param>
/// <param name="maxValue"></param>
public virtual void SetBar(float currentValue, float minValue, float maxValue)
{
float newPercent = MMMaths.Remap(currentValue, minValue, maxValue, 0f, 1f);
SetBar01(newPercent);
}
/// <summary>
/// Sets the bar value to the normalized value set in parameter
/// </summary>
/// <param name="newPercent"></param>
public virtual void SetBar01(float newPercent)
{
if (!_initialized)
{
Initialization();
}
newPercent = MMMaths.Remap(newPercent, 0f, 1f, MinimumBarFillValue, MaximumBarFillValue);
BarProgress = newPercent;
DelayedBarDecreasingProgress = newPercent;
DelayedBarIncreasingProgress = newPercent;
//_newPercent = newPercent;
BarTarget = newPercent;
_percentLastTimeBarWasUpdated = newPercent;
_delayedBarDecreasingProgress = DelayedBarDecreasingProgress;
_delayedBarIncreasingProgress = DelayedBarIncreasingProgress;
SetBarInternal(newPercent, ForegroundBar, _foregroundImage, _initialBarSize);
SetBarInternal(newPercent, DelayedBarDecreasing, _delayedDecreasingImage, _initialBarSize);
SetBarInternal(newPercent, DelayedBarIncreasing, _delayedIncreasingImage, _initialBarSize);
UpdateText();
_coroutineShouldRun = false;
CurrentState = MMProgressBarStates.Idle;
}
#endregion PUBLIC_API
#region START
/// <summary>
/// On start we store our image component
/// </summary>
protected virtual void Start()
{
Initialization();
}
protected virtual void OnEnable()
{
if (!_initialized)
{
return;
}
StoreInitialColor();
}
public virtual void Initialization()
{
_isForegroundBarNotNull = ForegroundBar != null;
_isDelayedBarDecreasingNotNull = DelayedBarDecreasing != null;
_isDelayedBarIncreasingNotNull = DelayedBarIncreasing != null;
_isPercentageTextNotNull = PercentageText != null;
#if MM_TEXTMESHPRO
_isPercentageTextMeshProNotNull = PercentageTextMeshPro != null;
#endif
_initialScale = this.transform.localScale;
if (_isForegroundBarNotNull)
{
_foregroundImage = ForegroundBar.GetComponent<Image>();
_isForegroundImageNotNull = _foregroundImage != null;
_initialBarSize = _foregroundImage.rectTransform.sizeDelta;
}
if (_isDelayedBarDecreasingNotNull)
{
_delayedDecreasingImage = DelayedBarDecreasing.GetComponent<Image>();
}
if (_isDelayedBarIncreasingNotNull)
{
_delayedIncreasingImage = DelayedBarIncreasing.GetComponent<Image>();
}
_initialized = true;
StoreInitialColor();
_percentLastTimeBarWasUpdated = BarProgress;
if (SetInitialFillValueOnStart)
{
SetBar01(InitialFillValue);
}
}
protected virtual void StoreInitialColor()
{
if (!Bumping && _isForegroundImageNotNull)
{
_initialColor = _foregroundImage.color;
}
}
#endregion START
#region TESTS
/// <summary>
/// This test method, called via the inspector button of the same name, lets you test what happens when you update the bar to a certain value
/// </summary>
protected virtual void DebugUpdateBar()
{
this.UpdateBar01(DebugNewTargetValue);
}
/// <summary>
/// Test method
/// </summary>
protected virtual void DebugSetBar()
{
this.SetBar01(DebugNewTargetValue);
}
/// <summary>
/// Test method
/// </summary>
public virtual void Plus10Percent()
{
float newProgress = BarTarget + 0.1f;
newProgress = Mathf.Clamp(newProgress, 0f, 1f);
UpdateBar01(newProgress);
}
/// <summary>
/// Test method
/// </summary>
public virtual void Minus10Percent()
{
float newProgress = BarTarget - 0.1f;
newProgress = Mathf.Clamp(newProgress, 0f, 1f);
UpdateBar01(newProgress);
}
#endregion TESTS
protected virtual void UpdateText()
{
_updatedText = TextPrefix + (BarTarget * TextValueMultiplier).ToString(TextFormat);
if (DisplayTotal)
{
_updatedText += TotalSeparator + (TextValueMultiplier).ToString(TextFormat);
}
_updatedText += TextSuffix;
if (_isPercentageTextNotNull)
{
PercentageText.text = _updatedText;
}
#if MM_TEXTMESHPRO
if (_isPercentageTextMeshProNotNull)
{
PercentageTextMeshPro.text = _updatedText;
}
#endif
}
/// <summary>
/// On Update we update our bars
/// </summary>
protected virtual IEnumerator UpdateBarsCo()
{
while (_coroutineShouldRun)
{
DetermineDeltaTime();
DetermineDirection();
UpdateBars();
yield return null;
}
CurrentState = MMProgressBarStates.Idle;
yield break;
}
protected virtual void DetermineDeltaTime()
{
_deltaTime = (TimeScale == TimeScales.Time) ? Time.deltaTime : Time.unscaledDeltaTime;
_time = (TimeScale == TimeScales.Time) ? Time.time : Time.unscaledTime;
}
protected virtual void DetermineDirection()
{
_direction = (_newPercent > _percentLastTimeBarWasUpdated) ? 1 : -1;
}
/// <summary>
/// Updates the foreground bar's scale
/// </summary>
protected virtual void UpdateBars()
{
float newFill;
float newFillDelayed;
float t1, t2 = 0f;
// if the value is decreasing
if (_direction < 0)
{
newFill = ComputeNewFill(LerpForegroundBar, LerpForegroundBarSpeedDecreasing, LerpForegroundBarDurationDecreasing, LerpForegroundBarCurveDecreasing, 0f, _percentLastTimeBarWasUpdated, out t1);
SetBarInternal(newFill, ForegroundBar, _foregroundImage, _initialBarSize);
SetBarInternal(newFill, DelayedBarIncreasing, _delayedIncreasingImage, _initialBarSize);
BarProgress = newFill;
DelayedBarIncreasingProgress = newFill;
CurrentState = MMProgressBarStates.Decreasing;
if (_time - _lastUpdateTimestamp > DecreasingDelay)
{
newFillDelayed = ComputeNewFill(LerpDecreasingDelayedBar, LerpDecreasingDelayedBarSpeed, LerpDecreasingDelayedBarDuration, LerpDecreasingDelayedBarCurve, DecreasingDelay,_delayedBarDecreasingProgress, out t2);
SetBarInternal(newFillDelayed, DelayedBarDecreasing, _delayedDecreasingImage, _initialBarSize);
DelayedBarDecreasingProgress = newFillDelayed;
CurrentState = MMProgressBarStates.InDecreasingDelay;
}
}
else // if the value is increasing
{
newFill = ComputeNewFill(LerpForegroundBar, LerpForegroundBarSpeedIncreasing, LerpForegroundBarDurationIncreasing, LerpForegroundBarCurveIncreasing, 0f, _delayedBarIncreasingProgress, out t1);
SetBarInternal(newFill, DelayedBarIncreasing, _delayedIncreasingImage, _initialBarSize);
DelayedBarIncreasingProgress = newFill;
CurrentState = MMProgressBarStates.Increasing;
if (DelayedBarIncreasing == null)
{
newFill = ComputeNewFill(LerpForegroundBar, LerpForegroundBarSpeedIncreasing, LerpForegroundBarDurationIncreasing, LerpForegroundBarCurveIncreasing, 0f, _percentLastTimeBarWasUpdated, out t2);
SetBarInternal(newFill, DelayedBarDecreasing, _delayedDecreasingImage, _initialBarSize);
SetBarInternal(newFill, ForegroundBar, _foregroundImage, _initialBarSize);
BarProgress = newFill;
DelayedBarDecreasingProgress = newFill;
CurrentState = MMProgressBarStates.InDecreasingDelay;
}
else
{
if (_time - _lastUpdateTimestamp > IncreasingDelay)
{
newFillDelayed = ComputeNewFill(LerpIncreasingDelayedBar, LerpForegroundBarSpeedIncreasing, LerpForegroundBarDurationIncreasing, LerpForegroundBarCurveIncreasing, IncreasingDelay, _delayedBarDecreasingProgress, out t2);
SetBarInternal(newFillDelayed, DelayedBarDecreasing, _delayedDecreasingImage, _initialBarSize);
SetBarInternal(newFillDelayed, ForegroundBar, _foregroundImage, _initialBarSize);
BarProgress = newFillDelayed;
DelayedBarDecreasingProgress = newFillDelayed;
CurrentState = MMProgressBarStates.InDecreasingDelay;
}
}
}
if ((t1 >= 1f) && (t2 >= 1f))
{
_coroutineShouldRun = false;
if (_direction > 0)
{
OnBarMovementIncreasingStop?.Invoke();
}
else
{
OnBarMovementDecreasingStop?.Invoke();
}
}
}
protected virtual float ComputeNewFill(bool lerpBar, float barSpeed, float barDuration, AnimationCurve barCurve, float delay, float lastPercent, out float t)
{
float newFill = 0f;
t = 0f;
if (lerpBar)
{
float delta = 0f;
float timeSpent = _time - _lastUpdateTimestamp - delay;
float speed = barSpeed;
if (speed == 0f) { speed = 1f; }
float duration = (BarFillMode == BarFillModes.FixedDuration) ? barDuration : (Mathf.Abs(_newPercent - lastPercent)) / speed;
delta = MMMaths.Remap(timeSpent, 0f, duration, 0f, 1f);
delta = Mathf.Clamp(delta, 0f, 1f);
t = delta;
if (t < 1f)
{
delta = barCurve.Evaluate(delta);
newFill = Mathf.LerpUnclamped(lastPercent, _newPercent, delta);
}
else
{
newFill = _newPercent;
}
}
else
{
newFill = _newPercent;
}
newFill = Mathf.Clamp( newFill, 0f, 1f);
return newFill;
}
protected virtual void SetBarInternal(float newAmount, Transform bar, Image image, Vector2 initialSize)
{
if (bar == null)
{
return;
}
switch (FillMode)
{
case FillModes.LocalScale:
_targetLocalScale = Vector3.one;
switch (BarDirection)
{
case BarDirections.LeftToRight:
_targetLocalScale.x = newAmount;
break;
case BarDirections.RightToLeft:
_targetLocalScale.x = 1f - newAmount;
break;
case BarDirections.DownToUp:
_targetLocalScale.y = newAmount;
break;
case BarDirections.UpToDown:
_targetLocalScale.y = 1f - newAmount;
break;
}
bar.localScale = _targetLocalScale;
break;
case FillModes.Width:
if (image == null)
{
return;
}
float newSizeX = MMMaths.Remap(newAmount, 0f, 1f, 0, initialSize.x);
image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, newSizeX);
break;
case FillModes.Height:
if (image == null)
{
return;
}
float newSizeY = MMMaths.Remap(newAmount, 0f, 1f, 0, initialSize.y);
image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, newSizeY);
break;
case FillModes.FillAmount:
if (image == null)
{
return;
}
image.fillAmount = newAmount;
break;
case FillModes.Anchor:
if (image == null)
{
return;
}
switch (BarDirection)
{
case BarDirections.LeftToRight:
_anchorVector.x = 0f;
_anchorVector.y = 0f;
image.rectTransform.anchorMin = _anchorVector;
_anchorVector.x = newAmount;
_anchorVector.y = 1f;
image.rectTransform.anchorMax = _anchorVector;
break;
case BarDirections.RightToLeft:
_anchorVector.x = newAmount;
_anchorVector.y = 0f;
image.rectTransform.anchorMin = _anchorVector;
_anchorVector.x = 1f;
_anchorVector.y = 1f;
image.rectTransform.anchorMax = _anchorVector;
break;
case BarDirections.DownToUp:
_anchorVector.x = 0f;
_anchorVector.y = 0f;
image.rectTransform.anchorMin = _anchorVector;
_anchorVector.x = 1f;
_anchorVector.y = newAmount;
image.rectTransform.anchorMax = _anchorVector;
break;
case BarDirections.UpToDown:
_anchorVector.x = 0f;
_anchorVector.y = newAmount;
image.rectTransform.anchorMin = _anchorVector;
_anchorVector.x = 1f;
_anchorVector.y = 1f;
image.rectTransform.anchorMax = _anchorVector;
break;
}
break;
}
}
#region Bump
/// <summary>
/// Triggers a camera bump
/// </summary>
public virtual void Bump()
{
bool shouldBump = false;
if (!_initialized)
{
return;
}
DetermineDirection();
if (BumpOnIncrease && (_direction > 0))
{
shouldBump = true;
}
if (BumpOnDecrease && (_direction < 0))
{
shouldBump = true;
}
if (BumpScaleOnChange)
{
shouldBump = true;
}
if (!shouldBump)
{
return;
}
if (this.gameObject.activeInHierarchy)
{
StartCoroutine(BumpCoroutine());
}
OnBump?.Invoke();
}
/// <summary>
/// A coroutine that (usually quickly) changes the scale of the bar
/// </summary>
/// <returns>The coroutine.</returns>
protected virtual IEnumerator BumpCoroutine()
{
float journey = 0f;
Bumping = true;
while (journey <= BumpDuration)
{
journey = journey + _deltaTime;
float percent = Mathf.Clamp01(journey / BumpDuration);
float curvePercent = BumpScaleAnimationCurve.Evaluate(percent);
float colorCurvePercent = BumpColorAnimationCurve.Evaluate(percent);
this.transform.localScale = curvePercent * _initialScale;
if (ChangeColorWhenBumping && _isForegroundImageNotNull)
{
_foregroundImage.color = Color.Lerp(_initialColor, BumpColor, colorCurvePercent);
}
yield return null;
}
if (ChangeColorWhenBumping && _isForegroundImageNotNull)
{
_foregroundImage.color = _initialColor;
}
Bumping = false;
yield return null;
}
#endregion Bump
#region ShowHide
/// <summary>
/// A simple method you can call to show the bar (set active true)
/// </summary>
public virtual void ShowBar()
{
this.gameObject.SetActive(true);
}
/// <summary>
/// Hides (SetActive false) the progress bar object, after an optional delay
/// </summary>
/// <param name="delay"></param>
public virtual void HideBar(float delay)
{
if (delay <= 0)
{
this.gameObject.SetActive(false);
}
else if (this.gameObject.activeInHierarchy)
{
StartCoroutine(HideBarCo(delay));
}
}
/// <summary>
/// An internal coroutine used to handle the disabling of the progress bar after a delay
/// </summary>
/// <param name="delay"></param>
/// <returns></returns>
protected virtual IEnumerator HideBarCo(float delay)
{
yield return MMCoroutine.WaitFor(delay);
this.gameObject.SetActive(false);
}
#endregion ShowHide
}
}