Skip to content

Instantly share code, notes, and snippets.

@aprius
Forked from cjddmut/EasingFunctions.cs
Last active October 13, 2019 10:57
Show Gist options
  • Save aprius/a9d321647ac0e8ddb9f975053fca5819 to your computer and use it in GitHub Desktop.
Save aprius/a9d321647ac0e8ddb9f975053fca5819 to your computer and use it in GitHub Desktop.
Easing Functions for Unity3D
/*
* Created by C.J. Kimberlin
*
* The MIT License (MIT)
*
* Copyright (c) 2019
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
* TERMS OF USE - EASING EQUATIONS
* Open source under the BSD License.
* Copyright (c)2001 Robert Penner
* All rights reserved.
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* ============= Description =============
*
* Below is an example of how to use the easing functions in the file. There is a getting function that will return the function
* from an enum. This is useful since the enum can be exposed in the editor and then the function queried during Start().
*
* EasingFunction.Ease ease = EasingFunction.Ease.EaseInOutQuad;
* EasingFunction.EasingFunc func = GetEasingFunction(ease;
*
* float value = func(0, 10, 0.67f);
*
* EasingFunction.EaseingFunc derivativeFunc = GetEasingFunctionDerivative(ease);
*
* float derivativeValue = derivativeFunc(0, 10, 0.67f);
*/
using UnityEngine;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable once CheckNamespace
namespace UnityModule.UniTween
{
public enum EEase
{
Linear,
Spring,
InBack,
OutBack,
InOutBack,
InQuad,
OutQuad,
InOutQuad,
InCubic,
OutCubic,
InOutCubic,
InQuart,
OutQuart,
InOutQuart,
InQuint,
OutQuint,
InOutQuint,
InSine,
OutSine,
InOutSine,
InExpo,
OutExpo,
InOutExpo,
InCirc,
OutCirc,
InOutCirc,
InBounce,
OutBounce,
InOutBounce,
InElastic,
OutElastic,
InOutElastic,
}
public static class EaseManager
{
private const float NATURAL_LOG_OF_2 = 0.693147181f;
private const float PI = 3.141593f;
private const float HALF_PI = 1.570796f;
public static float Linear(float start, float end, float value)
{
return Mathf.Lerp(start, end, value);
}
public static float Spring(float start, float end, float value)
{
value = Mathf.Clamp01(value);
value = (Mathf.Sin(value * PI * (0.2f + 2.5f * value * value * value)) * Mathf.Pow(1f - value, 2.2f) + value) * (1f + (1.2f * (1f - value)));
return start + (end - start) * value;
}
public static float EaseInQuad(float start, float end, float value)
{
end -= start;
return end * value * value + start;
}
public static float EaseOutQuad(float start, float end, float value)
{
end -= start;
return -end * value * (value - 2) + start;
}
public static float EaseInOutQuad(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1) return end * 0.5f * value * value + start;
value--;
return -end * 0.5f * (value * (value - 2) - 1) + start;
}
public static float EaseInCubic(float start, float end, float value)
{
end -= start;
return end * value * value * value + start;
}
public static float EaseOutCubic(float start, float end, float value)
{
value--;
end -= start;
return end * (value * value * value + 1) + start;
}
public static float EaseInOutCubic(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1) return end * 0.5f * value * value * value + start;
value -= 2;
return end * 0.5f * (value * value * value + 2) + start;
}
public static float EaseInQuart(float start, float end, float value)
{
end -= start;
return end * value * value * value * value + start;
}
public static float EaseOutQuart(float start, float end, float value)
{
value--;
end -= start;
return -end * (value * value * value * value - 1) + start;
}
public static float EaseInOutQuart(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1) return end * 0.5f * value * value * value * value + start;
value -= 2;
return -end * 0.5f * (value * value * value * value - 2) + start;
}
public static float EaseInQuint(float start, float end, float value)
{
end -= start;
return end * value * value * value * value * value + start;
}
public static float EaseOutQuint(float start, float end, float value)
{
value--;
end -= start;
return end * (value * value * value * value * value + 1) + start;
}
public static float EaseInOutQuint(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1) return end * 0.5f * value * value * value * value * value + start;
value -= 2;
return end * 0.5f * (value * value * value * value * value + 2) + start;
}
public static float EaseInSine(float start, float end, float value)
{
end -= start;
return -end * Mathf.Cos(value * HALF_PI) + end + start;
}
public static float EaseOutSine(float start, float end, float value)
{
end -= start;
return end * Mathf.Sin(value * HALF_PI) + start;
}
public static float EaseInOutSine(float start, float end, float value)
{
end -= start;
return -end * 0.5f * (Mathf.Cos(PI * value) - 1) + start;
}
public static float EaseInExpo(float start, float end, float value)
{
end -= start;
return end * Mathf.Pow(2, 10 * (value - 1)) + start;
}
public static float EaseOutExpo(float start, float end, float value)
{
end -= start;
return end * (-Mathf.Pow(2, -10 * value) + 1) + start;
}
public static float EaseInOutExpo(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1) return end * 0.5f * Mathf.Pow(2, 10 * (value - 1)) + start;
value--;
return end * 0.5f * (-Mathf.Pow(2, -10 * value) + 2) + start;
}
public static float EaseInCirc(float start, float end, float value)
{
end -= start;
return -end * (Mathf.Sqrt(1 - value * value) - 1) + start;
}
public static float EaseOutCirc(float start, float end, float value)
{
value--;
end -= start;
return end * Mathf.Sqrt(1 - value * value) + start;
}
public static float EaseInOutCirc(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1) return -end * 0.5f * (Mathf.Sqrt(1 - value * value) - 1) + start;
value -= 2;
return end * 0.5f * (Mathf.Sqrt(1 - value * value) + 1) + start;
}
public static float EaseInBounce(float start, float end, float value)
{
end -= start;
float d = 1f;
return end - EaseOutBounce(0, end, d - value) + start;
}
public static float EaseOutBounce(float start, float end, float value)
{
value /= 1f;
end -= start;
if (value < (1 / 2.75f))
{
return end * (7.5625f * value * value) + start;
}
else if (value < (2 / 2.75f))
{
value -= (1.5f / 2.75f);
return end * (7.5625f * (value) * value + .75f) + start;
}
else if (value < (2.5 / 2.75))
{
value -= (2.25f / 2.75f);
return end * (7.5625f * (value) * value + .9375f) + start;
}
else
{
value -= (2.625f / 2.75f);
return end * (7.5625f * (value) * value + .984375f) + start;
}
}
public static float EaseInOutBounce(float start, float end, float value)
{
end -= start;
float d = 1f;
if (value < d * 0.5f) return EaseInBounce(0, end, value * 2) * 0.5f + start;
return EaseOutBounce(0, end, value * 2 - d) * 0.5f + end * 0.5f + start;
}
public static float EaseInBack(float start, float end, float value)
{
end -= start;
value /= 1;
float s = 1.70158f;
return end * (value) * value * ((s + 1) * value - s) + start;
}
public static float EaseOutBack(float start, float end, float value)
{
float s = 1.70158f;
end -= start;
value = (value) - 1;
return end * ((value) * value * ((s + 1) * value + s) + 1) + start;
}
public static float EaseInOutBack(float start, float end, float value)
{
float s = 1.70158f;
end -= start;
value /= .5f;
if ((value) < 1)
{
s *= (1.525f);
return end * 0.5f * (value * value * (((s) + 1) * value - s)) + start;
}
value -= 2;
s *= (1.525f);
return end * 0.5f * ((value) * value * (((s) + 1) * value + s) + 2) + start;
}
public static float EaseInElastic(float start, float end, float value)
{
end -= start;
float d = 1f;
float p = d * .3f;
float s;
float a = 0;
if (value == 0) return start;
if ((value /= d) == 1) return start + end;
if (a == 0f || a < Mathf.Abs(end))
{
a = end;
s = p / 4;
}
else
{
s = p / (2 * PI) * Mathf.Asin(end / a);
}
return -(a * Mathf.Pow(2, 10 * (value -= 1)) * Mathf.Sin((value * d - s) * (2 * PI) / p)) + start;
}
public static float EaseOutElastic(float start, float end, float value)
{
end -= start;
float d = 1f;
float p = d * .3f;
float s;
float a = 0;
if (value == 0) return start;
if ((value /= d) == 1) return start + end;
if (a == 0f || a < Mathf.Abs(end))
{
a = end;
s = p * 0.25f;
}
else
{
s = p / (2 * PI) * Mathf.Asin(end / a);
}
return (a * Mathf.Pow(2, -10 * value) * Mathf.Sin((value * d - s) * (2 * PI) / p) + end + start);
}
public static float EaseInOutElastic(float start, float end, float value)
{
end -= start;
float d = 1f;
float p = d * .3f;
float s;
float a = 0;
if (value == 0) return start;
if ((value /= d * 0.5f) == 2) return start + end;
if (a == 0f || a < Mathf.Abs(end))
{
a = end;
s = p / 4;
}
else
{
s = p / (2 * PI) * Mathf.Asin(end / a);
}
if (value < 1) return -0.5f * (a * Mathf.Pow(2, 10 * (value -= 1)) * Mathf.Sin((value * d - s) * (2 * PI) / p)) + start;
return a * Mathf.Pow(2, -10 * (value -= 1)) * Mathf.Sin((value * d - s) * (2 * PI) / p) * 0.5f + end + start;
}
//
// These are derived functions that the motor can use to get the speed at a specific time.
//
// The easing functions all work with a normalized time (0 to 1) and the returned value here
// reflects that. Values returned here should be divided by the actual time.
//
// TODO: These functions have not had the testing they deserve. If there is odd behavior around
// dash speeds then this would be the first place I'd look.
public static float LinearDerivative(float start, float end, float value)
{
return end - start;
}
public static float EaseInQuadDerivative(float start, float end, float value)
{
return 2f * (end - start) * value;
}
public static float EaseOutQuadDerivative(float start, float end, float value)
{
end -= start;
return -end * value - end * (value - 2);
}
public static float EaseInOutQuadDerivative(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1)
{
return end * value;
}
value--;
return end * (1 - value);
}
public static float EaseInCubicDerivative(float start, float end, float value)
{
return 3f * (end - start) * value * value;
}
public static float EaseOutCubicDerivative(float start, float end, float value)
{
value--;
end -= start;
return 3f * end * value * value;
}
public static float EaseInOutCubicDerivative(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1)
{
return (3f / 2f) * end * value * value;
}
value -= 2;
return (3f / 2f) * end * value * value;
}
public static float EaseInQuartDerivative(float start, float end, float value)
{
return 4f * (end - start) * value * value * value;
}
public static float EaseOutQuartDerivative(float start, float end, float value)
{
value--;
end -= start;
return -4f * end * value * value * value;
}
public static float EaseInOutQuartDerivative(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1)
{
return 2f * end * value * value * value;
}
value -= 2;
return -2f * end * value * value * value;
}
public static float EaseInQuintDerivative(float start, float end, float value)
{
return 5f * (end - start) * value * value * value * value;
}
public static float EaseOutQuintDerivative(float start, float end, float value)
{
value--;
end -= start;
return 5f * end * value * value * value * value;
}
public static float EaseInOutQuintDerivative(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1)
{
return (5f / 2f) * end * value * value * value * value;
}
value -= 2;
return (5f / 2f) * end * value * value * value * value;
}
public static float EaseInSineDerivative(float start, float end, float value)
{
return (end - start) * 0.5f * PI * Mathf.Sin(0.5f * PI * value);
}
public static float EaseOutSineDerivative(float start, float end, float value)
{
end -= start;
return HALF_PI * end * Mathf.Cos(value * HALF_PI);
}
public static float EaseInOutSineDerivative(float start, float end, float value)
{
end -= start;
return end * 0.5f * PI * Mathf.Sin(PI * value);
}
public static float EaseInExpoDerivative(float start, float end, float value)
{
return (10f * NATURAL_LOG_OF_2 * (end - start) * Mathf.Pow(2f, 10f * (value - 1)));
}
public static float EaseOutExpoDerivative(float start, float end, float value)
{
end -= start;
return 5f * NATURAL_LOG_OF_2 * end * Mathf.Pow(2f, 1f - 10f * value);
}
public static float EaseInOutExpoDerivative(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1)
{
return 5f * NATURAL_LOG_OF_2 * end * Mathf.Pow(2f, 10f * (value - 1));
}
value--;
return (5f * NATURAL_LOG_OF_2 * end) / (Mathf.Pow(2f, 10f * value));
}
public static float EaseInCircDerivative(float start, float end, float value)
{
return ((end - start) * value) / Mathf.Sqrt(1f - value * value);
}
public static float EaseOutCircDerivative(float start, float end, float value)
{
value--;
end -= start;
return (-end * value) / Mathf.Sqrt(1f - value * value);
}
public static float EaseInOutCircDerivative(float start, float end, float value)
{
value /= .5f;
end -= start;
if (value < 1)
{
return (end * value) / (2f * Mathf.Sqrt(1f - value * value));
}
value -= 2;
return (-end * value) / (2f * Mathf.Sqrt(1f - value * value));
}
public static float EaseInBounceDerivative(float start, float end, float value)
{
end -= start;
float d = 1f;
return EaseOutBounceDerivative(0, end, d - value);
}
public static float EaseOutBounceDerivative(float start, float end, float value)
{
value /= 1f;
end -= start;
if (value < (1 / 2.75f))
{
return 2f * end * 7.5625f * value;
}
else if (value < (2 / 2.75f))
{
value -= (1.5f / 2.75f);
return 2f * end * 7.5625f * value;
}
else if (value < (2.5 / 2.75))
{
value -= (2.25f / 2.75f);
return 2f * end * 7.5625f * value;
}
else
{
value -= (2.625f / 2.75f);
return 2f * end * 7.5625f * value;
}
}
public static float EaseInOutBounceDerivative(float start, float end, float value)
{
end -= start;
float d = 1f;
if (value < d * 0.5f)
{
return EaseInBounceDerivative(0, end, value * 2) * 0.5f;
}
else
{
return EaseOutBounceDerivative(0, end, value * 2 - d) * 0.5f;
}
}
public static float EaseInBackDerivative(float start, float end, float value)
{
float s = 1.70158f;
return 3f * (s + 1f) * (end - start) * value * value - 2f * s * (end - start) * value;
}
public static float EaseOutBackDerivative(float start, float end, float value)
{
float s = 1.70158f;
end -= start;
value = (value) - 1;
return end * ((s + 1f) * value * value + 2f * value * ((s + 1f) * value + s));
}
public static float EaseInOutBackDerivative(float start, float end, float value)
{
float s = 1.70158f;
end -= start;
value /= .5f;
if ((value) < 1)
{
s *= (1.525f);
return 0.5f * end * (s + 1) * value * value + end * value * ((s + 1f) * value - s);
}
value -= 2;
s *= (1.525f);
return 0.5f * end * ((s + 1) * value * value + 2f * value * ((s + 1f) * value + s));
}
public static float EaseInElasticDerivative(float start, float end, float value)
{
return EaseOutElasticDerivative(start, end, 1f - value);
}
public static float EaseOutElasticDerivative(float start, float end, float value)
{
end -= start;
float d = 1f;
float p = d * .3f;
float s;
float a = 0;
if (a == 0f || a < Mathf.Abs(end))
{
a = end;
s = p * 0.25f;
}
else
{
s = p / (2 * PI) * Mathf.Asin(end / a);
}
return (a * PI * d * Mathf.Pow(2f, 1f - 10f * value) *
Mathf.Cos((2f * PI * (d * value - s)) / p)) / p - 5f * NATURAL_LOG_OF_2 * a *
Mathf.Pow(2f, 1f - 10f * value) * Mathf.Sin((2f * PI * (d * value - s)) / p);
}
public static float EaseInOutElasticDerivative(float start, float end, float value)
{
end -= start;
float d = 1f;
float p = d * .3f;
float s;
float a = 0;
if (a == 0f || a < Mathf.Abs(end))
{
a = end;
s = p / 4;
}
else
{
s = p / (2 * PI) * Mathf.Asin(end / a);
}
if (value < 1)
{
value -= 1;
return -5f * NATURAL_LOG_OF_2 * a * Mathf.Pow(2f, 10f * value) * Mathf.Sin(2 * PI * (d * value - 2f) / p) -
a * PI * d * Mathf.Pow(2f, 10f * value) * Mathf.Cos(2 * PI * (d * value - s) / p) / p;
}
value -= 1;
return a * PI * d * Mathf.Cos(2f * PI * (d * value - s) / p) / (p * Mathf.Pow(2f, 10f * value)) -
5f * NATURAL_LOG_OF_2 * a * Mathf.Sin(2f * PI * (d * value - s) / p) / (Mathf.Pow(2f, 10f * value));
}
public static float SpringDerivative(float start, float end, float value)
{
value = Mathf.Clamp01(value);
end -= start;
// TODO: And it's a little bit wrong
return end * (6f * (1f - value) / 5f + 1f) * (-2.2f * Mathf.Pow(1f - value, 1.2f) *
Mathf.Sin(PI * value * (2.5f * value * value * value + 0.2f)) + Mathf.Pow(1f - value, 2.2f) *
(PI * (2.5f * value * value * value + 0.2f) + 7.5f * PI * value * value * value) *
Mathf.Cos(PI * value * (2.5f * value * value * value + 0.2f)) + 1f) -
6f * end * (Mathf.Pow(1 - value, 2.2f) * Mathf.Sin(PI * value * (2.5f * value * value * value + 0.2f)) + value
/ 5f);
}
public static float Punch(float amplitude, float value)
{
float s = 9;
if (value == 0)
{
return 0;
}
if (value == 1)
{
return 0;
}
float period = 1 * 0.3f;
s = period / (2 * PI) * Mathf.Asin(0);
return (amplitude * Mathf.Pow(2, -10 * value) * Mathf.Sin((value * 1 - s) * (2 * PI) / period));
}
public static float Clerp(float start, float end, float value)
{
float min = 0.0f;
float max = 360.0f;
float half = Mathf.Abs((max - min) / 2.0f);
float retval = 0.0f;
float diff = 0.0f;
if ((end - start) < -half)
{
diff = ((max - start) + end) * value;
retval = start + diff;
}
else if ((end - start) > half)
{
diff = -((max - end) + start) * value;
retval = start + diff;
}
else retval = start + (end - start) * value;
return retval;
}
public delegate float Function(float start, float end, float value);
/// <summary>
/// Returns the function associated to the easingFunction enum. This value returned should be cached as it allocates memory
/// to return.
/// </summary>
/// <param name="easingFunction">The enum associated with the easing function.</param>
/// <returns>The easing function</returns>
public static Function GetEasingFunction(EEase easingFunction)
{
switch (easingFunction)
{
case EEase.Linear: return Linear;
case EEase.Spring: return Spring;
case EEase.InBack: return EaseInBack;
case EEase.OutBack: return EaseOutBack;
case EEase.InOutBack: return EaseInOutBack;
case EEase.InQuad: return EaseInQuad;
case EEase.OutQuad: return EaseOutQuad;
case EEase.InOutQuad: return EaseInOutQuad;
case EEase.InCubic: return EaseInCubic;
case EEase.OutCubic: return EaseOutCubic;
case EEase.InOutCubic: return EaseInOutCubic;
case EEase.InQuart: return EaseInQuart;
case EEase.OutQuart: return EaseOutQuart;
case EEase.InOutQuart: return EaseInOutQuart;
case EEase.InQuint: return EaseInQuint;
case EEase.OutQuint: return EaseOutQuint;
case EEase.InOutQuint: return EaseInOutQuint;
case EEase.InSine: return EaseInSine;
case EEase.OutSine: return EaseOutSine;
case EEase.InOutSine: return EaseInOutSine;
case EEase.InExpo: return EaseInExpo;
case EEase.OutExpo: return EaseOutExpo;
case EEase.InOutExpo: return EaseInOutExpo;
case EEase.InCirc: return EaseInCirc;
case EEase.OutCirc: return EaseOutCirc;
case EEase.InOutCirc: return EaseInOutCirc;
case EEase.InBounce: return EaseInBounce;
case EEase.OutBounce: return EaseOutBounce;
case EEase.InOutBounce: return EaseInOutBounce;
case EEase.InElastic: return EaseInElastic;
case EEase.OutElastic: return EaseOutElastic;
case EEase.InOutElastic: return EaseInOutElastic;
default: return null;
}
}
/// <summary>
/// Gets the derivative function of the appropriate easing function. If you use an easing function for position then this
/// function can get you the speed at a given time (normalized).
/// </summary>
/// <param name="easingFunction"></param>
/// <returns>The derivative function</returns>
public static Function GetEasingFunctionDerivative(EEase easingFunction)
{
switch (easingFunction)
{
case EEase.Linear: return LinearDerivative;
case EEase.Spring: return SpringDerivative;
case EEase.InBack: return EaseInBackDerivative;
case EEase.OutBack: return EaseOutBackDerivative;
case EEase.InOutBack: return EaseInOutBackDerivative;
case EEase.InQuad: return EaseInQuadDerivative;
case EEase.OutQuad: return EaseOutQuadDerivative;
case EEase.InOutQuad: return EaseInOutQuadDerivative;
case EEase.InCubic: return EaseInCubicDerivative;
case EEase.OutCubic: return EaseOutCubicDerivative;
case EEase.InOutCubic: return EaseInOutCubicDerivative;
case EEase.InQuart: return EaseInQuartDerivative;
case EEase.OutQuart: return EaseOutQuartDerivative;
case EEase.InOutQuart: return EaseInOutQuartDerivative;
case EEase.InQuint: return EaseInQuintDerivative;
case EEase.OutQuint: return EaseOutQuintDerivative;
case EEase.InOutQuint: return EaseInOutQuintDerivative;
case EEase.InSine: return EaseInSineDerivative;
case EEase.OutSine: return EaseOutSineDerivative;
case EEase.InOutSine: return EaseInOutSineDerivative;
case EEase.InExpo: return EaseInExpoDerivative;
case EEase.OutExpo: return EaseOutExpoDerivative;
case EEase.InOutExpo: return EaseInOutExpoDerivative;
case EEase.InCirc: return EaseInCircDerivative;
case EEase.OutCirc: return EaseOutCircDerivative;
case EEase.InOutCirc: return EaseInOutCircDerivative;
case EEase.InBounce: return EaseInBounceDerivative;
case EEase.OutBounce: return EaseOutBounceDerivative;
case EEase.InOutBounce: return EaseInOutBounceDerivative;
case EEase.InElastic: return EaseInElasticDerivative;
case EEase.OutElastic: return EaseOutElasticDerivative;
case EEase.InOutElastic: return EaseInOutElasticDerivative;
default: return null;
}
}
}
}
@aprius
Copy link
Author

