1/*
2Disclaimer for Robert Penner's Easing Equations license:
3
4TERMS OF USE - EASING EQUATIONS
5
6Open source under the BSD License.
7
8Copyright © 2001 Robert Penner
9All rights reserved.
10
11Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
12
13 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
14 * 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.
15 * 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.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 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.
18*/
19
20#include <QtCore/qmath.h>
21#include <math.h>
22#ifndef M_PI
23#define M_PI 3.14159265358979323846
24#endif
25#ifndef M_PI_2
26#define M_PI_2 (M_PI / 2)
27#endif
28
29QT_USE_NAMESPACE
30
31/**
32 * Easing equation function for a simple linear tweening, with no easing.
33 *
34 * @param t Current time (in frames or seconds).
35 * @return The correct value.
36 */
37static qreal easeNone(qreal progress)
38{
39 return progress;
40}
41
42/**
43 * Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
44 *
45 * @param t Current time (in frames or seconds).
46 * @return The correct value.
47 */
48static qreal easeInQuad(qreal t)
49{
50 return t*t;
51}
52
53/**
54* Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity.
55*
56* @param t Current time (in frames or seconds).
57* @return The correct value.
58*/
59static qreal easeOutQuad(qreal t)
60{
61 return -t*(t-2);
62}
63
64/**
65 * Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration.
66 *
67 * @param t Current time (in frames or seconds).
68 * @return The correct value.
69 */
70static qreal easeInOutQuad(qreal t)
71{
72 t*=2.0;
73 if (t < 1) {
74 return t*t/qreal(2);
75 } else {
76 --t;
77 return -0.5 * (t*(t-2) - 1);
78 }
79}
80
81/**
82 * Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration.
83 *
84 * @param t Current time (in frames or seconds).
85 * @return The correct value.
86 */
87static qreal easeOutInQuad(qreal t)
88{
89 if (t < 0.5) return easeOutQuad (t*2)/2;
90 return easeInQuad((2*t)-1)/2 + 0.5;
91}
92
93/**
94 * Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity.
95 *
96 * @param t Current time (in frames or seconds).
97 * @return The correct value.
98 */
99static qreal easeInCubic(qreal t)
100{
101 return t*t*t;
102}
103
104/**
105 * Easing equation function for a cubic (t^3) easing out: decelerating to zero velocity.
106 *
107 * @param t Current time (in frames or seconds).
108 * @return The correct value.
109 */
110static qreal easeOutCubic(qreal t)
111{
112 t-=1.0;
113 return t*t*t + 1;
114}
115
116/**
117 * Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration.
118 *
119 * @param t Current time (in frames or seconds).
120 * @return The correct value.
121 */
122static qreal easeInOutCubic(qreal t)
123{
124 t*=2.0;
125 if(t < 1) {
126 return 0.5*t*t*t;
127 } else {
128 t -= qreal(2.0);
129 return 0.5*(t*t*t + 2);
130 }
131}
132
133/**
134 * Easing equation function for a cubic (t^3) easing out/in: deceleration until halfway, then acceleration.
135 *
136 * @param t Current time (in frames or seconds).
137 * @return The correct value.
138 */
139static qreal easeOutInCubic(qreal t)
140{
141 if (t < 0.5) return easeOutCubic (2*t)/2;
142 return easeInCubic(2*t - 1)/2 + 0.5;
143}
144
145/**
146 * Easing equation function for a quartic (t^4) easing in: accelerating from zero velocity.
147 *
148 * @param t Current time (in frames or seconds).
149 * @return The correct value.
150 */
151static qreal easeInQuart(qreal t)
152{
153 return t*t*t*t;
154}
155
156/**
157 * Easing equation function for a quartic (t^4) easing out: decelerating to zero velocity.
158 *
159 * @param t Current time (in frames or seconds).
160 * @return The correct value.
161 */
162static qreal easeOutQuart(qreal t)
163{
164 t-= qreal(1.0);
165 return - (t*t*t*t- 1);
166}
167
168/**
169 * Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration.
170 *
171 * @param t Current time (in frames or seconds).
172 * @return The correct value.
173 */
174static qreal easeInOutQuart(qreal t)
175{
176 t*=2;
177 if (t < 1) return 0.5*t*t*t*t;
178 else {
179 t -= 2.0f;
180 return -0.5 * (t*t*t*t- 2);
181 }
182}
183
184/**
185 * Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration.
186 *
187 * @param t Current time (in frames or seconds).
188 * @return The correct value.
189 */
190static qreal easeOutInQuart(qreal t)
191{
192 if (t < 0.5) return easeOutQuart (2*t)/2;
193 return easeInQuart(2*t-1)/2 + 0.5;
194}
195
196/**
197 * Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity.
198 *
199 * @param t Current time (in frames or seconds).
200 * @return The correct value.
201 */
202static qreal easeInQuint(qreal t)
203{
204 return t*t*t*t*t;
205}
206
207/**
208 * Easing equation function for a quintic (t^5) easing out: decelerating to zero velocity.
209 *
210 * @param t Current time (in frames or seconds).
211 * @return The correct value.
212 */
213static qreal easeOutQuint(qreal t)
214{
215 t-=1.0;
216 return t*t*t*t*t + 1;
217}
218
219/**
220 * Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration.
221 *
222 * @param t Current time (in frames or seconds).
223 * @return The correct value.
224 */
225static qreal easeInOutQuint(qreal t)
226{
227 t*=2.0;
228 if (t < 1) return 0.5*t*t*t*t*t;
229 else {
230 t -= 2.0;
231 return 0.5*(t*t*t*t*t + 2);
232 }
233}
234
235/**
236 * Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration.
237 *
238 * @param t Current time (in frames or seconds).
239 * @return The correct value.
240 */
241static qreal easeOutInQuint(qreal t)
242{
243 if (t < 0.5) return easeOutQuint (2*t)/2;
244 return easeInQuint(2*t - 1)/2 + 0.5;
245}
246
247/**
248 * Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity.
249 *
250 * @param t Current time (in frames or seconds).
251 * @return The correct value.
252 */
253static qreal easeInSine(qreal t)
254{
255 return (t == 1.0) ? 1.0 : -::qCos(t * M_PI_2) + 1.0;
256}
257
258/**
259 * Easing equation function for a sinusoidal (sin(t)) easing out: decelerating to zero velocity.
260 *
261 * @param t Current time (in frames or seconds).
262 * @return The correct value.
263 */
264static qreal easeOutSine(qreal t)
265{
266 return ::qSin(t* M_PI_2);
267}
268
269/**
270 * Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration.
271 *
272 * @param t Current time (in frames or seconds).
273 * @return The correct value.
274 */
275static qreal easeInOutSine(qreal t)
276{
277 return -0.5 * (::qCos(M_PI*t) - 1);
278}
279
280/**
281 * Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration.
282 *
283 * @param t Current time (in frames or seconds).
284 * @return The correct value.
285 */
286static qreal easeOutInSine(qreal t)
287{
288 if (t < 0.5) return easeOutSine (2*t)/2;
289 return easeInSine(2*t - 1)/2 + 0.5;
290}
291
292/**
293 * Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity.
294 *
295 * @param t Current time (in frames or seconds).
296 * @return The correct value.
297 */
298static qreal easeInExpo(qreal t)
299{
300 return (t==0 || t == 1.0) ? t : ::qPow(2.0, 10 * (t - 1)) - qreal(0.001);
301}
302
303/**
304 * Easing equation function for an exponential (2^t) easing out: decelerating to zero velocity.
305 *
306 * @param t Current time (in frames or seconds).
307 * @return The correct value.
308 */
309static qreal easeOutExpo(qreal t)
310{
311 return (t==1.0) ? 1.0 : 1.001 * (-::qPow(2.0f, -10 * t) + 1);
312}
313
314/**
315 * Easing equation function for an exponential (2^t) easing in/out: acceleration until halfway, then deceleration.
316 *
317 * @param t Current time (in frames or seconds).
318 * @return The correct value.
319 */
320static qreal easeInOutExpo(qreal t)
321{
322 if (t==0.0) return qreal(0.0);
323 if (t==1.0) return qreal(1.0);
324 t*=2.0;
325 if (t < 1) return 0.5 * ::qPow(qreal(2.0), 10 * (t - 1)) - 0.0005;
326 return 0.5 * 1.0005 * (-::qPow(qreal(2.0), -10 * (t - 1)) + 2);
327}
328
329/**
330 * Easing equation function for an exponential (2^t) easing out/in: deceleration until halfway, then acceleration.
331 *
332 * @param t Current time (in frames or seconds).
333 * @return The correct value.
334 */
335static qreal easeOutInExpo(qreal t)
336{
337 if (t < 0.5) return easeOutExpo (2*t)/2;
338 return easeInExpo(2*t - 1)/2 + 0.5;
339}
340
341/**
342 * Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity.
343 *
344 * @param t Current time (in frames or seconds).
345 * @return The correct value.
346 */
347static qreal easeInCirc(qreal t)
348{
349 return -(::sqrt(1 - t*t) - 1);
350}
351
352/**
353 * Easing equation function for a circular (sqrt(1-t^2)) easing out: decelerating to zero velocity.
354 *
355 * @param t Current time (in frames or seconds).
356 * @return The correct value.
357 */
358static qreal easeOutCirc(qreal t)
359{
360 t-= qreal(1.0);
361 return ::sqrt(1 - t* t);
362}
363
364/**
365 * Easing equation function for a circular (sqrt(1-t^2)) easing in/out: acceleration until halfway, then deceleration.
366 *
367 * @param t Current time (in frames or seconds).
368 * @return The correct value.
369 */
370static qreal easeInOutCirc(qreal t)
371{
372 t*=qreal(2.0);
373 if (t < 1) {
374 return -0.5 * (::sqrt(1 - t*t) - 1);
375 } else {
376 t -= qreal(2.0);
377 return 0.5 * (::sqrt(1 - t*t) + 1);
378 }
379}
380
381/**
382 * Easing equation function for a circular (sqrt(1-t^2)) easing out/in: deceleration until halfway, then acceleration.
383 *
384 * @param t Current time (in frames or seconds).
385 * @return The correct value.
386 */
387static qreal easeOutInCirc(qreal t)
388{
389 if (t < 0.5) return easeOutCirc (2*t)/2;
390 return easeInCirc(2*t - 1)/2 + 0.5;
391}
392
393static qreal easeInElastic_helper(qreal t, qreal b, qreal c, qreal d, qreal a, qreal p)
394{
395 if (t==0) return b;
396 qreal t_adj = (qreal)t / (qreal)d;
397 if (t_adj==1) return b+c;
398
399 qreal s;
400 if(a < ::qFabs(c)) {
401 a = c;
402 s = p / 4.0f;
403 } else {
404 s = p / (2 * M_PI) * ::qAsin(c / a);
405 }
406
407 t_adj -= 1.0f;
408 return -(a*::qPow(2.0f,10*t_adj) * ::qSin( (t_adj*d-s)*(2*M_PI)/p )) + b;
409}
410
411/**
412 * Easing equation function for an elastic (exponentially decaying sine wave) easing in: accelerating from zero velocity.
413 *
414 * @param t Current time (in frames or seconds).
415 * @param a Amplitude.
416 * @param p Period.
417 * @return The correct value.
418 */
419static qreal easeInElastic(qreal t, qreal a, qreal p)
420{
421 return easeInElastic_helper(t, 0, 1, 1, a, p);
422}
423
424static qreal easeOutElastic_helper(qreal t, qreal /*b*/, qreal c, qreal /*d*/, qreal a, qreal p)
425{
426 if (t==0) return 0;
427 if (t==1) return c;
428
429 qreal s;
430 if(a < c) {
431 a = c;
432 s = p / 4.0f;
433 } else {
434 s = p / (2 * M_PI) * ::qAsin(c / a);
435 }
436
437 return (a*::qPow(2.0f,-10*t) * ::qSin( (t-s)*(2*M_PI)/p ) + c);
438}
439
440/**
441 * Easing equation function for an elastic (exponentially decaying sine wave) easing out: decelerating to zero velocity.
442 *
443 * @param t Current time (in frames or seconds).
444 * @param a Amplitude.
445 * @param p Period.
446 * @return The correct value.
447 */
448static qreal easeOutElastic(qreal t, qreal a, qreal p)
449{
450 return easeOutElastic_helper(t, 0, 1, 1, a, p);
451}
452
453/**
454 * Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: acceleration until halfway, then deceleration.
455 *
456 * @param t Current time (in frames or seconds).
457 * @param a Amplitude.
458 * @param p Period.
459 * @return The correct value.
460 */
461static qreal easeInOutElastic(qreal t, qreal a, qreal p)
462{
463 if (t==0) return 0.0;
464 t*=2.0;
465 if (t==2) return 1.0;
466
467 qreal s;
468 if(a < 1.0) {
469 a = 1.0;
470 s = p / 4.0f;
471 } else {
472 s = p / (2 * M_PI) * ::qAsin(1.0 / a);
473 }
474
475 if (t < 1) return -.5*(a*::qPow(2.0f,10*(t-1)) * ::qSin( (t-1-s)*(2*M_PI)/p ));
476 return a*::qPow(2.0f,-10*(t-1)) * ::qSin( (t-1-s)*(2*M_PI)/p )*.5 + 1.0;
477}
478
479/**
480 * Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: deceleration until halfway, then acceleration.
481 *
482 * @param t Current time (in frames or seconds).
483 * @param a Amplitude.
484 * @param p Period.
485 * @return The correct value.
486 */
487static qreal easeOutInElastic(qreal t, qreal a, qreal p)
488{
489 if (t < 0.5) return easeOutElastic_helper(t*2, 0, 0.5, 1.0, a, p);
490 return easeInElastic_helper(2*t - 1.0, 0.5, 0.5, 1.0, a, p);
491}
492
493/**
494 * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
495 *
496 * @param t Current time (in frames or seconds).
497 * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
498 * @return The correct value.
499 */
500static qreal easeInBack(qreal t, qreal s)
501{
502 return t*t*((s+1)*t - s);
503}
504
505/**
506 * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: decelerating to zero velocity.
507 *
508 * @param t Current time (in frames or seconds).
509 * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
510 * @return The correct value.
511 */
512static qreal easeOutBack(qreal t, qreal s)
513{
514 t-= qreal(1.0);
515 return t*t*((s+1)*t+ s) + 1;
516}
517
518/**
519 * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
520 *
521 * @param t Current time (in frames or seconds).
522 * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
523 * @return The correct value.
524 */
525static qreal easeInOutBack(qreal t, qreal s)
526{
527 t *= 2.0;
528 if (t < 1) {
529 s *= 1.525f;
530 return 0.5*(t*t*((s+1)*t - s));
531 } else {
532 t -= 2;
533 s *= 1.525f;
534 return 0.5*(t*t*((s+1)*t+ s) + 2);
535 }
536}
537
538/**
539 * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
540 *
541 * @param t Current time (in frames or seconds).
542 * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
543 * @return The correct value.
544 */
545static qreal easeOutInBack(qreal t, qreal s)
546{
547 if (t < 0.5) return easeOutBack (2*t, s)/2;
548 return easeInBack(2*t - 1, s)/2 + 0.5;
549}
550
551static qreal easeOutBounce_helper(qreal t, qreal c, qreal a)
552{
553 if (t == 1.0) return c;
554 if (t < (4/11.0)) {
555 return c*(7.5625*t*t);
556 } else if (t < (8/11.0)) {
557 t -= (6/11.0);
558 return -a * (1. - (7.5625*t*t + .75)) + c;
559 } else if (t < (10/11.0)) {
560 t -= (9/11.0);
561 return -a * (1. - (7.5625*t*t + .9375)) + c;
562 } else {
563 t -= (21/22.0);
564 return -a * (1. - (7.5625*t*t + .984375)) + c;
565 }
566}
567
568/**
569 * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating to zero velocity.
570 *
571 * @param t Current time (in frames or seconds).
572 * @param a Amplitude.
573 * @return The correct value.
574 */
575static qreal easeOutBounce(qreal t, qreal a)
576{
577 return easeOutBounce_helper(t, 1, a);
578}
579
580/**
581 * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity.
582 *
583 * @param t Current time (in frames or seconds).
584 * @param a Amplitude.
585 * @return The correct value.
586 */
587static qreal easeInBounce(qreal t, qreal a)
588{
589 return 1.0 - easeOutBounce_helper(1.0-t, 1.0, a);
590}
591
592
593/**
594 * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration.
595 *
596 * @param t Current time (in frames or seconds).
597 * @param a Amplitude.
598 * @return The correct value.
599 */
600static qreal easeInOutBounce(qreal t, qreal a)
601{
602 if (t < 0.5) return easeInBounce (2*t, a)/2;
603 else return (t == 1.0) ? 1.0 : easeOutBounce (2*t - 1, a)/2 + 0.5;
604}
605
606/**
607 * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration.
608 *
609 * @param t Current time (in frames or seconds).
610 * @param a Amplitude.
611 * @return The correct value.
612 */
613static qreal easeOutInBounce(qreal t, qreal a)
614{
615 if (t < 0.5) return easeOutBounce_helper(t*2, 0.5, a);
616 return 1.0 - easeOutBounce_helper (2.0-2*t, 0.5, a);
617}
618
619static inline qreal qt_sinProgress(qreal value)
620{
621 return qSin((value * M_PI) - M_PI_2) / 2 + qreal(0.5);
622}
623
624static inline qreal qt_smoothBeginEndMixFactor(qreal value)
625{
626 return qMin(qMax(1 - value * 2 + qreal(0.3), qreal(0.0)), qreal(1.0));
627}
628
629// SmoothBegin blends Smooth and Linear Interpolation.
630// Progress 0 - 0.3 : Smooth only
631// Progress 0.3 - ~ 0.5 : Mix of Smooth and Linear
632// Progress ~ 0.5 - 1 : Linear only
633
634/**
635 * Easing function that starts growing slowly, then increases in speed. At the end of the curve the speed will be constant.
636 */
637static qreal easeInCurve(qreal t)
638{
639 const qreal sinProgress = qt_sinProgress(t);
640 const qreal mix = qt_smoothBeginEndMixFactor(t);
641 return sinProgress * mix + t * (1 - mix);
642}
643
644/**
645 * Easing function that starts growing steadily, then ends slowly. The speed will be constant at the beginning of the curve.
646 */
647static qreal easeOutCurve(qreal t)
648{
649 const qreal sinProgress = qt_sinProgress(t);
650 const qreal mix = qt_smoothBeginEndMixFactor(1 - t);
651 return sinProgress * mix + t * (1 - mix);
652}
653
654/**
655 * Easing function where the value grows sinusoidally. Note that the calculated end value will be 0 rather than 1.
656 */
657static qreal easeSineCurve(qreal t)
658{
659 return (qSin(((t * M_PI * 2)) - M_PI_2) + 1) / 2;
660}
661
662/**
663 * Easing function where the value grows cosinusoidally. Note that the calculated start value will be 0.5 and the end value will be 0.5
664 * contrary to the usual 0 to 1 easing curve.
665 */
666static qreal easeCosineCurve(qreal t)
667{
668 return (qCos(((t * M_PI * 2)) - M_PI_2) + 1) / 2;
669}
670
671