doxygen: add newline after \file
[blender.git] / source / blender / blenlib / intern / easing.c
index f3b2efd..0776527 100644 (file)
@@ -1,20 +1,17 @@
 /*
- * Copyright © 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 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.
+ * * 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.
+ * * 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
  * 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.
+ *
+ * Copyright (c) 2001 Robert Penner
+ * All rights reserved.
  */
 
-/** \file blender/blenlib/intern/easing.c
- *  \ingroup bli
+/** \file
+ * \ingroup bli
  */
-#include <math.h>
 
 #include "BLI_math_base.h"
 
 
 #include "BLI_strict_flags.h"
 
+/* blend if (amplitude < fabsf(change) */
+#define USE_ELASTIC_BLEND
 
-float BackEaseIn(float time, float begin, float change, float duration, float overshoot)
+float BLI_easing_back_ease_in(float time, float begin, float change, float duration, float overshoot)
 {
-       if (overshoot == 0.0f)
-               overshoot = 1.70158f;
        time /= duration;
        return change * time * time * ((overshoot + 1) * time - overshoot) + begin;
 }
 
-float BackEaseOut(float time, float begin, float change, float duration, float overshoot)
+float BLI_easing_back_ease_out(float time, float begin, float change, float duration, float overshoot)
 {
-       if (overshoot == 0.0f)
-               overshoot = 1.70158f;
        time = time / duration - 1;
        return change * (time * time * ((overshoot + 1) * time + overshoot) + 1) + begin;
 }
 