aprius commented Oct 13, 2019

using System;
#if UNITY
using UnityEngine;
using Math = UnityEngine.Mathf;
#endif

static public class Easings
{
	/// <summary>
	/// Constant Pi.
	/// </summary>
	private const float PI = Math.PI; 
	
	/// <summary>
	/// Constant Pi / 2.
	/// </summary>
	private const float HALFPI = Math.PI / 2.0f; 
	
	/// <summary>
	/// Easing Functions enumeration
	/// </summary>
	public enum Functions
	{
		Linear,
		QuadraticEaseIn,
		QuadraticEaseOut,
		QuadraticEaseInOut,
		CubicEaseIn,
		CubicEaseOut,
		CubicEaseInOut,
		QuarticEaseIn,
		QuarticEaseOut,
		QuarticEaseInOut,
		QuinticEaseIn,
		QuinticEaseOut,
		QuinticEaseInOut,
		SineEaseIn,
		SineEaseOut,
		SineEaseInOut,
		CircularEaseIn,
		CircularEaseOut,
		CircularEaseInOut,
		ExponentialEaseIn,
		ExponentialEaseOut,
		ExponentialEaseInOut,
		ElasticEaseIn,
		ElasticEaseOut,
		ElasticEaseInOut,
		BackEaseIn,
		BackEaseOut,
		BackEaseInOut,
		BounceEaseIn,
		BounceEaseOut,
		BounceEaseInOut
	}
	
