using UnityEngine; using UnityEngine.Events; using System.Collections; namespace TMPro { // Base interface for tweeners, // using an interface instead of // an abstract class as we want the // tweens to be structs. internal interface ITweenValue { void TweenValue(float floatPercentage); bool ignoreTimeScale { get; } float duration { get; } bool ValidTarget(); } // Color tween class, receives the // TweenValue callback and then sets // the value on the target. internal struct ColorTween : ITweenValue { public enum ColorTweenMode { All, RGB, Alpha } public class ColorTweenCallback : UnityEvent { } private ColorTweenCallback m_Target; private Color m_StartColor; private Color m_TargetColor; private ColorTweenMode m_TweenMode; private float m_Duration; private bool m_IgnoreTimeScale; public Color startColor { get { return m_StartColor; } set { m_StartColor = value; } } public Color targetColor { get { return m_TargetColor; } set { m_TargetColor = value; } } public ColorTweenMode tweenMode { get { return m_TweenMode; } set { m_TweenMode = value; } } public float duration { get { return m_Duration; } set { m_Duration = value; } } public bool ignoreTimeScale { get { return m_IgnoreTimeScale; } set { m_IgnoreTimeScale = value; } } public void TweenValue(float floatPercentage) { if (!ValidTarget()) return; var newColor = Color.Lerp(m_StartColor, m_TargetColor, floatPercentage); if (m_TweenMode == ColorTweenMode.Alpha) { newColor.r = m_StartColor.r; newColor.g = m_StartColor.g; newColor.b = m_StartColor.b; } else if (m_TweenMode == ColorTweenMode.RGB) { newColor.a = m_StartColor.a; } m_Target.Invoke(newColor); } public void AddOnChangedCallback(UnityAction callback) { if (m_Target == null) m_Target = new ColorTweenCallback(); m_Target.AddListener(callback); } public bool GetIgnoreTimescale() { return m_IgnoreTimeScale; } public float GetDuration() { return m_Duration; } public bool ValidTarget() { return m_Target != null; } } // Float tween class, receives the // TweenValue callback and then sets // the value on the target. internal struct FloatTween : ITweenValue { public class FloatTweenCallback : UnityEvent { } private FloatTweenCallback m_Target; private float m_StartValue; private float m_TargetValue; private float m_Duration; private bool m_IgnoreTimeScale; public float startValue { get { return m_StartValue; } set { m_StartValue = value; } } public float targetValue { get { return m_TargetValue; } set { m_TargetValue = value; } } public float duration { get { return m_Duration; } set { m_Duration = value; } } public bool ignoreTimeScale { get { return m_IgnoreTimeScale; } set { m_IgnoreTimeScale = value; } } public void TweenValue(float floatPercentage) { if (!ValidTarget()) return; var newValue = Mathf.Lerp(m_StartValue, m_TargetValue, floatPercentage); m_Target.Invoke(newValue); } public void AddOnChangedCallback(UnityAction callback) { if (m_Target == null) m_Target = new FloatTweenCallback(); m_Target.AddListener(callback); } public bool GetIgnoreTimescale() { return m_IgnoreTimeScale; } public float GetDuration() { return m_Duration; } public bool ValidTarget() { return m_Target != null; } } // Tween runner, executes the given tween. // The coroutine will live within the given // behaviour container. internal class TweenRunner where T : struct, ITweenValue { protected MonoBehaviour m_CoroutineContainer; protected IEnumerator m_Tween; // utility function for starting the tween private static IEnumerator Start(T tweenInfo) { if (!tweenInfo.ValidTarget()) yield break; var elapsedTime = 0.0f; while (elapsedTime < tweenInfo.duration) { elapsedTime += tweenInfo.ignoreTimeScale ? Time.unscaledDeltaTime : Time.deltaTime; var percentage = Mathf.Clamp01(elapsedTime / tweenInfo.duration); tweenInfo.TweenValue(percentage); yield return null; } tweenInfo.TweenValue(1.0f); } public void Init(MonoBehaviour coroutineContainer) { m_CoroutineContainer = coroutineContainer; } public void StartTween(T info) { if (m_CoroutineContainer == null) { Debug.LogWarning("Coroutine container not configured... did you forget to call Init?"); return; } StopTween(); if (!m_CoroutineContainer.gameObject.activeInHierarchy) { info.TweenValue(1.0f); return; } m_Tween = Start(info); m_CoroutineContainer.StartCoroutine(m_Tween); } public void StopTween() { if (m_Tween != null) { m_CoroutineContainer.StopCoroutine(m_Tween); m_Tween = null; } } } }