expo + circ + OutIn refactor

master
Evan Hemsley 2019-10-30 18:17:02 -07:00
parent 171538122f
commit a26aa29721
2 changed files with 405 additions and 104 deletions

View File

@ -20,9 +20,43 @@ namespace MoonTools.Core.Easing
private static float NormalizedTime(Func<float, float, float, float, float> easingFunction, float t) => easingFunction(t, 0, 1, 1);
private static float TimeRange(Func<float, float> easingFunction, float time, float start, float end) => start + (end - start) * easingFunction((time - start) / (end - start));
private static float OutIn(Func<float, float, float, float, float> outFunc,
Func<float, float, float, float, float> inFunc,
float t,
float b,
float c,
float d)
{
if (t < d / 2)
{
return outFunc(t * 2, b, c / 2, d);
}
else
{
return inFunc((t * 2) - d, b + c / 2, c / 2, d);
}
}
private static double NormalizedTime(Func<double, double, double, double, double> easingFunction, double t) => easingFunction(t, 0, 1, 1);
private static double TimeRange(Func<double, double> easingFunction, double time, double start, double end) => start + (end - start) * easingFunction((time - start) / (end - start));
private static double OutIn(Func<double, double, double, double, double> outFunc,
Func<double, double, double, double, double> inFunc,
double t,
double b,
double c,
double d)
{
if (t < d / 2)
{
return outFunc(t * 2, b, c / 2, d);
}
else
{
return inFunc((t * 2) - d, b + c / 2, c / 2, d);
}
}
/********* EASING FUNCTIONS ********/
// LINEAR
@ -129,35 +163,11 @@ namespace MoonTools.Core.Easing
public static float OutInQuad(float t) => NormalizedTime(OutInQuad, t);
public static float OutInQuad(float time, float start, float end) => TimeRange(OutInQuad, time, start, end);
public static float OutInQuad(float t, float b, float c, float d)
{
CheckTime(t, d);
if (t < d / 2)
{
return OutQuad(t * 2, b, c / 2, d);
}
else
{
return InQuad((t * 2) - d, b + c / 2, c / 2, d);
}
}
public static float OutInQuad(float t, float b, float c, float d) => OutIn(OutQuad, InQuad, t, b, c, d);
public static double OutInQuad(double t) => NormalizedTime(OutInQuad, t);
public static double OutInQuad(double time, double start, double end) => TimeRange(OutInQuad, time, start, end);
public static double OutInQuad(double t, double b, double c, double d)
{
CheckTime(t, d);
if (t < d / 2)
{
return OutQuad(t * 2, b, c / 2, d);
}
else
{
return InQuad((t * 2) - d, b + c / 2, c / 2, d);
}
}
public static double OutInQuad(double t, double b, double c, double d) => OutIn(OutQuad, InQuad, t, b, c, d);
// IN CUBIC
@ -247,33 +257,11 @@ namespace MoonTools.Core.Easing
public static float OutInCubic(float t) => NormalizedTime(OutInCubic, t);
public static float OutInCubic(float time, float start, float end) => TimeRange(OutInCubic, time, start, end);
public static float OutInCubic(float t, float b, float c, float d)
{
if (t < d / 2)
{
return OutCubic(t * 2, b, c / 2, d);
}
else
{
return InCubic((t * 2) - d, b + c / 2, c / 2, d);
}
}
public static float OutInCubic(float t, float b, float c, float d) => OutIn(OutCubic, InCubic, t, b, c, d);
public static double OutInCubic(double t) => NormalizedTime(OutInCubic, t);
public static double OutInCubic(double time, double start, double end) => TimeRange(OutInCubic, time, start, end);
public static double OutInCubic(double t, double b, double c, double d)
{
if (t < d / 2)
{
return OutCubic(t * 2, b, c / 2, d);
}
else
{
return InCubic((t * 2) - d, b + c / 2, c / 2, d);
}
}
public static double OutInCubic(double t, double b, double c, double d) => OutIn(OutCubic, InCubic, t, b, c, d);
// IN QUARTIC
@ -361,33 +349,11 @@ namespace MoonTools.Core.Easing
public static float OutInQuart(float t) => NormalizedTime(OutInQuart, t);
public static float OutInQuart(float time, float start, float end) => TimeRange(OutInQuart, time, start, end);
public static float OutInQuart(float t, float b, float c, float d)
{
if (t < d / 2)
{
return OutQuart(t * 2, b, c / 2, d);
}
else
{
return InQuart((t * 2) - d, b + c / 2, c / 2, d);
}
}
public static float OutInQuart(float t, float b, float c, float d) => OutIn(OutQuart, InQuart, t, b, c, d);
public static double OutInQuart(double t) => NormalizedTime(OutInQuart, t);
public static double OutInQuart(double time, double start, double end) => TimeRange(OutInQuart, time, start, end);
public static double OutInQuart(double t, double b, double c, double d)
{
if (t < d / 2)
{
return OutQuart(t * 2, b, c / 2, d);
}
else
{
return InQuart((t * 2) - d, b + c / 2, c / 2, d);
}
}
public static double OutInQuart(double t, double b, double c, double d) => OutIn(OutQuart, InQuart, t, b, c, d);
// IN QUINTIC
@ -475,35 +441,11 @@ namespace MoonTools.Core.Easing
public static float OutInQuint(float t) => NormalizedTime(OutInQuint, t);
public static float OutInQuint(float time, float start, float end) => TimeRange(OutInQuint, time, start, end);
public static float OutInQuint(float t, float b, float c, float d)
{
CheckTime(t, d);
if (t < d / 2)
{
return OutQuint(t * 2, b, c / 2, d);
}
else
{
return InQuint((t * 2) - d, b + c / 2, c / 2, d);
}
}
public static float OutInQuint(float t, float b, float c, float d) => OutIn(OutQuint, InQuint, t, b, c, d);
public static double OutInQuint(double t) => NormalizedTime(OutInQuint, t);
public static double OutInQuint(double time, double start, double end) => TimeRange(OutInQuint, time, start, end);
public static double OutInQuint(double t, double b, double c, double d)
{
CheckTime(t, d);
if (t < d / 2)
{
return OutQuint(t * 2, b, c / 2, d);
}
else
{
return InQuint((t * 2) - d, b + c / 2, c / 2, d);
}
}
public static double OutInQuint(double t, double b, double c, double d) => OutIn(OutQuint, InQuint, t, b, c, d);
// note: no float implementations because trig functions are double precision
@ -544,17 +486,120 @@ namespace MoonTools.Core.Easing
public static double OutInSine(double t) => NormalizedTime(OutInSine, t);
public static double OutInSine(double time, double start, double end) => TimeRange(OutInSine, time, start, end);
public static double OutInSine(double t, double b, double c, double d) => OutIn(OutSine, InSine, t, b, c, d);
public static double OutInSine(double t, double b, double c, double d)
// IN EXPONENTIAL
public static double InExpo(double t) => NormalizedTime(InExpo, t);
public static double InExpo(double time, double start, double end) => TimeRange(InExpo, time, start, end);
public static double InExpo(double t, double b, double c, double d)
{
if (t < d / 2)
CheckTime(t, d);
if (t == 0)
{
return OutSine(t * 2, b, c / 2, d);
return b;
}
else
{
return InSine((t * 2) - d, b + c / 2, c / 2, d);
return c * Math.Pow(2, 10 * ((t / d) - 1)) + b - c * 0.001;
}
}
// OUT EXPONENTIAL
public static double OutExpo(double t) => NormalizedTime(OutExpo, t);
public static double OutExpo(double time, double start, double end) => TimeRange(OutExpo, time, start, end);
public static double OutExpo(double t, double b, double c, double d)
{
CheckTime(t, d);
if (t == d)
{
return b + c;
}
else
{
return c * 1.001 * (-Math.Pow(2, -10 * t / d) + 1) + b;
}
}
// IN OUT EXPONENTIAL
public static double InOutExpo(double t) => NormalizedTime(InOutExpo, t);
public static double InOutExpo(double time, double start, double end) => TimeRange(InOutExpo, time, start, end);
public static double InOutExpo(double t, double b, double c, double d)
{
CheckTime(t, d);
if (t == 0) { return b; }
if (t == d) { return b + c; }
t = t / d * 2;
if (t < 1)
{
return c / 2 * Math.Pow(2, 10 * (t - 1)) + b - c * 0.0005;
}
else
{
t = t - 1;
return c / 2 * 1.0005 * (-Math.Pow(2, -10 * t) + 2) + b;
}
}
// OUT IN EXPONENTIAL
public static double OutInExpo(double t) => NormalizedTime(OutInExpo, t);
public static double OutInExpo(double time, double start, double end) => TimeRange(OutInExpo, time, start, end);
public static double OutInExpo(double t, double b, double c, double d) => OutIn(OutExpo, InExpo, t, b, c, d);
// IN CIRCULAR
public static double InCirc(double t) => NormalizedTime(InCirc, t);
public static double InCirc(double time, double start, double end) => TimeRange(InCirc, time, start, end);
public static double InCirc(double t, double b, double c, double d)
{
CheckTime(t, d);
t = t / d;
return -c * (Math.Sqrt(1 - (t * t)) - 1) + b;
}
// OUT CIRCULAR
public static double OutCirc(double t) => NormalizedTime(OutCirc, t);
public static double OutCirc(double time, double start, double end) => TimeRange(OutCirc, time, start, end);
public static double OutCirc(double t, double b, double c, double d)
{
CheckTime(t, d);
t = t / d - 1;
return c * Math.Sqrt(1 - (t * t)) + b;
}
// IN OUT CIRCULAR
public static double InOutCirc(double t) => NormalizedTime(InOutCirc, t);
public static double InOutCirc(double time, double start, double end) => TimeRange(InOutCirc, time, start, end);
public static double InOutCirc(double t, double b, double c, double d)
{
CheckTime(t, d);
t = t / d * 2;
if (t < 1)
{
return -c / 2 * (Math.Sqrt(1 - (t * t)) - 1) + b;
}
else
{
t = t - 2;
return c / 2 * (Math.Sqrt(1 - (t * t)) + 1) + b;
}
}
// OUT IN CIRCULAR
public static double OutInCirc(double t) => NormalizedTime(OutInCirc, t);
public static double OutInCirc(double time, double start, double end) => TimeRange(OutInCirc, time, start, end);
public static double OutInCirc(double t, double b, double c, double d) => OutIn(OutCirc, InCirc, t, b, c, d);
}
}