	/// <summary>
	/// Interpolate using the specified function.
	/// </summary>
	static public float Interpolate(float p, Functions function)
	{
		switch(function)
		{
			default:
			case Functions.Linear: 					return Linear(p);
			case Functions.QuadraticEaseOut:		return QuadraticEaseOut(p);
			case Functions.QuadraticEaseIn:			return QuadraticEaseIn(p);
			case Functions.QuadraticEaseInOut:		return QuadraticEaseInOut(p);
			case Functions.CubicEaseIn:				return CubicEaseIn(p);
			case Functions.CubicEaseOut:			return CubicEaseOut(p);
			case Functions.CubicEaseInOut:			return CubicEaseInOut(p);
			case Functions.QuarticEaseIn:			return QuarticEaseIn(p);
			case Functions.QuarticEaseOut:			return QuarticEaseOut(p);
			case Functions.QuarticEaseInOut:		return QuarticEaseInOut(p);
			case Functions.QuinticEaseIn:			return QuinticEaseIn(p);
			case Functions.QuinticEaseOut:			return QuinticEaseOut(p);
			case Functions.QuinticEaseInOut:		return QuinticEaseInOut(p);
			case Functions.SineEaseIn:				return SineEaseIn(p);
			case Functions.SineEaseOut:				return SineEaseOut(p);
			case Functions.SineEaseInOut:			return SineEaseInOut(p);
			case Functions.CircularEaseIn:			return CircularEaseIn(p);
			case Functions.CircularEaseOut:			return CircularEaseOut(p);
			case Functions.CircularEaseInOut:		return CircularEaseInOut(p);
			case Functions.ExponentialEaseIn:		return ExponentialEaseIn(p);
			case Functions.ExponentialEaseOut:		return ExponentialEaseOut(p);
			case Functions.ExponentialEaseInOut:	return ExponentialEaseInOut(p);
			case Functions.ElasticEaseIn:			return ElasticEaseIn(p);
			case Functions.ElasticEaseOut:			return ElasticEaseOut(p);
			case Functions.ElasticEaseInOut:		return ElasticEaseInOut(p);
			case Functions.BackEaseIn:				return BackEaseIn(p);
			case Functions.BackEaseOut:				return BackEaseOut(p);
			case Functions.BackEaseInOut:			return BackEaseInOut(p);
			case Functions.BounceEaseIn:			return BounceEaseIn(p);
			case Functions.BounceEaseOut:			return BounceEaseOut(p);
			case Functions.BounceEaseInOut:			return BounceEaseInOut(p);
		}
	}
	
