Merge pull request #26350 from jjd-uk/estuary_media_align
[xbmc.git] / xbmc / guilib / Tween.h
blob6aea30238e776ce0dc59b65d34d6003c1a67e4a8
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #pragma once
11 ///////////////////////////////////////////////////////////////////////
12 // Tween.h
13 // A couple of tweening classes implemented in C++.
14 // ref: http://www.robertpenner.com/easing/
16 // Author: d4rk <d4rk@xbmc.org>
17 ///////////////////////////////////////////////////////////////////////
20 ///////////////////////////////////////////////////////////////////////
21 // Current list of classes:
23 // LinearTweener
24 // QuadTweener
25 // CubicTweener
26 // SineTweener
27 // CircleTweener
28 // BackTweener
29 // BounceTweener
30 // ElasticTweener
32 ///////////////////////////////////////////////////////////////////////
34 #include <math.h>
36 #ifndef M_PI
37 #define M_PI 3.14159265358979323846
38 #endif
40 enum TweenerType
42 EASE_IN,
43 EASE_OUT,
44 EASE_INOUT
48 class Tweener
50 public:
51 explicit Tweener(TweenerType tweenerType = EASE_OUT) { m_tweenerType = tweenerType; }
52 virtual ~Tweener() = default;
54 void SetEasing(TweenerType type) { m_tweenerType = type; }
55 virtual float Tween(float time, float start, float change, float duration)=0;
56 virtual bool HasResumePoint() const { return m_tweenerType == EASE_INOUT; }
57 protected:
58 TweenerType m_tweenerType;
62 class LinearTweener : public Tweener
64 public:
65 float Tween(float time, float start, float change, float duration) override
67 return change * time / duration + start;
69 bool HasResumePoint() const override { return false; }
73 class QuadTweener : public Tweener
75 public:
76 explicit QuadTweener(float a = 1.0f) { _a=a; }
77 float Tween(float time, float start, float change, float duration) override
79 switch (m_tweenerType)
81 case EASE_IN:
82 time /= duration;
83 return change * time * (_a * time + 1 - _a) + start;
84 break;
86 case EASE_OUT:
87 time /= duration;
88 return -change * time * (_a * time - 1 - _a) + start;
89 break;
91 case EASE_INOUT:
92 time /= duration/2;
93 if (time < 1)
94 return (change) * time * (_a * time + 1 - _a) + start;
95 time--;
96 return (-change) * time * (_a * time - 1 - _a) + start;
97 break;
99 return change * time * time + start;
101 private:
102 float _a;
106 class CubicTweener : public Tweener
108 public:
109 float Tween(float time, float start, float change, float duration) override
111 switch (m_tweenerType)
113 case EASE_IN:
114 time /= duration;
115 return change * time * time * time + start;
116 break;
118 case EASE_OUT:
119 time /= duration;
120 time--;
121 return change * (time * time * time + 1) + start;
122 break;
124 case EASE_INOUT:
125 time /= duration/2;
126 if (time < 1)
127 return (change/2) * time * time * time + start;
128 time-=2;
129 return (change/2) * (time * time * time + 2) + start;
130 break;
132 return change * time * time + start;
136 class CircleTweener : public Tweener
138 public:
139 float Tween(float time, float start, float change, float duration) override
141 switch (m_tweenerType)
143 case EASE_IN:
144 time /= duration;
145 return (-change) * (sqrt(1 - time * time) - 1) + start;
146 break;
148 case EASE_OUT:
149 time /= duration;
150 time--;
151 return change * sqrt(1 - time * time) + start;
152 break;
154 case EASE_INOUT:
155 time /= duration/2;
156 if (time < 1)
157 return (-change/2) * (sqrt(1 - time * time) - 1) + start;
158 time-=2;
159 return change/2 * (sqrt(1 - time * time) + 1) + start;
160 break;
162 return change * sqrt(1 - time * time) + start;
166 class BackTweener : public Tweener
168 public:
169 explicit BackTweener(float s=1.70158) { _s=s; }
171 float Tween(float time, float start, float change, float duration) override
173 float s = _s;
174 switch (m_tweenerType)
176 case EASE_IN:
177 time /= duration;
178 return change * time * time * ((s + 1) * time - s) + start;
179 break;
181 case EASE_OUT:
182 time /= duration;
183 time--;
184 return change * (time * time * ((s + 1) * time + s) + 1) + start;
185 break;
187 case EASE_INOUT:
188 time /= duration/2;
189 s*=(1.525f);
190 if ((time ) < 1)
192 return (change/2) * (time * time * ((s + 1) * time - s)) + start;
194 time-=2;
195 return (change/2) * (time * time * ((s + 1) * time + s) + 2) + start;
196 break;
198 return change * ((time-1) * time * ((s + 1) * time + s) + 1) + start;
200 private:
201 float _s;
206 class SineTweener : public Tweener
208 public:
209 float Tween(float time, float start, float change, float duration) override
211 time /= duration;
212 switch (m_tweenerType)
214 case EASE_IN:
215 return change * (1 - cos(time * static_cast<float>(M_PI) / 2.0f)) + start;
216 break;
218 case EASE_OUT:
219 return change * sin(time * static_cast<float>(M_PI) / 2.0f) + start;
220 break;
222 case EASE_INOUT:
223 return change / 2 * (1 - cos(static_cast<float>(M_PI) * time)) + start;
224 break;
226 return (change / 2) * (1 - cos(static_cast<float>(M_PI) * time)) + start;
231 class BounceTweener : public Tweener
233 public:
234 float Tween(float time, float start, float change, float duration) override
236 switch (m_tweenerType)
238 case EASE_IN:
239 return (change - easeOut(duration - time, 0, change, duration)) + start;
240 break;
242 case EASE_OUT:
243 return easeOut(time, start, change, duration);
244 break;
246 case EASE_INOUT:
247 if (time < duration/2)
248 return (change - easeOut (duration - (time * 2), 0, change, duration) + start) * .5f + start;
249 else
250 return (easeOut (time * 2 - duration, 0, change, duration) * .5f + change * .5f) + start;
251 break;
254 return easeOut(time, start, change, duration);
256 protected:
257 static float easeOut(float time, float start, float change, float duration)
259 time /= duration;
260 if (time < (1 / 2.75f))
262 return change * (7.5625f * time * time) + start;
264 else if (time < (2 / 2.75f))
266 time -= (1.5f/2.75f);
267 return change * (7.5625f * time * time + .75f) + start;
269 else if (time < (2.5f / 2.75f))
271 time -= (2.25f/2.75f);
272 return change * (7.5625f * time * time + .9375f) + start;
274 else
276 time -= (2.625f/2.75f);
277 return change * (7.5625f * time * time + .984375f) + start;
283 class ElasticTweener : public Tweener
285 public:
286 ElasticTweener(float a=0.0, float p=0.0) { _a=a; _p=p; }
288 float Tween(float time, float start, float change, float duration) override
290 switch (m_tweenerType)
292 case EASE_IN:
293 return easeIn(time, start, change, duration);
294 break;
296 case EASE_OUT:
297 return easeOut(time, start, change, duration);
298 break;
300 case EASE_INOUT:
301 return easeInOut(time, start, change, duration);
302 break;
304 return easeOut(time, start, change, duration);
306 protected:
307 float _a;
308 float _p;
310 float easeIn(float time, float start, float change, float duration) const
312 float s=0;
313 float a=_a;
314 float p=_p;
316 if (time==0)
317 return start;
318 time /= duration;
319 if (time==1)
320 return start + change;
321 if (!p)
322 p=duration*.3f;
323 if (!a || a < fabs(change))
325 a = change;
326 s = p / 4.0f;
328 else
330 s = p / (2 * static_cast<float>(M_PI)) * asin(change / a);
332 time--;
333 return -(a * pow(2.0f, 10 * time) *
334 sin((time * duration - s) * (2 * static_cast<float>(M_PI)) / p)) +
335 start;
338 float easeOut(float time, float start, float change, float duration) const
340 float s=0;
341 float a=_a;
342 float p=_p;
344 if (time==0)
345 return start;
346 time /= duration;
347 if (time==1)
348 return start + change;
349 if (!p)
350 p=duration*.3f;
351 if (!a || a < fabs(change))
353 a = change;
354 s = p / 4.0f;
356 else
358 s = p / (2 * static_cast<float>(M_PI)) * asin(change / a);
360 return (a * pow(2.0f, -10 * time) *
361 sin((time * duration - s) * (2 * static_cast<float>(M_PI)) / p)) +
362 change + start;
365 float easeInOut(float time, float start, float change, float duration) const
367 float s=0;
368 float a=_a;
369 float p=_p;
371 if (time==0)
372 return start;
373 time /= duration/2;
374 if (time==2)
375 return start + change;
376 if (!p)
377 p=duration*.3f*1.5f;
378 if (!a || a < fabs(change))
380 a = change;
381 s = p / 4.0f;
383 else
385 s = p / (2 * static_cast<float>(M_PI)) * asin(change / a);
388 if (time < 1)
390 time--;
391 return -.5f * (a * pow(2.0f, 10 * (time)) *
392 sin((time * duration - s) * (2 * static_cast<float>(M_PI)) / p)) +
393 start;
395 time--;
396 return a * pow(2.0f, -10 * (time)) *
397 sin((time * duration - s) * (2 * static_cast<float>(M_PI)) / p) * .5f +
398 change + start;