2 // The following code is based on Tweener for actionscript, http://code.google.com/p/tweener/
\r
4 //Disclaimer for Robert Penner's Easing Equations license:
\r
6 //TERMS OF USE - EASING EQUATIONS
\r
8 //Open source under the BSD License.
\r
10 //Copyright © 2001 Robert Penner
\r
11 //All rights reserved.
\r
13 //Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
\r
15 // * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
\r
16 // * 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.
\r
17 // * 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.
\r
19 //THIS 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.
\r
23 #include <boost/assign/list_of.hpp>
\r
24 #include <unordered_map>
\r
27 #include <functional>
\r
31 typedef std::function<double(double, double, double, double)> tweener_t;
\r
33 static const double PI = std::atan(1.0)*4.0;
\r
34 static const double H_PI = std::atan(1.0)*2.0;
\r
36 inline double ease_none (double t, double b, double c, double d)
\r
41 inline double ease_in_quad (double t, double b, double c, double d)
\r
43 return c*(t/=d)*t + b;
\r
46 inline double ease_out_quad (double t, double b, double c, double d)
\r
48 return -c *(t/=d)*(t-2) + b;
\r
51 inline double ease_in_out_quad (double t, double b, double c, double d)
\r
56 return -c/2 * ((--t)*(t-2) - 1) + b;
\r
59 inline double ease_out_in_quad (double t, double b, double c, double d)
\r
62 return ease_out_quad (t*2, b, c/2, d);
\r
64 return ease_in_quad((t*2)-d, b+c/2, c/2, d);
\r
67 inline double ease_in_cubic (double t, double b, double c, double d)
\r
69 return c*(t/=d)*t*t + b;
\r
72 inline double ease_out_cubic (double t, double b, double c, double d)
\r
74 return c*((t=t/d-1)*t*t + 1) + b;
\r
77 inline double ease_in_out_cubic (double t, double b, double c, double d)
\r
80 return c/2*t*t*t + b;
\r
82 return c/2*((t-=2)*t*t + 2) + b;
\r
85 inline double ease_out_in_cubic (double t, double b, double c, double d)
\r
87 if (t < d/2) return ease_out_cubic (t*2, b, c/2, d);
\r
88 return ease_in_cubic((t*2)-d, b+c/2, c/2, d);
\r
91 inline double ease_in_quart (double t, double b, double c, double d)
\r
93 return c*(t/=d)*t*t*t + b;
\r
96 inline double ease_out_quart (double t, double b, double c, double d)
\r
98 return -c * ((t=t/d-1)*t*t*t - 1) + b;
\r
101 inline double ease_in_out_quart (double t, double b, double c, double d)
\r
104 return c/2*t*t*t*t + b;
\r
106 return -c/2 * ((t-=2)*t*t*t - 2) + b;
\r
109 inline double ease_out_in_quart (double t, double b, double c, double d)
\r
112 return ease_out_quart (t*2, b, c/2, d);
\r
114 return ease_in_quart((t*2)-d, b+c/2, c/2, d);
\r
117 inline double ease_in_quint (double t, double b, double c, double d)
\r
119 return c*(t/=d)*t*t*t*t + b;
\r
122 inline double ease_out_quint (double t, double b, double c, double d)
\r
124 return c*((t=t/d-1)*t*t*t*t + 1) + b;
\r
127 inline double ease_in_out_quint (double t, double b, double c, double d)
\r
130 return c/2*t*t*t*t*t + b;
\r
132 return c/2*((t-=2)*t*t*t*t + 2) + b;
\r
135 inline double ease_out_in_quint (double t, double b, double c, double d)
\r
138 return ease_out_quint (t*2, b, c/2, d);
\r
140 return ease_in_quint((t*2)-d, b+c/2, c/2, d);
\r
143 inline double ease_in_sine (double t, double b, double c, double d)
\r
145 return -c * std::cos(t/d * (PI/2)) + c + b;
\r
148 inline double ease_out_sine (double t, double b, double c, double d)
\r
150 return c * std::sin(t/d * (PI/2)) + b;
\r
153 inline double ease_in_out_sine (double t, double b, double c, double d)
\r
155 return -c/2 * (std::cos(PI*t/d) - 1) + b;
\r
158 inline double ease_out_in_sine (double t, double b, double c, double d)
\r
161 return ease_out_sine (t*2, b, c/2, d);
\r
163 return ease_in_sine((t*2)-d, b+c/2, c/2, d);
\r
166 inline double ease_in_expo (double t, double b, double c, double d)
\r
168 return (t==0) ? b : c * std::pow(2, 10 * (t/d - 1)) + b - c * 0.001;
\r
171 inline double ease_out_expo (double t, double b, double c, double d)
\r
173 return (t==d) ? b+c : c * 1.001 * (-std::pow(2, -10 * t/d) + 1) + b;
\r
176 inline double ease_in_out_expo (double t, double b, double c, double d)
\r
183 return c/2 * std::pow(2, 10 * (t - 1)) + b - c * 0.0005;
\r
185 return c/2 * 1.0005 * (-std::pow(2, -10 * --t) + 2) + b;
\r
188 inline double ease_out_in_expo (double t, double b, double c, double d) {
\r
190 return ease_out_expo (t*2, b, c/2, d);
\r
192 return ease_in_expo((t*2)-d, b+c/2, c/2, d);
\r
195 inline double ease_in_circ (double t, double b, double c, double d)
\r
197 return -c * (std::sqrt(1 - (t/=d)*t) - 1) + b;
\r
200 inline double ease_out_circ (double t, double b, double c, double d)
\r
202 return c * std::sqrt(1 - (t=t/d-1)*t) + b;
\r
205 inline double ease_in_out_circ (double t, double b, double c, double d)
\r
208 return -c/2 * (std::sqrt(1 - t*t) - 1) + b;
\r
210 return c/2 * (std::sqrt(1 - (t-=2)*t) + 1) + b;
\r
213 inline double ease_out_in_circ (double t, double b, double c, double d)
\r
215 if (t < d/2) return ease_out_circ(t*2, b, c/2, d);
\r
216 return ease_in_circ((t*2)-d, b+c/2, c/2, d);
\r
219 inline double ease_in_elastic (double t, double b, double c, double d)
\r
221 if (t==0) return b;
\r
222 if ((t/=d)==1) return b+c;
\r
223 //var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period;
\r
225 //var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;
\r
229 if (a == 0.0 || a < std::abs(c))
\r
235 s = p/(2*PI) * std::asin (c/a);
\r
237 return -(a*std::pow(2,10*(t-=1)) * std::sin( (t*d-s)*(2*PI)/p )) + b;
\r
240 inline double ease_out_elastic (double t, double b, double c, double d)
\r
246 //var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period;
\r
248 //var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;
\r
252 if (a == 0.0 || a < std::abs(c))
\r
258 s = p/(2*PI) * std::asin (c/a);
\r
260 return (a*std::pow(2,-10*t) * std::sin( (t*d-s)*(2*PI)/p ) + c + b);
\r
263 inline double ease_in_out_elastic (double t, double b, double c, double d)
\r
269 //var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*(.3*1.5) : p_params.period;
\r
271 //var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;
\r
272 double p = d*0.3*1.5;
\r
275 if (a == 0.0 || a < std::abs(c))
\r
281 s = p/(2*PI) * std::asin (c/a);
\r
284 return -.5*(a*std::pow(2,10*(t-=1)) * std::sin( (t*d-s)*(2*PI)/p )) + b;
\r
286 return a*std::pow(2,-10*(t-=1)) * std::sin( (t*d-s)*(2*PI)/p )*.5 + c + b;
\r
289 inline double ease_out_in_elastic (double t, double b, double c, double d)
\r
291 if (t < d/2) return ease_out_elastic (t*2, b, c/2, d);
\r
292 return ease_in_elastic((t*2)-d, b+c/2, c/2, d);
\r
295 inline double ease_in_back (double t, double b, double c, double d)
\r
297 //var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;
\r
298 double s = 1.70158;
\r
299 return c*(t/=d)*t*((s+1)*t - s) + b;
\r
302 inline double ease_out_back (double t, double b, double c, double d)
\r
304 //var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;
\r
305 double s = 1.70158;
\r
306 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
\r
309 inline double ease_in_out_back (double t, double b, double c, double d)
\r
311 //var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;
\r
312 double s = 1.70158;
\r
313 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
\r
314 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
\r
318 inline double ease_out_int_back (double t, double b, double c, double d)
\r
320 if (t < d/2) return ease_out_back (t*2, b, c/2, d);
\r
321 return ease_in_back((t*2)-d, b+c/2, c/2, d);
\r
325 inline double ease_out_bounce (double t, double b, double c, double d)
\r
327 if ((t/=d) < (1/2.75))
\r
328 return c*(7.5625*t*t) + b;
\r
329 else if (t < (2/2.75))
\r
330 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
\r
331 else if (t < (2.5/2.75))
\r
332 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
\r
334 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
\r
337 inline double ease_in_bounce (double t, double b, double c, double d)
\r
339 return c - ease_out_bounce (d-t, 0, c, d) + b;
\r
342 inline double ease_in_out_bounce (double t, double b, double c, double d)
\r
344 if (t < d/2) return ease_in_bounce (t*2, 0, c, d) * .5 + b;
\r
345 else return ease_out_bounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
\r
349 inline double ease_out_in_bounce (double t, double b, double c, double d)
\r
351 if (t < d/2) return ease_out_bounce (t*2, b, c/2, d);
\r
352 return ease_in_bounce((t*2)-d, b+c/2, c/2, d);
\r
355 inline tweener_t get_tweener(std::wstring name = L"linear")
\r
357 std::transform(name.begin(), name.end(), name.begin(), std::tolower);
\r
359 static const std::unordered_map<std::wstring, tweener_t> tweens = boost::assign::map_list_of
\r
361 (L"linear", ease_none )
\r
362 (L"easenone", ease_none )
\r
363 (L"easeinquad", ease_in_quad )
\r
364 (L"easeoutquad", ease_out_quad )
\r
365 (L"easeinoutquad", ease_in_out_quad )
\r
366 (L"easeoutinquad", ease_out_in_quad )
\r
367 (L"easeincubic", ease_in_cubic )
\r
368 (L"easeoutcubic", ease_out_cubic )
\r
369 (L"easeinoutcubic", ease_in_out_cubic )
\r
370 (L"easeoutincubic", ease_out_in_cubic )
\r
371 (L"easeinquart", ease_in_quart )
\r
372 (L"easeoutquart", ease_out_quart )
\r
373 (L"easeinoutquart", ease_in_out_quart )
\r
374 (L"easeoutinquart", ease_out_in_quart )
\r
375 (L"easeinquint", ease_in_quint )
\r
376 (L"easeoutquint", ease_out_quint )
\r
377 (L"easeinoutquint", ease_in_out_quint )
\r
378 (L"easeoutinquint", ease_out_in_quint )
\r
379 (L"easeinsine", ease_in_sine )
\r
380 (L"easeoutsine", ease_out_sine )
\r
381 (L"easeinoutsine", ease_in_out_sine )
\r
382 (L"easeoutinsine", ease_out_in_sine )
\r
383 (L"easeinexpo", ease_in_expo )
\r
384 (L"easeoutexpo", ease_out_expo )
\r
385 (L"easeinoutexpo", ease_in_out_expo )
\r
386 (L"easeoutinexpo", ease_out_in_expo )
\r
387 (L"easeincirc", ease_in_circ )
\r
388 (L"easeoutcirc", ease_out_circ )
\r
389 (L"easeinoutcirc", ease_in_out_circ )
\r
390 (L"easeoutincirc", ease_out_in_circ )
\r
391 (L"easeinelastic", ease_in_elastic )
\r
392 (L"easeoutelastic", ease_out_elastic )
\r
393 (L"easeinoutelastic", ease_in_out_elastic)
\r
394 (L"easeoutinelastic", ease_out_in_elastic)
\r
395 (L"easeinback", ease_in_back )
\r
396 (L"easeoutback", ease_out_back )
\r
397 (L"easeinoutback", ease_in_out_back )
\r
398 (L"easeoutintback", ease_out_int_back )
\r
399 (L"easeoutbounce", ease_out_bounce )
\r
400 (L"easeinbounce", ease_in_bounce )
\r
401 (L"easeinoutbounce", ease_in_out_bounce )
\r
402 (L"easeoutinbounce", ease_out_in_bounce );
\r
404 auto it = tweens.find(name);
\r
405 if(it == tweens.end())
\r
407 CASPAR_LOG(warning) << L"Invalid tween: " << name << L" fallback to \"linear\".";
\r
408 it = tweens.find(L"linear");
\r