	/// <summary>
	/// Modeled after the line y = x
	/// </summary>
	static public float Linear(float p)
	{
		return p;
	}
	
	/// <summary>
	/// Modeled after the parabola y = x^2
	/// </summary>
	static public float QuadraticEaseIn(float p)
	{
		return p * p;
	}
	
	/// <summary>
	/// Modeled after the parabola y = -x^2 + 2x
	/// </summary>
	static public float QuadraticEaseOut(float p)
	{
		return -(p * (p - 2));
	}
	
	/// <summary>
	/// Modeled after the piecewise quadratic
	/// y = (1/2)((2x)^2)             ; [0, 0.5)
	/// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
	/// </summary>
	static public float QuadraticEaseInOut(float p)
	{
		if(p < 0.5f)
		{
			return 2 * p * p;
		}
		else
		{
			return (-2 * p * p) + (4 * p) - 1;
		}
	}
	
	/// <summary>
	/// Modeled after the cubic y = x^3
	/// </summary>
	static public float CubicEaseIn(float p)
	{
		return p * p * p;
	}
	
	/// <summary>
	/// Modeled after the cubic y = (x - 1)^3 + 1
	/// </summary>
	static public float CubicEaseOut(float p)
	{
		float f = (p - 1);
		return f * f * f + 1;
	}
	
