using System; namespace MLEM.Misc { /// /// This class contains a set of easing functions, adapted from . /// These can be used for ui elements or any other kind of animations. /// By default, each function takes an input that ranges between 0 and 1, and produces an output that roughly ranges between 0 and 1. To change this behavior, you can use and . /// public static class Easings { /// public static readonly Easing InSine = p => 1 - (float) Math.Cos(p * Math.PI / 2); /// public static readonly Easing OutSine = p => (float) Math.Sin(p * Math.PI / 2); /// public static readonly Easing InOutSine = p => -((float) Math.Cos(p * Math.PI) - 1) / 2; /// public static readonly Easing InQuad = p => p * p; /// public static readonly Easing OutQuad = p => 1 - (1 - p) * (1 - p); /// public static readonly Easing InOutQuad = p => p < 0.5F ? 2 * p * p : 1 - (-2 * p + 2) * (-2 * p + 2) / 2; /// public static readonly Easing InCubic = p => p * p * p; /// public static readonly Easing OutCubic = p => 1 - (1 - p) * (1 - p) * (1 - p); /// public static readonly Easing InOutCubic = p => p < 0.5F ? 4 * p * p * p : 1 - (-2 * p + 2) * (-2 * p + 2) * (-2 * p + 2) / 2; /// public static readonly Easing InExpo = p => p == 0 ? 0 : (float) Math.Pow(2, 10 * p - 10); /// public static readonly Easing OutExpo = p => p == 1 ? 1 : 1 - (float) Math.Pow(2, -10 * p); /// public static readonly Easing InOutExpo = p => p == 0 ? 0 : p == 1 ? 1 : p < 0.5F ? (float) Math.Pow(2, 20 * p - 10) / 2 : (2 - (float) Math.Pow(2, -20 * p + 10)) / 2; /// public static readonly Easing InCirc = p => 1 - (float) Math.Sqrt(1 - p * p); /// public static readonly Easing OutCirc = p => (float) Math.Sqrt(1 - (p - 1) * (p - 1)); /// public static readonly Easing InOutCirc = p => p < 0.5F ? (1 - (float) Math.Sqrt(1 - 2 * p * (2 * p))) / 2 : ((float) Math.Sqrt(1 - (-2 * p + 2) * (-2 * p + 2)) + 1) / 2; /// public static readonly Easing InBack = p => 2.70158F * p * p * p - 1.70158F * p * p; /// public static readonly Easing OutBack = p => 1 + 2.70158F * (p - 1) * (p - 1) * (p - 1) + 1.70158F * (p - 1) * (p - 1); /// public static readonly Easing InOutBack = p => p < 0.5 ? 2 * p * (2 * p) * ((2.594909F + 1) * 2 * p - 2.594909F) / 2 : ((2 * p - 2) * (2 * p - 2) * ((2.594909F + 1) * (p * 2 - 2) + 2.594909F) + 2) / 2; /// public static readonly Easing InElastic = p => p == 0 ? 0 : p == 1 ? 1 : -(float) Math.Pow(2, 10 * p - 10) * (float) Math.Sin((p * 10 - 10.75) * 2.094395F); /// public static readonly Easing OutElastic = p => p == 0 ? 0 : p == 1 ? 1 : (float) Math.Pow(2, -10 * p) * (float) Math.Sin((p * 10 - 0.75) * 2.0943951023932F) + 1; /// public static readonly Easing InOutElastic = p => p == 0 ? 0 : p == 1 ? 1 : p < 0.5 ? -((float) Math.Pow(2, 20 * p - 10) * (float) Math.Sin((20 * p - 11.125) * 1.39626340159546F)) / 2 : (float) Math.Pow(2, -20 * p + 10) * (float) Math.Sin((20 * p - 11.125) * 1.39626340159546F) / 2 + 1; /// public static readonly Easing InBounce = p => 1 - OutBounce(1 - p); /// public static readonly Easing OutBounce = p => { const float n1 = 7.5625F; const float d1 = 2.75F; if (p < 1 / d1) { return n1 * p * p; } else if (p < 2 / d1) { return n1 * (p -= 1.5F / d1) * p + 0.75F; } else if (p < 2.5 / d1) { return n1 * (p -= 2.25F / d1) * p + 0.9375F; } else { return n1 * (p -= 2.625F / d1) * p + 0.984375F; } }; /// public static readonly Easing InOutBounce = p => p < 0.5 ? (1 - OutBounce(1 - 2 * p)) / 2 : (1 + OutBounce(2 * p - 1)) / 2; /// /// Scales the input of an easing function, which is usually between 0 and 1, to a given minimum and maximum. /// Note that the minimum needs to be smaller than the maximum. /// /// The easing function to scale /// The minimum input value /// The maximum input value /// The scaled easing function public static Easing ScaleInput(this Easing easing, float min, float max) { return p => easing((p - min) / (max - min)); } /// /// Scales the output of an easing function, which is usually between 0 and 1, to a given minimum and maximum. /// Note that the minimum needs to be smaller than the maximum. /// /// The easing function to scale /// The minimum output value /// The maximum output value /// The scaled easing function public static Easing ScaleOutput(this Easing easing, float min, float max) { return p => easing(p) * (max - min) + min; } /// /// Causes the easing functino to play fully, and then play fully in reverse, in the span between an input of 0 and 1. /// In some places, this behavior is also called "auto-reversing". /// /// The easing function to play in reverse as well /// An auto-reversing version of the easing function public static Easing AndReverse(this Easing easing) { return p => p <= 0.5F ? easing(p * 2) : easing(1 - (p - 0.5F) * 2); } /// /// A delegate method used by . /// /// The percentage into the easing function. Either between 0 and 1, or, if was used, between an arbitary set of values. public delegate float Easing(float percentage); } }