-float BackEaseInOut(float time, float begin, float change, float duration, float overshoot)
+float BLI_easing_back_ease_in_out(float time, float begin, float change, float duration, float overshoot)
 {
-       if (overshoot == 0.0f)
-               overshoot = 1.70158f; 
        overshoot *= 1.525f;
        if ((time /= duration / 2) < 1.0f) {
                return change / 2 * (time * time * ((overshoot + 1) * time - overshoot)) + begin;
@@ -70,7 +64,7 @@ float BackEaseInOut(float time, float begin, float change, float duration, float
 
 }
 
-float BounceEaseOut(float time, float begin, float change, float duration)
+float BLI_easing_bounce_ease_out(float time, float begin, float change, float duration)
 {
        time /= duration;
        if (time < (1 / 2.75f)) {
@@ -90,32 +84,32 @@ float BounceEaseOut(float time, float begin, float change, float duration)
        }
 }
 
-float BounceEaseIn(float time, float begin, float change, float duration)
+float BLI_easing_bounce_ease_in(float time, float begin, float change, float duration)
 {
-       return change - BounceEaseOut(duration - time, 0, change, duration) + begin;
+       return change - BLI_easing_bounce_ease_out(duration - time, 0, change, duration) + begin;
 }
 
-float BounceEaseInOut(float time, float begin, float change, float duration)
+float BLI_easing_bounce_ease_in_out(float time, float begin, float change, float duration)
 {
        if (time < duration / 2)
-               return BounceEaseIn(time * 2, 0, change, duration) * 0.5f + begin;
+               return BLI_easing_bounce_ease_in(time * 2, 0, change, duration) * 0.5f + begin;
        else
-               return BounceEaseOut(time * 2 - duration, 0, change, duration) * 0.5f + change * 0.5f + begin;
+               return BLI_easing_bounce_ease_out(time * 2 - duration, 0, change, duration) * 0.5f + change * 0.5f + begin;
 }
 
-float CircEaseIn(float time, float begin, float change, float duration)
+float BLI_easing_circ_ease_in(float time, float begin, float change, float duration)
 {
        time /= duration;
        return -change * (sqrtf(1 - time * time) - 1) + begin;
 }
 
-float CircEaseOut(float time, float begin, float change, float duration)
+float BLI_easing_circ_ease_out(float time, float begin, float change, float duration)
 {
        time = time / duration - 1;
        return change * sqrtf(1 - time * time) + begin;
 }
 
-float CircEaseInOut(float time, float begin, float change, float duration)
+float BLI_easing_circ_ease_in_out(float time, float begin, float change, float duration)
 {
        if ((time /= duration / 2) < 1.0f)
                return -change / 2 * (sqrtf(1 - time * time) - 1) + begin;
@@ -123,19 +117,19 @@ float CircEaseInOut(float time, float begin, float change, float duration)
        return change / 2 * (sqrtf(1 - time * time) + 1) + begin;
 }
 
-float CubicEaseIn(float time, float begin, float change, float duration)
+float BLI_easing_cubic_ease_in(float time, float begin, float change, float duration)
 {
        time /= duration;
        return change * time * time * time + begin;
 }
 
-float CubicEaseOut(float time, float begin, float change, float duration)
+float BLI_easing_cubic_ease_out(float time, float begin, float change, float duration)
 {
        time = time / duration - 1;
        return change * (time * time * time + 1) + begin;
 }
 
-float CubicEaseInOut(float time, float begin, float change, float duration)
+float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float duration)
 {
        if ((time /= duration / 2) < 1.0f)
                return change / 2 * time * time * time + begin;
@@ -143,86 +137,129 @@ float CubicEaseInOut(float time, float begin, float change, float duration)
        return change / 2 * (time * time * time + 2) + begin;
 }
 
-float ElasticEaseIn(float time, float begin, float change, float duration, float amplitude, float period)
+#ifdef USE_ELASTIC_BLEND
+/**
+ * When the amplitude is less than the change, we need to blend
+ * \a f when we're close to the crossing point (int time), else we get an ugly sharp falloff.
+ */
+static float elastic_blend(float time, float change, float duration, float amplitude, float s, float f)
+{
+       if (change) {
+               /* Looks like a magic number,
+                * but this is a part of the sine curve we need to blend from */
+               const float t = fabsf(s);
+               if (amplitude) {
+                       f *= amplitude / fabsf(change);
+               }
+               else {
+                       f = 0.0f;
+               }
+
+               if (fabsf(time * duration) < t) {
+                       float l = fabsf(time * duration) / t;
+                       f = (f * l) + (1.0f - l);
+               }
+       }
+
+       return f;
+}
+#endif
+
+float BLI_easing_elastic_ease_in(float time, float begin, float change, float duration, float amplitude, float period)
 {
        float s;
+       float f = 1.0f;
 
        if (time == 0.0f)
                return begin;
 
        if ((time /= duration) == 1.0f)
                return begin + change;
-
+       time -= 1.0f;
        if (!period)
                period = duration * 0.3f;
-
        if (!amplitude || amplitude < fabsf(change)) {
-               amplitude = change;
                s = period / 4;
+#ifdef USE_ELASTIC_BLEND
+               f = elastic_blend(time, change, duration, amplitude, s, f);
+#endif
+               amplitude = change;
        }
        else
                s = period / (2 * (float)M_PI) * asinf(change / amplitude);
 
-       time -= 1.0f;
-       return -(amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period)) + begin;
+       return (-f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + begin;
 }
 
-float ElasticEaseOut(float time, float begin, float change, float duration, float amplitude, float period)
+float BLI_easing_elastic_ease_out(float time, float begin, float change, float duration, float amplitude, float period)
 {
        float s;
+       float f = 1.0f;
 
        if (time == 0.0f)
                return begin;
        if ((time /= duration) == 1.0f)
                return begin + change;
+       time = -time;
        if (!period)
                period = duration * 0.3f;
        if (!amplitude || amplitude < fabsf(change)) {
-               amplitude = change;
                s = period / 4;
+#ifdef USE_ELASTIC_BLEND
+               f = elastic_blend(time, change, duration, amplitude, s, f);
+#endif
+               amplitude = change;
        }
        else
                s = period / (2 * (float)M_PI) * asinf(change / amplitude);
 
-       return (amplitude * powf(2, -10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period) + change + begin);
+       return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + change + begin;
 }
 
-float ElasticEaseInOut(float time, float begin, float change, float duration, float amplitude, float period)
+float BLI_easing_elastic_ease_in_out(float time, float begin, float change, float duration, float amplitude, float period)
 {
        float s;
+       float f = 1.0f;
 
        if (time == 0.0f)
                return begin;
        if ((time /= duration / 2) == 2.0f)
                return begin + change;
+       time -= 1.0f;
        if (!period)
                period = duration * (0.3f * 1.5f);
        if (!amplitude || amplitude < fabsf(change)) {
-               amplitude = change;
                s = period / 4;
+#ifdef USE_ELASTIC_BLEND
+               f = elastic_blend(time, change, duration, amplitude, s, f);
+#endif
+               amplitude = change;
        }
        else
                s = period / (2 * (float)M_PI) * asinf(change / amplitude);
-       if (time < 1.0f) {
-               time -= 1.0f;
-               return -0.5f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period)) + begin;
-       }
 
-       time -= 1.0f;
-       return amplitude * powf(2, -10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period) * 0.5f + change + begin;
+       if (time < 0.0f) {
+               f *= -0.5f;
+               return  (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + begin;
+       }
+       else {
+               time = -time;
+               f *= 0.5f;
+               return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + change + begin;
+       }
 }
 