	/// <summary>	
	/// Modeled after the piecewise cubic
	/// y = (1/2)((2x)^3)       ; [0, 0.5)
	/// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
	/// </summary>
	static public float CubicEaseInOut(float p)
	{
		if(p < 0.5f)
		{
			return 4 * p * p * p;
		}
		else
		{
			float f = ((2 * p) - 2);
			return 0.5f * f * f * f + 1;
		}
	}
	
	/// <summary>
	/// Modeled after the quartic x^4
	/// </summary>
	static public float QuarticEaseIn(float p)
	{
		return p * p * p * p;
	}
	
	/// <summary>
	/// Modeled after the quartic y = 1 - (x - 1)^4
	/// </summary>
	static public float QuarticEaseOut(float p)
	{
		float f = (p - 1);
		return f * f * f * (1 - p) + 1;
	}
	
	/// <summary>
	// Modeled after the piecewise quartic
	// y = (1/2)((2x)^4)        ; [0, 0.5)
	// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
	/// </summary>
	static public float QuarticEaseInOut(float p) 
	{
		if(p < 0.5f)
		{
			return 8 * p * p * p * p;
		}
		else
		{
			float f = (p - 1);
			return -8 * f * f * f * f + 1;
		}
	}
	
	/// <summary>
	/// Modeled after the quintic y = x^5
	/// </summary>
	static public float QuinticEaseIn(float p) 
	{
		return p * p * p * p * p;
	}
	
