627 lines
27 KiB
C#
627 lines
27 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
/**
|
|
* Interpolation utility functions: easing, bezier, and catmull-rom.
|
|
* Consider using Unity's Animation curve editor and AnimationCurve class
|
|
* before scripting the desired behaviour using this utility.
|
|
*
|
|
* Interpolation functionality available at different levels of abstraction.
|
|
* Low level access via individual easing functions (ex. EaseInOutCirc),
|
|
* Bezier(), and CatmullRom(). High level access using sequence generators,
|
|
* NewEase(), NewBezier(), and NewCatmullRom().
|
|
*
|
|
* Sequence generators are typically used as follows:
|
|
*
|
|
* IEnumerable<Vector3> sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration);
|
|
* foreach (Vector3 newPoint in sequence) {
|
|
* transform.position = newPoint;
|
|
* yield return WaitForSeconds(1.0f);
|
|
* }
|
|
*
|
|
* Or:
|
|
*
|
|
* IEnumerator<Vector3> sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration).GetEnumerator();
|
|
* function Update() {
|
|
* if (sequence.MoveNext()) {
|
|
* transform.position = sequence.Current;
|
|
* }
|
|
* }
|
|
*
|
|
* The low level functions work similarly to Unity's built in Lerp and it is
|
|
* up to you to track and pass in elapsedTime and duration on every call. The
|
|
* functions take this form (or the logical equivalent for Bezier() and CatmullRom()).
|
|
*
|
|
* transform.position = ease(start, distance, elapsedTime, duration);
|
|
*
|
|
* For convenience in configuration you can use the Ease(EaseType) function to
|
|
* look up a concrete easing function:
|
|
*
|
|
* [SerializeField]
|
|
* Interpolate.EaseType easeType; // set using Unity's property inspector
|
|
* Interpolate.Function ease; // easing of a particular EaseType
|
|
* function Awake() {
|
|
* ease = Interpolate.Ease(easeType);
|
|
* }
|
|
*
|
|
* @author Fernando Zapata (fernando@cpudreams.com)
|
|
* @Traduzione Andrea85cs (andrea85cs@dynematica.it)
|
|
*/
|
|
|
|
public class Interpolate {
|
|
|
|
|
|
/**
|
|
* Different methods of easing interpolation.
|
|
*/
|
|
public enum EaseType {
|
|
Linear,
|
|
EaseInQuad,
|
|
EaseOutQuad,
|
|
EaseInOutQuad,
|
|
EaseInCubic,
|
|
EaseOutCubic,
|
|
EaseInOutCubic,
|
|
EaseInQuart,
|
|
EaseOutQuart,
|
|
EaseInOutQuart,
|
|
EaseInQuint,
|
|
EaseOutQuint,
|
|
EaseInOutQuint,
|
|
EaseInSine,
|
|
EaseOutSine,
|
|
EaseInOutSine,
|
|
EaseInExpo,
|
|
EaseOutExpo,
|
|
EaseInOutExpo,
|
|
EaseInCirc,
|
|
EaseOutCirc,
|
|
EaseInOutCirc
|
|
}
|
|
|
|
/**
|
|
* Sequence of eleapsedTimes until elapsedTime is >= duration.
|
|
*
|
|
* Note: elapsedTimes are calculated using the value of Time.deltatTime each
|
|
* time a value is requested.
|
|
*/
|
|
static Vector3 Identity(Vector3 v) {
|
|
return v;
|
|
}
|
|
|
|
static Vector3 TransformDotPosition(Transform t) {
|
|
return t.position;
|
|
}
|
|
|
|
|
|
static IEnumerable<float> NewTimer(float duration) {
|
|
float elapsedTime = 0.0f;
|
|
while (elapsedTime < duration) {
|
|
yield return elapsedTime;
|
|
elapsedTime += Time.deltaTime;
|
|
// make sure last value is never skipped
|
|
if (elapsedTime >= duration) {
|
|
yield return elapsedTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
public delegate Vector3 ToVector3<T>(T v);
|
|
public delegate float Function(float a, float b, float c, float d);
|
|
|
|
/**
|
|
* Generates sequence of integers from start to end (inclusive) one step
|
|
* at a time.
|
|
*/
|
|
static IEnumerable<float> NewCounter(int start, int end, int step) {
|
|
for (int i = start; i <= end; i += step) {
|
|
yield return i;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns sequence generator from start to end over duration using the
|
|
* given easing function. The sequence is generated as it is accessed
|
|
* using the Time.deltaTime to calculate the portion of duration that has
|
|
* elapsed.
|
|
*/
|
|
public static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, float duration) {
|
|
IEnumerable<float> timer = Interpolate.NewTimer(duration);
|
|
return NewEase(ease, start, end, duration, timer);
|
|
}
|
|
|
|
/**
|
|
* Instead of easing based on time, generate n interpolated points (slices)
|
|
* between the start and end positions.
|
|
*/
|
|
public static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, int slices) {
|
|
IEnumerable<float> counter = Interpolate.NewCounter(0, slices + 1, 1);
|
|
return NewEase(ease, start, end, slices + 1, counter);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Generic easing sequence generator used to implement the time and
|
|
* slice variants. Normally you would not use this function directly.
|
|
*/
|
|
static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, float total, IEnumerable<float> driver) {
|
|
Vector3 distance = end - start;
|
|
foreach (float i in driver) {
|
|
yield return Ease(ease, start, distance, i, total);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Vector3 interpolation using given easing method. Easing is done independently
|
|
* on all three vector axis.
|
|
*/
|
|
static Vector3 Ease(Function ease, Vector3 start, Vector3 distance, float elapsedTime, float duration) {
|
|
start.x = ease(start.x, distance.x, elapsedTime, duration);
|
|
start.y = ease(start.y, distance.y, elapsedTime, duration);
|
|
start.z = ease(start.z, distance.z, elapsedTime, duration);
|
|
return start;
|
|
}
|
|
|
|
/**
|
|
* Returns the static method that implements the given easing type for scalars.
|
|
* Use this method to easily switch between easing interpolation types.
|
|
*
|
|
* All easing methods clamp elapsedTime so that it is always <= duration.
|
|
*
|
|
* var ease = Interpolate.Ease(EaseType.EaseInQuad);
|
|
* i = ease(start, distance, elapsedTime, duration);
|
|
*/
|
|
public static Function Ease(EaseType type) {
|
|
// Source Flash easing functions:
|
|
// http://gizma.com/easing/
|
|
// http://www.robertpenner.com/easing/easing_demo.html
|
|
//
|
|
// Changed to use more friendly variable names, that follow my Lerp
|
|
// conventions:
|
|
// start = b (start value)
|
|
// distance = c (change in value)
|
|
// elapsedTime = t (current time)
|
|
// duration = d (time duration)
|
|
|
|
Function f = null;
|
|
switch (type) {
|
|
case EaseType.Linear: f = Interpolate.Linear; break;
|
|
case EaseType.EaseInQuad: f = Interpolate.EaseInQuad; break;
|
|
case EaseType.EaseOutQuad: f = Interpolate.EaseOutQuad; break;
|
|
case EaseType.EaseInOutQuad: f = Interpolate.EaseInOutQuad; break;
|
|
case EaseType.EaseInCubic: f = Interpolate.EaseInCubic; break;
|
|
case EaseType.EaseOutCubic: f = Interpolate.EaseOutCubic; break;
|
|
case EaseType.EaseInOutCubic: f = Interpolate.EaseInOutCubic; break;
|
|
case EaseType.EaseInQuart: f = Interpolate.EaseInQuart; break;
|
|
case EaseType.EaseOutQuart: f = Interpolate.EaseOutQuart; break;
|
|
case EaseType.EaseInOutQuart: f = Interpolate.EaseInOutQuart; break;
|
|
case EaseType.EaseInQuint: f = Interpolate.EaseInQuint; break;
|
|
case EaseType.EaseOutQuint: f = Interpolate.EaseOutQuint; break;
|
|
case EaseType.EaseInOutQuint: f = Interpolate.EaseInOutQuint; break;
|
|
case EaseType.EaseInSine: f = Interpolate.EaseInSine; break;
|
|
case EaseType.EaseOutSine: f = Interpolate.EaseOutSine; break;
|
|
case EaseType.EaseInOutSine: f = Interpolate.EaseInOutSine; break;
|
|
case EaseType.EaseInExpo: f = Interpolate.EaseInExpo; break;
|
|
case EaseType.EaseOutExpo: f = Interpolate.EaseOutExpo; break;
|
|
case EaseType.EaseInOutExpo: f = Interpolate.EaseInOutExpo; break;
|
|
case EaseType.EaseInCirc: f = Interpolate.EaseInCirc; break;
|
|
case EaseType.EaseOutCirc: f = Interpolate.EaseOutCirc; break;
|
|
case EaseType.EaseInOutCirc: f = Interpolate.EaseInOutCirc; break;
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/**
|
|
* Returns sequence generator from the first node to the last node over
|
|
* duration time using the points in-between the first and last node
|
|
* as control points of a bezier curve used to generate the interpolated points
|
|
* in the sequence. If there are no control points (ie. only two nodes, first
|
|
* and last) then this behaves exactly the same as NewEase(). In other words
|
|
* a zero-degree bezier spline curve is just the easing method. The sequence
|
|
* is generated as it is accessed using the Time.deltaTime to calculate the
|
|
* portion of duration that has elapsed.
|
|
*/
|
|
public static IEnumerable<Vector3> NewBezier(Function ease, Transform[] nodes, float duration) {
|
|
IEnumerable<float> timer = Interpolate.NewTimer(duration);
|
|
return NewBezier<Transform>(ease, nodes, TransformDotPosition, duration, timer);
|
|
}
|
|
|
|
/**
|
|
* Instead of interpolating based on time, generate n interpolated points
|
|
* (slices) between the first and last node.
|
|
*/
|
|
public static IEnumerable<Vector3> NewBezier(Function ease, Transform[] nodes, int slices) {
|
|
IEnumerable<float> counter = NewCounter(0, slices + 1, 1);
|
|
return NewBezier<Transform>(ease, nodes, TransformDotPosition, slices + 1, counter);
|
|
}
|
|
|
|
/**
|
|
* A Vector3[] variation of the Transform[] NewBezier() function.
|
|
* Same functionality but using Vector3s to define bezier curve.
|
|
*/
|
|
public static IEnumerable<Vector3> NewBezier(Function ease, Vector3[] points, float duration) {
|
|
IEnumerable<float> timer = NewTimer(duration);
|
|
return NewBezier<Vector3>(ease, points, Identity, duration, timer);
|
|
}
|
|
|
|
/**
|
|
* A Vector3[] variation of the Transform[] NewBezier() function.
|
|
* Same functionality but using Vector3s to define bezier curve.
|
|
*/
|
|
public static IEnumerable<Vector3> NewBezier(Function ease, Vector3[] points, int slices) {
|
|
IEnumerable<float> counter = NewCounter(0, slices + 1, 1);
|
|
return NewBezier<Vector3>(ease, points, Identity, slices + 1, counter);
|
|
}
|
|
|
|
/**
|
|
* Generic bezier spline sequence generator used to implement the time and
|
|
* slice variants. Normally you would not use this function directly.
|
|
*/
|
|
static IEnumerable<Vector3> NewBezier<T>(Function ease, IList nodes, ToVector3<T> toVector3, float maxStep, IEnumerable<float> steps) {
|
|
// need at least two nodes to spline between
|
|
if (nodes.Count >= 2) {
|
|
// copy nodes array since Bezier is destructive
|
|
Vector3[] points = new Vector3[nodes.Count];
|
|
|
|
foreach (float step in steps) {
|
|
// re-initialize copy before each destructive call to Bezier
|
|
for (int i = 0; i < nodes.Count; i++) {
|
|
points[i] = toVector3((T)nodes[i]);
|
|
}
|
|
yield return Bezier(ease, points, step, maxStep);
|
|
// make sure last value is always generated
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A Vector3 n-degree bezier spline.
|
|
*
|
|
* WARNING: The points array is modified by Bezier. See NewBezier() for a
|
|
* safe and user friendly alternative.
|
|
*
|
|
* You can pass zero control points, just the start and end points, for just
|
|
* plain easing. In other words a zero-degree bezier spline curve is just the
|
|
* easing method.
|
|
*
|
|
* @param points start point, n control points, end point
|
|
*/
|
|
static Vector3 Bezier(Function ease, Vector3[] points, float elapsedTime, float duration) {
|
|
// Reference: http://ibiblio.org/e-notes/Splines/Bezier.htm
|
|
// Interpolate the n starting points to generate the next j = (n - 1) points,
|
|
// then interpolate those n - 1 points to generate the next n - 2 points,
|
|
// continue this until we have generated the last point (n - (n - 1)), j = 1.
|
|
// We store the next set of output points in the same array as the
|
|
// input points used to generate them. This works because we store the
|
|
// result in the slot of the input point that is no longer used for this
|
|
// iteration.
|
|
for (int j = points.Length - 1; j > 0; j--) {
|
|
for (int i = 0; i < j; i++) {
|
|
points[i].x = ease(points[i].x, points[i + 1].x - points[i].x, elapsedTime, duration);
|
|
points[i].y = ease(points[i].y, points[i + 1].y - points[i].y, elapsedTime, duration);
|
|
points[i].z = ease(points[i].z, points[i + 1].z - points[i].z, elapsedTime, duration);
|
|
}
|
|
}
|
|
return points[0];
|
|
}
|
|
|
|
/**
|
|
* Returns sequence generator from the first node, through each control point,
|
|
* and to the last node. N points are generated between each node (slices)
|
|
* using Catmull-Rom.
|
|
*/
|
|
public static IEnumerable<Vector3> NewCatmullRom(Transform[] nodes, int slices, bool loop) {
|
|
return NewCatmullRom<Transform>(nodes, TransformDotPosition, slices, loop);
|
|
}
|
|
|
|
/**
|
|
* A Vector3[] variation of the Transform[] NewCatmullRom() function.
|
|
* Same functionality but using Vector3s to define curve.
|
|
*/
|
|
public static IEnumerable<Vector3> NewCatmullRom(Vector3[] points, int slices, bool loop) {
|
|
return NewCatmullRom<Vector3>(points, Identity, slices, loop);
|
|
}
|
|
|
|
/**
|
|
* Generic catmull-rom spline sequence generator used to implement the
|
|
* Vector3[] and Transform[] variants. Normally you would not use this
|
|
* function directly.
|
|
*/
|
|
static IEnumerable<Vector3> NewCatmullRom<T>(IList nodes, ToVector3<T> toVector3, int slices, bool loop) {
|
|
// need at least two nodes to spline between
|
|
if (nodes.Count >= 2) {
|
|
|
|
// yield the first point explicitly, if looping the first point
|
|
// will be generated again in the step for loop when interpolating
|
|
// from last point back to the first point
|
|
yield return toVector3((T)nodes[0]);
|
|
|
|
int last = nodes.Count - 1;
|
|
for (int current = 0; loop || current < last; current++) {
|
|
// wrap around when looping
|
|
if (loop && current > last) {
|
|
current = 0;
|
|
}
|
|
// handle edge cases for looping and non-looping scenarios
|
|
// when looping we wrap around, when not looping use start for previous
|
|
// and end for next when you at the ends of the nodes array
|
|
int previous = (current == 0) ? ((loop) ? last : current) : current - 1;
|
|
int start = current;
|
|
int end = (current == last) ? ((loop) ? 0 : current) : current + 1;
|
|
int next = (end == last) ? ((loop) ? 0 : end) : end + 1;
|
|
|
|
// adding one guarantees yielding at least the end point
|
|
int stepCount = slices + 1;
|
|
for (int step = 1; step <= stepCount; step++) {
|
|
yield return CatmullRom(toVector3((T)nodes[previous]),
|
|
toVector3((T)nodes[start]),
|
|
toVector3((T)nodes[end]),
|
|
toVector3((T)nodes[next]),
|
|
step, stepCount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A Vector3 Catmull-Rom spline. Catmull-Rom splines are similar to bezier
|
|
* splines but have the useful property that the generated curve will go
|
|
* through each of the control points.
|
|
*
|
|
* NOTE: The NewCatmullRom() functions are an easier to use alternative to this
|
|
* raw Catmull-Rom implementation.
|
|
*
|
|
* @param previous the point just before the start point or the start point
|
|
* itself if no previous point is available
|
|
* @param start generated when elapsedTime == 0
|
|
* @param end generated when elapsedTime >= duration
|
|
* @param next the point just after the end point or the end point itself if no
|
|
* next point is available
|
|
*/
|
|
static Vector3 CatmullRom(Vector3 previous, Vector3 start, Vector3 end, Vector3 next,
|
|
float elapsedTime, float duration) {
|
|
// References used:
|
|
// p.266 GemsV1
|
|
//
|
|
// tension is often set to 0.5 but you can use any reasonable value:
|
|
// http://www.cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
|
|
//
|
|
// bias and tension controls:
|
|
// http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/
|
|
|
|
float percentComplete = elapsedTime / duration;
|
|
float percentCompleteSquared = percentComplete * percentComplete;
|
|
float percentCompleteCubed = percentCompleteSquared * percentComplete;
|
|
|
|
return previous * (-0.5f * percentCompleteCubed +
|
|
percentCompleteSquared -
|
|
0.5f * percentComplete) +
|
|
start * ( 1.5f * percentCompleteCubed +
|
|
-2.5f * percentCompleteSquared + 1.0f) +
|
|
end * (-1.5f * percentCompleteCubed +
|
|
2.0f * percentCompleteSquared +
|
|
0.5f * percentComplete) +
|
|
next * ( 0.5f * percentCompleteCubed -
|
|
0.5f * percentCompleteSquared);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Linear interpolation (same as Mathf.Lerp)
|
|
*/
|
|
static float Linear(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime to be <= duration
|
|
if (elapsedTime > duration) { elapsedTime = duration; }
|
|
return distance * (elapsedTime / duration) + start;
|
|
}
|
|
|
|
/**
|
|
* quadratic easing in - accelerating from zero velocity
|
|
*/
|
|
static float EaseInQuad(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
return distance * elapsedTime * elapsedTime + start;
|
|
}
|
|
|
|
/**
|
|
* quadratic easing out - decelerating to zero velocity
|
|
*/
|
|
static float EaseOutQuad(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
return -distance * elapsedTime * (elapsedTime - 2) + start;
|
|
}
|
|
|
|
/**
|
|
* quadratic easing in/out - acceleration until halfway, then deceleration
|
|
*/
|
|
static float EaseInOutQuad(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
|
|
if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime + start;
|
|
elapsedTime--;
|
|
return -distance / 2 * (elapsedTime * (elapsedTime - 2) - 1) + start;
|
|
}
|
|
|
|
/**
|
|
* cubic easing in - accelerating from zero velocity
|
|
*/
|
|
static float EaseInCubic(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
return distance * elapsedTime * elapsedTime * elapsedTime + start;
|
|
}
|
|
|
|
/**
|
|
* cubic easing out - decelerating to zero velocity
|
|
*/
|
|
static float EaseOutCubic(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
elapsedTime--;
|
|
return distance * (elapsedTime * elapsedTime * elapsedTime + 1) + start;
|
|
}
|
|
|
|
/**
|
|
* cubic easing in/out - acceleration until halfway, then deceleration
|
|
*/
|
|
static float EaseInOutCubic(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
|
|
if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime + start;
|
|
elapsedTime -= 2;
|
|
return distance / 2 * (elapsedTime * elapsedTime * elapsedTime + 2) + start;
|
|
}
|
|
|
|
/**
|
|
* quartic easing in - accelerating from zero velocity
|
|
*/
|
|
static float EaseInQuart(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
|
|
}
|
|
|
|
/**
|
|
* quartic easing out - decelerating to zero velocity
|
|
*/
|
|
static float EaseOutQuart(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
elapsedTime--;
|
|
return -distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 1) + start;
|
|
}
|
|
|
|
/**
|
|
* quartic easing in/out - acceleration until halfway, then deceleration
|
|
*/
|
|
static float EaseInOutQuart(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
|
|
if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
|
|
elapsedTime -= 2;
|
|
return -distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 2) + start;
|
|
}
|
|
|
|
|
|
/**
|
|
* quintic easing in - accelerating from zero velocity
|
|
*/
|
|
static float EaseInQuint(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
|
|
}
|
|
|
|
/**
|
|
* quintic easing out - decelerating to zero velocity
|
|
*/
|
|
static float EaseOutQuint(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
elapsedTime--;
|
|
return distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 1) + start;
|
|
}
|
|
|
|
/**
|
|
* quintic easing in/out - acceleration until halfway, then deceleration
|
|
*/
|
|
static float EaseInOutQuint(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2f);
|
|
if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
|
|
elapsedTime -= 2;
|
|
return distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 2) + start;
|
|
}
|
|
|
|
/**
|
|
* sinusoidal easing in - accelerating from zero velocity
|
|
*/
|
|
static float EaseInSine(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime to be <= duration
|
|
if (elapsedTime > duration) { elapsedTime = duration; }
|
|
return -distance * Mathf.Cos(elapsedTime / duration * (Mathf.PI / 2)) + distance + start;
|
|
}
|
|
|
|
/**
|
|
* sinusoidal easing out - decelerating to zero velocity
|
|
*/
|
|
static float EaseOutSine(float start, float distance, float elapsedTime, float duration) {
|
|
if (elapsedTime > duration) { elapsedTime = duration; }
|
|
return distance * Mathf.Sin(elapsedTime / duration * (Mathf.PI / 2)) + start;
|
|
}
|
|
|
|
/**
|
|
* sinusoidal easing in/out - accelerating until halfway, then decelerating
|
|
*/
|
|
static float EaseInOutSine(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime to be <= duration
|
|
if (elapsedTime > duration) { elapsedTime = duration; }
|
|
return -distance / 2 * (Mathf.Cos(Mathf.PI * elapsedTime / duration) - 1) + start;
|
|
}
|
|
|
|
/**
|
|
* exponential easing in - accelerating from zero velocity
|
|
*/
|
|
static float EaseInExpo(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime to be <= duration
|
|
if (elapsedTime > duration) { elapsedTime = duration; }
|
|
return distance * Mathf.Pow(2, 10 * (elapsedTime / duration - 1)) + start;
|
|
}
|
|
|
|
/**
|
|
* exponential easing out - decelerating to zero velocity
|
|
*/
|
|
static float EaseOutExpo(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime to be <= duration
|
|
if (elapsedTime > duration) { elapsedTime = duration; }
|
|
return distance * (-Mathf.Pow(2, -10 * elapsedTime / duration) + 1) + start;
|
|
}
|
|
|
|
/**
|
|
* exponential easing in/out - accelerating until halfway, then decelerating
|
|
*/
|
|
static float EaseInOutExpo(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
|
|
if (elapsedTime < 1) return distance / 2 * Mathf.Pow(2, 10 * (elapsedTime - 1)) + start;
|
|
elapsedTime--;
|
|
return distance / 2 * (-Mathf.Pow(2, -10 * elapsedTime) + 2) + start;
|
|
}
|
|
|
|
/**
|
|
* circular easing in - accelerating from zero velocity
|
|
*/
|
|
static float EaseInCirc(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
return -distance * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) - 1) + start;
|
|
}
|
|
|
|
/**
|
|
* circular easing out - decelerating to zero velocity
|
|
*/
|
|
static float EaseOutCirc(float start, float distance, float elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
|
|
elapsedTime--;
|
|
return distance * Mathf.Sqrt(1 - elapsedTime * elapsedTime) + start;
|
|
}
|
|
|
|
/**
|
|
* circular easing in/out - acceleration until halfway, then deceleration
|
|
*/
|
|
static float EaseInOutCirc(float start, float distance, float
|
|
elapsedTime, float duration) {
|
|
// clamp elapsedTime so that it cannot be greater than duration
|
|
elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
|
|
if (elapsedTime < 1) return -distance / 2 * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) - 1) + start;
|
|
elapsedTime -= 2;
|
|
return distance / 2 * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) + 1) + start;
|
|
}
|
|
}
|