#ifndef BREEZE_EASINGS_H #define BREEZE_EASINGS_H #include // From: https://easings.net/ typedef enum BzEaseType { BZ_EASE_NONE, BZ_EASE_IN_SINE, BZ_EASE_OUT_SINE, BZ_EASE_INOUT_SINE, BZ_EASE_IN_QUAD, BZ_EASE_OUT_QUAD, BZ_EASE_INOUT_QUAD, BZ_EASE_IN_CUBIC, BZ_EASE_OUT_CUBIC, BZ_EASE_INOUT_CUBIC, BZ_EASE_IN_QUART, BZ_EASE_OUT_QUART, BZ_EASE_INOUT_QUART, BZ_EASE_IN_QUINT, BZ_EASE_OUT_QUINT, BZ_EASE_INOUT_QUINT, BZ_EASE_IN_EXPO, BZ_EASE_OUT_EXPO, BZ_EASE_INOUT_EXPO, BZ_EASE_IN_CIRC, BZ_EASE_OUT_CIRC, BZ_EASE_INOUT_CIRC, BZ_EASE_IN_BACK, BZ_EASE_OUT_BACK, BZ_EASE_INOUT_BACK, BZ_EASE_IN_ELASTIC, BZ_EASE_OUT_ELASTIC, BZ_EASE_INOUT_ELASTIC, BZ_EASE_IN_BOUNCE, BZ_EASE_OUT_BOUNCE, BZ_EASE_INOUT_BOUNCE, BZ_EASE_COUNT, } BzEaseType; static const char *bzEasePrettyName(BzEaseType type) { switch (type) { case BZ_EASE_NONE: return "easeNone"; case BZ_EASE_IN_SINE: return "easeInSine"; case BZ_EASE_OUT_SINE: return "easeOutSine"; case BZ_EASE_INOUT_SINE: return "easeInOutSine"; case BZ_EASE_IN_QUAD: return "easeInQuad"; case BZ_EASE_OUT_QUAD: return "easeOutQuad"; case BZ_EASE_INOUT_QUAD: return "easeInOutQuad"; case BZ_EASE_IN_CUBIC: return "easeInCubic"; case BZ_EASE_OUT_CUBIC: return "easeOutCubic"; case BZ_EASE_INOUT_CUBIC: return "easeInOutCubic"; case BZ_EASE_IN_QUART: return "easeInQuart"; case BZ_EASE_OUT_QUART: return "easeOutQuart"; case BZ_EASE_INOUT_QUART: return "easeInOutQuart"; case BZ_EASE_IN_QUINT: return "easeInQuint"; case BZ_EASE_OUT_QUINT: return "easeOutQuint"; case BZ_EASE_INOUT_QUINT: return "easeInOutQuint"; case BZ_EASE_IN_EXPO: return "easeInExpo"; case BZ_EASE_OUT_EXPO: return "easeOutExpo"; case BZ_EASE_INOUT_EXPO: return "easeInOutExpo"; case BZ_EASE_IN_CIRC: return "easeInCirc"; case BZ_EASE_OUT_CIRC: return "easeOutCirc"; case BZ_EASE_INOUT_CIRC: return "easeInOutCirc"; case BZ_EASE_IN_BACK: return "easeInBack"; case BZ_EASE_OUT_BACK: return "easeOutBack"; case BZ_EASE_INOUT_BACK: return "easeInOutBack"; case BZ_EASE_IN_ELASTIC: return "easeInElastic"; case BZ_EASE_OUT_ELASTIC: return "easeOutElastic"; case BZ_EASE_INOUT_ELASTIC: return "easeInOutElastic"; case BZ_EASE_IN_BOUNCE: return "easeeInBounce"; case BZ_EASE_OUT_BOUNCE: return "easeOutBounce"; case BZ_EASE_INOUT_BOUNCE: return "easeInOutBounce"; default: return NULL; } } static f32 bzEaseNone(f32 x) { return x; } static f32 bzEaseInSine(f32 x) { return 1 - cosf((x * M_PI) / 2.0f); } static f32 bzEaseOutSine(f32 x) { return sinf((x * M_PI) / 2.0f); } static f32 bzEaseInOutSine(f32 x) { return -(-cosf(M_PI * x) - 1) / 2.0f; } static f32 bzEaseInQuad(f32 x) { return x * x; } static f32 bzEaseOutQuad(f32 x) { return 1 - (1 - x) * (1 - x); } static f32 bzEaseInOutQuad(f32 x) { return x < 0.5f ? 2.0f * x * x : 1 - powf(-2.0f * x + 2, 2) / 2.0f; } static f32 bzEaseInCubic(f32 x) { return x * x * x; } static f32 bzEaseOutCubic(f32 x) { return 1 - powf(1 - x, 3); } static f32 bzEaseInOutCubic(f32 x) { return x < 0.5 ? 4 * x * x * x : 1 - powf(-2.0f * x + 2, 3) / 2.0f; } static f32 bzEaseInQuart(f32 x) { return x * x * x * x; } static f32 bzEaseOutQuart(f32 x) { return 1 - powf(1 - x, 4); } static f32 bzEaseInOutQuart(f32 x) { return x < 0.5 ? 8 * x * x * x * x : 1 - powf(-2 * x + 2, 4) / 2.0f; } static f32 bzEaseInQuint(f32 x) { return x * x * x * x * x; } static f32 bzEaseOutQuint(f32 x) { return 1 - powf(1 - x, 5); } static f32 bzEaseInOutQuint(f32 x) { return x < 0.5 ? 16 * x * x * x * x * x : 1 - powf(-2 * x + 2, 5) / 2.0f; } static f32 bzEaseInExpo(f32 x) { return x == 0 ? 0 : powf(2, 10 * x - 10); } static f32 bzEaseOutExpo(f32 x) { return x == 1 ? 1 : 1 - powf(2, -10 * x); } static f32 bzEaseInOutExpo(f32 x) { if (x == 0) return 0; if (x == 1) return 1; return x < 0.5 ? powf(2, 20 * x - 10) / 2.0 : (2 - powf(2, -20 * x + 10)) / 2.0; } static f32 bzEaseInCirc(f32 x) { return 1 - sqrtf(1 - powf(x, 2)); } static f32 bzEaseOutCirc(f32 x) { return sqrtf(1 - powf(x - 1, 2)); } static f32 bzEaseInOutCirc(f32 x) { return x < 0.5 ? (1 - sqrtf(1 - powf(2 * x, 2))) / 2 : (sqrtf(1 - powf(-2 * x + 2, 2)) + 1) / 2; } static f32 bzEaseInBack(f32 x) { const f32 c1 = 1.70158f; const f32 c3 = c1 + 1; return (c3 * x * x * x) - (c1 * x * x); } static f32 bzEaseOutBack(f32 x) { const f32 c1 = 1.70158f; const f32 c3 = c1 + 1; return 1 + (c3 * powf(x - 1, 3)) + (c1 * powf(x - 1, 2)); } static f32 bzEaseInOutBack(f32 x) { const f32 c1 = 1.70158f; const f32 c2 = c1 * 1.525; return x < 0.5 ? (powf(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2.0f : (powf(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2.0f; } static f32 bzEaseInElastic(f32 x) { const f32 c4 = (2 * M_PI) / 3.0f; if (x == 0) return 0; if (x == 1) return 1; return -powf(2, 10 * x - 10) * sinf((x * 10 - 10.75) * c4); } static f32 bzEaseOutElastic(f32 x) { const f32 c4 = (2 * M_PI) / 3.0f; if (x == 0) return 0; if (x == 1) return 1; return powf(2, -10 * x) * sinf((x * 10 - 0.75) * c4) + 1; } static f32 bzEaseInOutElastic(f32 x) { const f32 c5 = (2 * M_PI) / 4.5f; if (x == 0) return 0; if (x == 1) return 1; return x < 0.5 ? -(powf(2, 20 * x - 10) * sinf((20 * x - 11.125) * c5)) / 2.0f : (powf(2, -20 * x + 10) * sinf((20 * x - 11.125) * c5)) / 2.0f + 1; } static f32 bzEaseOutBounce(f32 x); static f32 bzEaseInBounce(f32 x) { return 1 - bzEaseOutBounce(1 - x); } static f32 bzEaseOutBounce(f32 x) { const f32 n1 = 7.5625; const f32 d1 = 2.75; if (x < 1 / d1) { return n1 * x * x; } else if (x < 2 / d1) { return (x -= 1.5f / d1, n1 * x * x + 0.75f); } else if (x < 2.5 / d1) { return (x -= 2.25 / d1, n1 * x * x + 0.9375); } else { return (x -= 2.625 / d1, n1 * x * x + 0.984375); } } static f32 bzEaseInOutBounce(f32 x) { return x < 0.5 ? (1 - bzEaseOutBounce(1 - 2 * x)) / 2.0f : (1 + bzEaseOutBounce(2 * x - 1)) / 2.0f; } static f32 bzEase(BzEaseType easeType, f32 x) { switch (easeType) { case BZ_EASE_NONE: return bzEaseNone(x); case BZ_EASE_IN_SINE: return bzEaseInSine(x); case BZ_EASE_OUT_SINE: return bzEaseOutSine(x); case BZ_EASE_INOUT_SINE: return bzEaseInOutSine(x); case BZ_EASE_IN_QUAD: return bzEaseInQuad(x); case BZ_EASE_OUT_QUAD: return bzEaseOutQuad(x); case BZ_EASE_INOUT_QUAD: return bzEaseInOutQuad(x); case BZ_EASE_IN_CUBIC: return bzEaseInCubic(x); case BZ_EASE_OUT_CUBIC: return bzEaseOutCubic(x); case BZ_EASE_INOUT_CUBIC: return bzEaseInOutCubic(x); case BZ_EASE_IN_QUART: return bzEaseInQuart(x); case BZ_EASE_OUT_QUART: return bzEaseOutQuart(x); case BZ_EASE_INOUT_QUART: return bzEaseInOutQuart(x); case BZ_EASE_IN_QUINT: return bzEaseInQuint(x); case BZ_EASE_OUT_QUINT: return bzEaseOutQuint(x); case BZ_EASE_INOUT_QUINT: return bzEaseInOutQuint(x); case BZ_EASE_IN_EXPO: return bzEaseInExpo(x); case BZ_EASE_OUT_EXPO: return bzEaseOutExpo(x); case BZ_EASE_INOUT_EXPO: return bzEaseInOutExpo(x); case BZ_EASE_IN_CIRC: return bzEaseInCirc(x); case BZ_EASE_OUT_CIRC: return bzEaseOutCirc(x); case BZ_EASE_INOUT_CIRC: return bzEaseInOutCirc(x); case BZ_EASE_IN_BACK: return bzEaseInBack(x); case BZ_EASE_OUT_BACK: return bzEaseOutBack(x); case BZ_EASE_INOUT_BACK: return bzEaseInOutBack(x); case BZ_EASE_IN_ELASTIC: return bzEaseInElastic(x); case BZ_EASE_OUT_ELASTIC: return bzEaseOutElastic(x); case BZ_EASE_INOUT_ELASTIC: return bzEaseInOutElastic(x); case BZ_EASE_IN_BOUNCE: return bzEaseInBounce(x); case BZ_EASE_OUT_BOUNCE: return bzEaseOutBounce(x); case BZ_EASE_INOUT_BOUNCE: return bzEaseInOutBounce(x); } } #endif //BREEZE_EASINGS_H