	/// <summary>
	/// Modeled after the quintic y = (x - 1)^5 + 1
	/// </summary>
	static public float QuinticEaseOut(float p) 
	{
		float f = (p - 1);
		return f * f * f * f * f + 1;
	}
	
	/// <summary>
	/// Modeled after the piecewise quintic
	/// y = (1/2)((2x)^5)       ; [0, 0.5)
	/// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
	/// </summary>
	static public float QuinticEaseInOut(float p) 
	{
		if(p < 0.5f)
		{
			return 16 * p * p * p * p * p;
		}
		else
		{
			float f = ((2 * p) - 2);
			return 0.5f * f * f * f * f * f + 1;
		}
	}
	
	/// <summary>
	/// Modeled after quarter-cycle of sine wave
	/// </summary>
	static public float SineEaseIn(float p)
	{
		return Math.Sin((p - 1) * HALFPI) + 1;
	}
	
	/// <summary>
	/// Modeled after quarter-cycle of sine wave (different phase)
	/// </summary>
	static public float SineEaseOut(float p)
	{
		return Math.Sin(p * HALFPI);
	}
	
	/// <summary>
	/// Modeled after half sine wave
	/// </summary>
	static public float SineEaseInOut(float p)
	{
		return 0.5f * (1 - Math.Cos(p * PI));
	}
	