View File

@ -337,6 +337,150 @@ namespace Test
invalidTime = () => Easing.OutSine(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
[Test]
public void InExpo()
{
Easing.InExpo(0.25f).Should().BeApproximately(0.0045242717280199f, 0.0001f);
Easing.InExpo(0.5f).Should().BeApproximately(0.03025f, 0.0001f);
Easing.InExpo(0.75f).Should().BeApproximately(0.17577669529664f, 0.0001f);
Easing.InExpo(3f, 2, 6).Should().BeApproximately(2.0180970869121f, 0.0001f);
Easing.InExpo(4f, 2, 6).Should().BeApproximately(2.121f, 0.0001f);
Easing.InExpo(5f, 2, 6).Should().BeApproximately(2.703106781187f, 0.0001f);
Action invalidTime = () => Easing.InExpo(1.5f);
invalidTime.Should().Throw<ArgumentException>();
invalidTime = () => Easing.InExpo(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
[Test]
public void OutExpo()
{
Easing.OutExpo(0.25f).Should().BeApproximately(0.82404652800807f, 0.0001f);
Easing.OutExpo(0.5f).Should().BeApproximately(0.96971875f, 0.0001f);
Easing.OutExpo(0.75f).Should().BeApproximately(0.99547020400025f, 0.0001f);
Easing.OutExpo(3f, 2, 6).Should().BeApproximately(5.29618611203f, 0.0001f);
Easing.OutExpo(4f, 2, 6).Should().BeApproximately(5.878875f, 0.0001f);
Easing.OutExpo(5f, 2, 6).Should().BeApproximately(5.981880816f, 0.0001f);
Action invalidTime = () => Easing.OutExpo(1.5f);
invalidTime.Should().Throw<ArgumentException>();
invalidTime = () => Easing.OutExpo(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
[Test]
public void InOutExpo()
{
Easing.InOutExpo(0.25f).Should().BeApproximately(0.015125f, 0.001f);
Easing.InOutExpo(0.5f).Should().BeApproximately(0.5f, 0.001f);
Easing.InOutExpo(0.75f).Should().BeApproximately(0.9848671875f, 0.001f);
Easing.InOutExpo(3f, 2, 6).Should().BeApproximately(2.0605f, 0.001f);
Easing.InOutExpo(4f, 2, 6).Should().BeApproximately(4f, 0.001f);
Easing.InOutExpo(5f, 2, 6).Should().BeApproximately(5.93946875f, 0.001f);
Action invalidTime = () => Easing.InOutExpo(1.5f);
invalidTime.Should().Throw<ArgumentException>();
invalidTime = () => Easing.InOutExpo(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
[Test]
public void OutInExpo()
{
Easing.OutInExpo(0.25f).Should().BeApproximately(0.484859375f, 0.001f);
Easing.OutInExpo(0.5f).Should().BeApproximately(0.5f, 0.001f);
Easing.OutInExpo(0.75f).Should().BeApproximately(0.515125f, 0.001f);
Easing.OutInExpo(3f, 2, 6).Should().BeApproximately(3.9394375f, 0.001f);
Easing.OutInExpo(4f, 2, 6).Should().BeApproximately(4f, 0.001f);
Easing.OutInExpo(5f, 2, 6).Should().BeApproximately(4.0605f, 0.001f);
Action invalidTime = () => Easing.OutInExpo(1.5f);
invalidTime.Should().Throw<ArgumentException>();
invalidTime = () => Easing.OutInExpo(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
[Test]
public void InCircular()
{
Easing.InCirc(0.25f).Should().BeApproximately(0.031754163448146f, 0.001f);
Easing.InCirc(0.5f).Should().BeApproximately(0.13397459621556f, 0.001f);
Easing.InCirc(0.75f).Should().BeApproximately(0.33856217223385f, 0.001f);
Easing.InCirc(3f, 2, 6).Should().BeApproximately(2.127016653793f, 0.001f);
Easing.InCirc(4f, 2, 6).Should().BeApproximately(2.535898384862f, 0.001f);
Easing.InCirc(5f, 2, 6).Should().BeApproximately(3.35424868894f, 0.001f);
Action invalidTime = () => Easing.InCirc(1.5f);
invalidTime.Should().Throw<ArgumentException>();
invalidTime = () => Easing.InCirc(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
[Test]
public void OutCircular()
{
Easing.OutCirc(0.25f).Should().BeApproximately(0.66143782776615f, 0.001f);
Easing.OutCirc(0.5f).Should().BeApproximately(0.86602540378444f, 0.001f);
Easing.OutCirc(0.75f).Should().BeApproximately(0.96824583655185f, 0.001f);
Easing.OutCirc(3f, 2, 6).Should().BeApproximately(4.64575131107f, 0.001f);
Easing.OutCirc(4f, 2, 6).Should().BeApproximately(5.46410161514f, 0.001f);
Easing.OutCirc(5f, 2, 6).Should().BeApproximately(5.87298334621f, 0.001f);
Action invalidTime = () => Easing.OutCirc(1.5f);
invalidTime.Should().Throw<ArgumentException>();
invalidTime = () => Easing.OutCirc(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
[Test]
public void InOutCircular()
{
Easing.InOutCirc(0.25f).Should().BeApproximately(0.066987298107781f, 0.001f);
Easing.InOutCirc(0.5f).Should().BeApproximately(0.5f, 0.001f);
Easing.InOutCirc(0.75f).Should().BeApproximately(0.93301270189222f, 0.001f);
Easing.InOutCirc(3f, 2, 6).Should().BeApproximately(2.267949192431f, 0.001f);
Easing.InOutCirc(4f, 2, 6).Should().BeApproximately(4f, 0.001f);
Easing.InOutCirc(5f, 2, 6).Should().BeApproximately(5.73205080757f, 0.001f);
Action invalidTime = () => Easing.InOutCirc(1.5f);
invalidTime.Should().Throw<ArgumentException>();
invalidTime = () => Easing.InOutCirc(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
[Test]
public void OutInCircular()
{
Easing.OutInCirc(0.25f).Should().BeApproximately(0.43301270189222f, 0.001f);
Easing.OutInCirc(0.5f).Should().BeApproximately(0.5f, 0.001f);
Easing.OutInCirc(0.75f).Should().BeApproximately(0.56698729810778f, 0.001f);
Easing.OutInCirc(3f, 2, 6).Should().BeApproximately(3.73205080757f, 0.001f);
Easing.OutInCirc(4f, 2, 6).Should().BeApproximately(4f, 0.001f);
Easing.OutInCirc(5f, 2, 6).Should().BeApproximately(4.26794919243f, 0.001f);
Action invalidTime = () => Easing.OutInCirc(1.5f);
invalidTime.Should().Throw<ArgumentException>();
invalidTime = () => Easing.OutInCirc(7f, 2, 6);
invalidTime.Should().Throw<ArgumentException>();
}
}
public class DoubleTests
@ -634,6 +778,118 @@ namespace Test
CheckDoubleArguments(Easing.OutInSine, Easing.OutInSine);
}
[Test]
public void InExpo()
{
Easing.InExpo(0.25).Should().BeApproximately(0.0045242717280199, 0.0001);
Easing.InExpo(0.5).Should().BeApproximately(0.03025, 0.0001);
Easing.InExpo(0.75).Should().BeApproximately(0.17577669529664, 0.0001);
Easing.InExpo(3, 2, 6).Should().BeApproximately(2.0180970869121, 0.0001);
Easing.InExpo(4, 2, 6).Should().BeApproximately(2.121, 0.0001);
Easing.InExpo(5, 2, 6).Should().BeApproximately(2.703106781187, 0.0001);
CheckDoubleArguments(Easing.InExpo, Easing.InExpo);
}
[Test]
public void OutExpo()
{
Easing.OutExpo(0.25).Should().BeApproximately(0.82404652800807, 0.0001);
Easing.OutExpo(0.5).Should().BeApproximately(0.96971875, 0.0001);
Easing.OutExpo(0.75).Should().BeApproximately(0.99547020400025, 0.0001);
Easing.OutExpo(3, 2, 6).Should().BeApproximately(5.29618611203, 0.0001);
Easing.OutExpo(4, 2, 6).Should().BeApproximately(5.878875, 0.0001);
Easing.OutExpo(5, 2, 6).Should().BeApproximately(5.981880816, 0.0001);
CheckDoubleArguments(Easing.OutExpo, Easing.OutExpo);
}
[Test]
public void InOutExpo()
{
Easing.InOutExpo(0.25).Should().BeApproximately(0.015125, 0.001);
Easing.InOutExpo(0.5).Should().BeApproximately(0.5, 0.001);
Easing.InOutExpo(0.75).Should().BeApproximately(0.9848671875, 0.001);
Easing.InOutExpo(3, 2, 6).Should().BeApproximately(2.0605, 0.001);
Easing.InOutExpo(4, 2, 6).Should().BeApproximately(4, 0.001);
Easing.InOutExpo(5, 2, 6).Should().BeApproximately(5.93946875, 0.001);
CheckDoubleArguments(Easing.InOutExpo, Easing.InOutExpo);
}
[Test]
public void OutInExpo()
{
Easing.OutInExpo(0.25).Should().BeApproximately(0.484859375, 0.001);
Easing.OutInExpo(0.5).Should().BeApproximately(0.5, 0.001);
Easing.OutInExpo(0.75).Should().BeApproximately(0.515125, 0.001);
Easing.OutInExpo(3, 2, 6).Should().BeApproximately(3.9394375, 0.001);
Easing.OutInExpo(4, 2, 6).Should().BeApproximately(4, 0.001);
Easing.OutInExpo(5, 2, 6).Should().BeApproximately(4.0605, 0.001);
CheckDoubleArguments(Easing.OutInExpo, Easing.OutInExpo);
}
[Test]
public void InCircular()
{
Easing.InCirc(0.25).Should().BeApproximately(0.031754163448146, 0.001);
Easing.InCirc(0.5).Should().BeApproximately(0.13397459621556, 0.001);
Easing.InCirc(0.75).Should().BeApproximately(0.33856217223385, 0.001);
Easing.InCirc(3, 2, 6).Should().BeApproximately(2.127016653793, 0.001);
Easing.InCirc(4, 2, 6).Should().BeApproximately(2.535898384862, 0.001);
Easing.InCirc(5, 2, 6).Should().BeApproximately(3.35424868894, 0.001);
CheckDoubleArguments(Easing.InCirc, Easing.InCirc);
}
[Test]
public void OutCircular()
{
Easing.OutCirc(0.25).Should().BeApproximately(0.66143782776615, 0.001);
Easing.OutCirc(0.5).Should().BeApproximately(0.86602540378444, 0.001);
Easing.OutCirc(0.75).Should().BeApproximately(0.96824583655185, 0.001);
Easing.OutCirc(3, 2, 6).Should().BeApproximately(4.64575131107, 0.001);
Easing.OutCirc(4, 2, 6).Should().BeApproximately(5.46410161514, 0.001);
Easing.OutCirc(5, 2, 6).Should().BeApproximately(5.87298334621, 0.001);
CheckDoubleArguments(Easing.OutCirc, Easing.OutCirc);
}
[Test]
public void InOutCircular()
{
Easing.InOutCirc(0.25).Should().BeApproximately(0.066987298107781, 0.001);
Easing.InOutCirc(0.5).Should().BeApproximately(0.5, 0.001);
Easing.InOutCirc(0.75).Should().BeApproximately(0.93301270189222, 0.001);
Easing.InOutCirc(3, 2, 6).Should().BeApproximately(2.267949192431, 0.001);
Easing.InOutCirc(4, 2, 6).Should().BeApproximately(4, 0.001);
Easing.InOutCirc(5, 2, 6).Should().BeApproximately(5.73205080757, 0.001);
CheckDoubleArguments(Easing.InOutCirc, Easing.InOutCirc);
}
[Test]
public void OutInCircular()
{
Easing.OutInCirc(0.25).Should().BeApproximately(0.43301270189222, 0.001);
Easing.OutInCirc(0.5).Should().BeApproximately(0.5, 0.001);
Easing.OutInCirc(0.75).Should().BeApproximately(0.56698729810778, 0.001);
Easing.OutInCirc(3, 2, 6).Should().BeApproximately(3.73205080757, 0.001);
Easing.OutInCirc(4, 2, 6).Should().BeApproximately(4, 0.001);
Easing.OutInCirc(5, 2, 6).Should().BeApproximately(4.26794919243, 0.001);
CheckDoubleArguments(Easing.OutInCirc, Easing.OutInCirc);
}
}
}
}