using UnityEngine;
using UnityEngine.Events;
namespace WXB
{
public class Tweener
{
public enum Method
{
Linear,
EaseIn,
EaseOut,
EaseInOut,
BounceIn,
BounceOut,
}
public enum Style
{
Once,
Loop,
PingPong,
}
public Method method = Method.Linear;
public Style style = Style.Once;
public float duration = 1f;
float mDuration = 0f;
float mAmountPerDelta = 1000f;
float mFactor = 0f;
///
/// Amount advanced per delta time.
///
public float amountPerDelta
{
get
{
if (duration == 0f) return 1000f;
if (mDuration != duration)
{
mDuration = duration;
mAmountPerDelta = Mathf.Abs(1f / duration) * Mathf.Sign(mAmountPerDelta);
}
return mAmountPerDelta;
}
}
///
/// Tween factor, 0-1 range.
///
public float tweenFactor { get { return mFactor; } set { mFactor = Mathf.Clamp01(value); } }
public void Update(float delta)
{
// Advance the sampling factor
mFactor += (duration == 0f) ? 1f : amountPerDelta * delta;
// Loop style simply resets the play factor after it exceeds 1.
if (style == Style.Loop)
{
if (mFactor > 1f)
{
mFactor -= Mathf.Floor(mFactor);
}
}
else if (style == Style.PingPong)
{
// Ping-pong style reverses the direction
if (mFactor > 1f)
{
mFactor = 1f - (mFactor - Mathf.Floor(mFactor));
mAmountPerDelta = -mAmountPerDelta;
}
else if (mFactor < 0f)
{
mFactor = -mFactor;
mFactor -= Mathf.Floor(mFactor);
mAmountPerDelta = -mAmountPerDelta;
}
}
// If the factor goes out of range and this is a one-time tweening operation, disable the script
if ((style == Style.Once) && (duration == 0f || mFactor > 1f || mFactor < 0f))
{
mFactor = Mathf.Clamp01(mFactor);
Sample(mFactor, true);
}
else
{
Sample(mFactor, false);
}
}
///
/// Sample the tween at the specified factor.
///
public void Sample(float factor, bool isFinished)
{
// Calculate the sampling value
float val = Mathf.Clamp01(factor);
if (method == Method.EaseIn)
{
val = 1f - Mathf.Sin(0.5f * Mathf.PI * (1f - val));
}
else if (method == Method.EaseOut)
{
val = Mathf.Sin(0.5f * Mathf.PI * val);
}
else if (method == Method.EaseInOut)
{
const float pi2 = Mathf.PI * 2f;
val = val - Mathf.Sin(val * pi2) / pi2;
}
else if (method == Method.BounceIn)
{
val = BounceLogic(val);
}
else if (method == Method.BounceOut)
{
val = 1f - BounceLogic(1f - val);
}
if (OnUpdate != null)
OnUpdate(val, isFinished);
}
///
/// Main Bounce logic to simplify the Sample function
///
float BounceLogic(float val)
{
if (val < 0.363636f) // 0.363636 = (1/ 2.75)
{
val = 7.5685f * val * val;
}
else if (val < 0.727272f) // 0.727272 = (2 / 2.75)
{
val = 7.5625f * (val -= 0.545454f) * val + 0.75f; // 0.545454f = (1.5 / 2.75)
}
else if (val < 0.909090f) // 0.909090 = (2.5 / 2.75)
{
val = 7.5625f * (val -= 0.818181f) * val + 0.9375f; // 0.818181 = (2.25 / 2.75)
}
else
{
val = 7.5625f * (val -= 0.9545454f) * val + 0.984375f; // 0.9545454 = (2.625 / 2.75)
}
return val;
}
///
/// Manually activate the tweening process, reversing it if necessary.
///
public void Play(bool forward)
{
mAmountPerDelta = Mathf.Abs(amountPerDelta);
if (!forward) mAmountPerDelta = -mAmountPerDelta;
}
///
/// Manually reset the tweener's state to the beginning.
/// If the tween is playing forward, this means the tween's start.
/// If the tween is playing in reverse, this means the tween's end.
///
public void ResetToBeginning()
{
mFactor = (amountPerDelta < 0f) ? 1f : 0f;
Sample(mFactor, false);
}
///
/// Manually start the tweening process, reversing its direction.
///
public void Toggle()
{
if (mFactor > 0f)
{
mAmountPerDelta = -amountPerDelta;
}
else
{
mAmountPerDelta = Mathf.Abs(amountPerDelta);
}
}
///
/// Actual tweening logic should go here.
///
public System.Action OnUpdate;
}
}