	/// <summary>
	/// Modeled after shifted quadrant IV of unit circle
	/// </summary>
	static public float CircularEaseIn(float p)
	{
		return 1 - Math.Sqrt(1 - (p * p));
	}
	
	/// <summary>
	/// Modeled after shifted quadrant II of unit circle
	/// </summary>
	static public float CircularEaseOut(float p)
	{
		return Math.Sqrt((2 - p) * p);
	}
	
	/// <summary>	
	/// Modeled after the piecewise circular function
	/// y = (1/2)(1 - Math.Sqrt(1 - 4x^2))           ; [0, 0.5)
	/// y = (1/2)(Math.Sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
	/// </summary>
	static public float CircularEaseInOut(float p)
	{
		if(p < 0.5f)
		{
			return 0.5f * (1 - Math.Sqrt(1 - 4 * (p * p)));
		}
		else
		{
			return 0.5f * (Math.Sqrt(-((2 * p) - 3) * ((2 * p) - 1)) + 1);
		}
	}
	
	/// <summary>
	/// Modeled after the exponential function y = 2^(10(x - 1))
	/// </summary>
	static public float ExponentialEaseIn(float p)
	{
		return (p == 0.0f) ? p : Math.Pow(2, 10 * (p - 1));
	}
	
	/// <summary>
	/// Modeled after the exponential function y = -2^(-10x) + 1
	/// </summary>
	static public float ExponentialEaseOut(float p)
	{
		return (p == 1.0f) ? p : 1 - Math.Pow(2, -10 * p);
	}
	
