/* RetroArch - A frontend for libretro. * Copyright (C) 2014-2015 - Jean-André Santoni * Copyright (C) 2011-2015 - Daniel De Matteis * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with RetroArch. * If not, see . */ #include "menu_animation.h" #include "../driver.h" #include static void tween_free(tween_t *tween) { if (tween) free(tween); tween = NULL; } bool add_tween(float duration, float target_value, float* subject, easingFunc easing, tween_cb cb) { tween_t *tween = NULL, *temp_tweens = NULL; if (!driver.menu) return false; temp_tweens = (tween_t*)realloc(driver.menu->tweens, (driver.menu->numtweens + 1) * sizeof(tween_t)); if (!temp_tweens) { tween_free(driver.menu->tweens); return false; } driver.menu->tweens = temp_tweens; tween = (tween_t*)&driver.menu->tweens[driver.menu->numtweens]; if (!tween) return false; tween->alive = 1; tween->duration = duration; tween->running_since = 0; tween->initial_value = *subject; tween->target_value = target_value; tween->subject = subject; tween->easing = easing; tween->cb = cb; driver.menu->numtweens++; return true; } void update_tweens(float dt) { unsigned i; unsigned active_tweens = 0; for(i = 0; i < driver.menu->numtweens; i++) { tween_t *tween = &driver.menu->tweens[i]; if (!tween) continue; if (tween->running_since >= tween->duration) continue; tween->running_since += dt; if (tween->easing) *tween->subject = tween->easing( tween->running_since, tween->initial_value, tween->target_value - tween->initial_value, tween->duration); if (tween->running_since >= tween->duration) { *tween->subject = tween->target_value; if (tween->cb) tween->cb(); } if (tween->running_since < tween->duration) active_tweens += 1; } if (!active_tweens) driver.menu->numtweens = 0; } /* Linear */ float linear(float t, float b, float c, float d) { return c * t / d + b; } /* Quad */ float inQuad(float t, float b, float c, float d) { return c * pow(t / d, 2) + b; } float outQuad(float t, float b, float c, float d) { t = t / d; return -c * t * (t - 2) + b; } float inOutQuad(float t, float b, float c, float d) { t = t / d * 2; if (t < 1) return c / 2 * pow(t, 2) + b; return -c / 2 * ((t - 1) * (t - 3) - 1) + b; } float outInQuad(float t, float b, float c, float d) { if (t < d / 2) return outQuad(t * 2, b, c / 2, d); return inQuad((t * 2) - d, b + c / 2, c / 2, d); } /* Cubic */ float inCubic(float t, float b, float c, float d) { return c * pow(t / d, 3) + b; } float outCubic(float t, float b, float c, float d) { return c * (pow(t / d - 1, 3) + 1) + b; } float inOutCubic(float t, float b, float c, float d) { t = t / d * 2; if (t < 1) return c / 2 * t * t * t + b; t = t - 2; return c / 2 * (t * t * t + 2) + b; } float outInCubic(float t, float b, float c, float d) { if (t < d / 2) return outCubic(t * 2, b, c / 2, d); return inCubic((t * 2) - d, b + c / 2, c / 2, d); } /* Quart */ float inQuart(float t, float b, float c, float d) { return c * pow(t / d, 4) + b; } float outQuart(float t, float b, float c, float d) { return -c * (pow(t / d - 1, 4) - 1) + b; } float inOutQuart(float t, float b, float c, float d) { t = t / d * 2; if (t < 1) return c / 2 * pow(t, 4) + b; return -c / 2 * (pow(t - 2, 4) - 2) + b; } float outInQuart(float t, float b, float c, float d) { if (t < d / 2) return outQuart(t * 2, b, c / 2, d); return inQuart((t * 2) - d, b + c / 2, c / 2, d); } /* Quint */ float inQuint(float t, float b, float c, float d) { return c * pow(t / d, 5) + b; } float outQuint(float t, float b, float c, float d) { return c * (pow(t / d - 1, 5) + 1) + b; } float inOutQuint(float t, float b, float c, float d) { t = t / d * 2; if (t < 1) return c / 2 * pow(t, 5) + b; return c / 2 * (pow(t - 2, 5) + 2) + b; } float outInQuint(float t, float b, float c, float d) { if (t < d / 2) return outQuint(t * 2, b, c / 2, d); return inQuint((t * 2) - d, b + c / 2, c / 2, d); } /* Sine */ float inSine(float t, float b, float c, float d) { return -c * cos(t / d * (M_PI / 2)) + c + b; } float outSine(float t, float b, float c, float d) { return c * sin(t / d * (M_PI / 2)) + b; } float inOutSine(float t, float b, float c, float d) { return -c / 2 * (cos(M_PI * t / d) - 1) + b; } float outInSine(float t, float b, float c, float d) { if (t < d / 2) return outSine(t * 2, b, c / 2, d); return inSine((t * 2) -d, b + c / 2, c / 2, d); } /* Expo */ float inExpo(float t, float b, float c, float d) { if (t == 0) return b; return c * powf(2, 10 * (t / d - 1)) + b - c * 0.001; } float outExpo(float t, float b, float c, float d) { if (t == d) return b + c; return c * 1.001 * (-powf(2, -10 * t / d) + 1) + b; } float inOutExpo(float t, float b, float c, float d) { if (t == 0) return b; if (t == d) return b + c; t = t / d * 2; if (t < 1) return c / 2 * powf(2, 10 * (t - 1)) + b - c * 0.0005; return c / 2 * 1.0005 * (-powf(2, -10 * (t - 1)) + 2) + b; } float outInExpo(float t, float b, float c, float d) { if (t < d / 2) return outExpo(t * 2, b, c / 2, d); return inExpo((t * 2) - d, b + c / 2, c / 2, d); } /* Circ */ float inCirc(float t, float b, float c, float d) { return(-c * (sqrt(1 - powf(t / d, 2)) - 1) + b); } float outCirc(float t, float b, float c, float d) { return(c * sqrt(1 - powf(t / d - 1, 2)) + b); } float inOutCirc(float t, float b, float c, float d) { t = t / d * 2; if (t < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; t = t - 2; return c / 2 * (sqrt(1 - t * t) + 1) + b; } float outInCirc(float t, float b, float c, float d) { if (t < d / 2) return outCirc(t * 2, b, c / 2, d); return inCirc((t * 2) - d, b + c / 2, c / 2, d); } /* Bounce */ float outBounce(float t, float b, float c, float d) { t = t / d; if (t < 1 / 2.75) return c * (7.5625 * t * t) + b; if (t < 2 / 2.75) { t = t - (1.5 / 2.75); return c * (7.5625 * t * t + 0.75) + b; } else if (t < 2.5 / 2.75) { t = t - (2.25 / 2.75); return c * (7.5625 * t * t + 0.9375) + b; } t = t - (2.625 / 2.75); return c * (7.5625 * t * t + 0.984375) + b; } float inBounce(float t, float b, float c, float d) { return c - outBounce(d - t, 0, c, d) + b; } float inOutBounce(float t, float b, float c, float d) { if (t < d / 2) return inBounce(t * 2, 0, c, d) * 0.5 + b; return outBounce(t * 2 - d, 0, c, d) * 0.5 + c * .5 + b; } float outInBounce(float t, float b, float c, float d) { if (t < d / 2) return outBounce(t * 2, b, c / 2, d); return inBounce((t * 2) - d, b + c / 2, c / 2, d); }