-float ExpoEaseIn(float time, float begin, float change, float duration)
+float BLI_easing_expo_ease_in(float time, float begin, float change, float duration)
 {
        return (time == 0.0f) ? begin : change * powf(2, 10 * (time / duration - 1)) + begin;
 }
 
-float ExpoEaseOut(float time, float begin, float change, float duration)
+float BLI_easing_expo_ease_out(float time, float begin, float change, float duration)
 {
        return (time == duration) ? begin + change : change * (-powf(2, -10 * time / duration) + 1) + begin;
 }
 
-float ExpoEaseInOut(float time, float begin, float change, float duration)
+float BLI_easing_expo_ease_in_out(float time, float begin, float change, float duration)
 {
        if (time == 0.0f)
                return begin;
@@ -234,24 +271,24 @@ float ExpoEaseInOut(float time, float begin, float change, float duration)
        return change / 2 * (-powf(2, -10 * time) + 2) + begin;
 }
 
-float LinearEase(float time, float begin, float change, float duration)
+float BLI_easing_linear_ease(float time, float begin, float change, float duration)
 {
        return change * time / duration + begin;
 }
 
-float QuadEaseIn(float time, float begin, float change, float duration)
+float BLI_easing_quad_ease_in(float time, float begin, float change, float duration)
 {
        time /= duration;
        return change * time * time + begin;
 }
 
-float QuadEaseOut(float time, float begin, float change, float duration)
+float BLI_easing_quad_ease_out(float time, float begin, float change, float duration)
 {
        time /= duration;
        return -change * time * (time - 2) + begin;
 }
 
-float QuadEaseInOut(float time, float begin, float change, float duration)
+float BLI_easing_quad_ease_in_out(float time, float begin, float change, float duration)
 {
        if ((time /= duration / 2) < 1.0f)
                return change / 2 * time * time + begin;
@@ -260,19 +297,19 @@ float QuadEaseInOut(float time, float begin, float change, float duration)
 }
 
 
-float QuartEaseIn(float time, float begin, float change, float duration)
+float BLI_easing_quart_ease_in(float time, float begin, float change, float duration)
 {
        time /= duration;
        return change * time * time * time * time + begin;
 }
 
-float QuartEaseOut(float time, float begin, float change, float duration)
+float BLI_easing_quart_ease_out(float time, float begin, float change, float duration)
 {
        time = time / duration - 1;
        return -change * (time * time * time * time - 1) + begin;
 }
 
-float QuartEaseInOut(float time, float begin, float change, float duration)
+float BLI_easing_quart_ease_in_out(float time, float begin, float change, float duration)
 {
        if ((time /= duration / 2) < 1.0f)
                return change / 2 * time * time * time * time + begin;
@@ -280,35 +317,35 @@ float QuartEaseInOut(float time, float begin, float change, float duration)
        return -change / 2 * ( time * time * time * time - 2) + begin;
 }
 
-float QuintEaseIn(float time, float begin, float change, float duration)
+float BLI_easing_quint_ease_in(float time, float begin, float change, float duration)
 {
        time /= duration;
        return change * time * time * time * time * time + begin;
 }
-float QuintEaseOut(float time, float begin, float change, float duration)
+float BLI_easing_quint_ease_out(float time, float begin, float change, float duration)
 {
        time = time / duration - 1;
        return change * (time * time * time * time * time + 1) + begin;
 }
-float QuintEaseInOut(float time, float begin, float change, float duration)
+float BLI_easing_quint_ease_in_out(float time, float begin, float change, float duration)
 {
        if ((time /= duration / 2) < 1.0f)
-                return change / 2 * time * time * time * time * time + begin;
+               return change / 2 * time * time * time * time * time + begin;
        time -= 2.0f;
        return change / 2 * (time * time * time * time * time + 2) + begin;
 }
 
-float SineEaseIn(float time, float begin, float change, float duration)
+float BLI_easing_sine_ease_in(float time, float begin, float change, float duration)
 {
        return -change * cosf(time / duration * (float)M_PI_2) + change + begin;
 }
 
-float SineEaseOut(float time, float begin, float change, float duration)
+float BLI_easing_sine_ease_out(float time, float begin, float change, float duration)
 {
        return change * sinf(time / duration * (float)M_PI_2) + begin;
 }
 
-float SineEaseInOut(float time, float begin, float change, float duration)
+float BLI_easing_sine_ease_in_out(float time, float begin, float change, float duration)
 {
        return -change / 2 * (cosf((float)M_PI * time / duration) - 1) + begin;
 }