	/// <summary>
	/// Modeled after the piecewise exponential
	/// y = (1/2)2^(10(2x - 1))         ; [0,0.5)
	/// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
	/// </summary>
	static public float ExponentialEaseInOut(float p)
	{
		if(p == 0.0 || p == 1.0) return p;
		
		if(p < 0.5f)
		{
			return 0.5f * Math.Pow(2, (20 * p) - 10);
		}
		else
		{
			return -0.5f * Math.Pow(2, (-20 * p) + 10) + 1;
		}
	}
	
	/// <summary>
	/// Modeled after the damped sine wave y = sin(13pi/2*x)*Math.Pow(2, 10 * (x - 1))
	/// </summary>
	static public float ElasticEaseIn(float p)
	{
		return Math.Sin(13 * HALFPI * p) * Math.Pow(2, 10 * (p - 1));
	}
	
	/// <summary>
	/// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*Math.Pow(2, -10x) + 1
	/// </summary>
	static public float ElasticEaseOut(float p)
	{
		return Math.Sin(-13 * HALFPI * (p + 1)) * Math.Pow(2, -10 * p) + 1;
	}
	
	/// <summary>
	/// Modeled after the piecewise exponentially-damped sine wave:
	/// y = (1/2)*sin(13pi/2*(2*x))*Math.Pow(2, 10 * ((2*x) - 1))      ; [0,0.5)
	/// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*Math.Pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
	/// </summary>
	static public float ElasticEaseInOut(float p)
	{
		if(p < 0.5f)
		{
			return 0.5f * Math.Sin(13 * HALFPI * (2 * p)) * Math.Pow(2, 10 * ((2 * p) - 1));
		}
		else
		{
			return 0.5f * (Math.Sin(-13 * HALFPI * ((2 * p - 1) + 1)) * Math.Pow(2, -10 * (2 * p - 1)) + 2);
		}
	}
	
	/// <summary>
	/// Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
	/// </summary>
	static public float BackEaseIn(float p)
	{
		return p * p * p - p * Math.Sin(p * PI);
	}
	
	/// <summary>
	/// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
	/// </summary>	
	static public float BackEaseOut(float p)
	{
		float f = (1 - p);
		return 1 - (f * f * f - f * Math.Sin(f * PI));
	}
	
	/// <summary>
	/// Modeled after the piecewise overshooting cubic function:
	/// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi))           ; [0, 0.5)
	/// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
	/// </summary>
	static public float BackEaseInOut(float p)
	{
		if(p < 0.5f)
		{
			float f = 2 * p;
			return 0.5f * (f * f * f - f * Math.Sin(f * PI));
		}
		else
		{
			float f = (1 - (2*p - 1));
			return 0.5f * (1 - (f * f * f - f * Math.Sin(f * PI))) + 0.5f;
		}
	}
	
	/// <summary>
	/// </summary>
	static public float BounceEaseIn(float p)
	{
		return 1 - BounceEaseOut(1 - p);
	}
	
	/// <summary>
	/// </summary>
	static public float BounceEaseOut(float p)
	{
		if(p < 4/11.0f)
		{
			return (121 * p * p)/16.0f;
		}
		else if(p < 8/11.0f)
		{
			return (363/40.0f * p * p) - (99/10.0f * p) + 17/5.0f;
		}
		else if(p < 9/10.0f)
		{
			return (4356/361.0f * p * p) - (35442/1805.0f * p) + 16061/1805.0f;
		}
		else
		{
			return (54/5.0f * p * p) - (513/25.0f * p) + 268/25.0f;
		}
	}
	
	/// <summary>
	/// </summary>
	static public float BounceEaseInOut(float p)
	{
		if(p < 0.5f)
		{
			return 0.5f * BounceEaseIn(p*2);
		}
		else
		{
			return 0.5f * BounceEaseOut(p * 2 - 1) + 0.5f;
		}
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment