[cosmetics] update date in GPL header
[vuplus_xbmc] / xbmc / guilib / Tween.h
1 #ifndef __TWEEN_H__
2 #define __TWEEN_H__
3
4 /*
5  *      Copyright (C) 2005-2013 Team XBMC
6  *      http://www.xbmc.org
7  *
8  *  This Program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2, or (at your option)
11  *  any later version.
12  *
13  *  This Program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with XBMC; see the file COPYING.  If not, see
20  *  <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 ///////////////////////////////////////////////////////////////////////
25 // Tween.h
26 // A couple of tweening classes implemented in C++.
27 // ref: http://www.robertpenner.com/easing/
28 //
29 // Author: d4rk <d4rk@xbmc.org>
30 ///////////////////////////////////////////////////////////////////////
31
32
33 ///////////////////////////////////////////////////////////////////////
34 // Current list of classes:
35 //
36 // LinearTweener
37 // QuadTweener
38 // CubicTweener
39 // SineTweener
40 // CircleTweener
41 // BackTweener
42 // BounceTweener
43 // ElasticTweener
44 //
45 ///////////////////////////////////////////////////////////////////////
46
47 #include <math.h>
48
49 #ifndef M_PI
50 #define M_PI 3.14159265358979323846f
51 #endif
52
53 enum TweenerType
54 {
55   EASE_IN,
56   EASE_OUT,
57   EASE_INOUT
58 };
59
60
61 class Tweener
62 {
63 public:
64   Tweener(TweenerType tweenerType = EASE_OUT) { m_tweenerType = tweenerType; }
65   virtual ~Tweener() {};
66
67   void SetEasing(TweenerType type) { m_tweenerType = type; }
68   virtual float Tween(float time, float start, float change, float duration)=0;
69   virtual bool HasResumePoint() const { return m_tweenerType == EASE_INOUT; }
70 protected:
71   TweenerType m_tweenerType;
72 };
73
74
75 class LinearTweener : public Tweener
76 {
77 public:
78   virtual float Tween(float time, float start, float change, float duration)
79   {
80     return change * time / duration + start;
81   }
82   virtual bool HasResumePoint() const { return false; }
83 };
84
85
86 class QuadTweener : public Tweener
87 {
88 public:
89   QuadTweener(float a = 1.0f) { _a=a; }
90   virtual float Tween(float time, float start, float change, float duration)
91   {
92     switch (m_tweenerType)
93       {
94       case EASE_IN:
95         time /= duration;
96         return change * time * (_a * time + 1 - _a) + start;
97         break;
98
99       case EASE_OUT:
100         time /= duration;
101         return -change * time * (_a * time - 1 - _a) + start;
102         break;
103
104       case EASE_INOUT:
105         time /= duration/2;
106         if (time < 1)
107           return (change) * time * (_a * time + 1 - _a) + start;
108         time--;
109         return (-change) * time * (_a * time - 1 - _a) + start;
110         break;
111       }
112     return change * time * time + start;
113   }
114 private:
115   float _a;
116 };
117
118
119 class CubicTweener : public Tweener
120 {
121 public:
122   virtual float Tween(float time, float start, float change, float duration)
123   {
124     switch (m_tweenerType)
125       {
126       case EASE_IN:
127         time /= duration;
128         return change * time * time * time + start;
129         break;
130
131       case EASE_OUT:
132         time /= duration;
133         time--;
134         return change * (time * time * time + 1) + start;
135         break;
136
137       case EASE_INOUT:
138         time /= duration/2;
139         if (time < 1)
140           return (change/2) * time * time * time + start;
141         time-=2;
142         return (change/2) * (time * time * time + 2) + start;
143         break;
144       }
145     return change * time * time + start;
146   }
147 };
148
149 class CircleTweener : public Tweener
150 {
151 public:
152   virtual float Tween(float time, float start, float change, float duration)
153   {
154     switch (m_tweenerType)
155       {
156       case EASE_IN:
157         time /= duration;
158         return (-change) * (sqrt(1 - time * time) - 1) + start;
159         break;
160
161       case EASE_OUT:
162         time /= duration;
163         time--;
164         return change * sqrt(1 - time * time) + start;
165         break;
166
167       case EASE_INOUT:
168         time /= duration/2;
169         if (time  < 1)
170           return (-change/2) * (sqrt(1 - time * time) - 1) + start;
171         time-=2;
172         return change/2 * (sqrt(1 - time * time) + 1) + start;
173         break;
174       }
175     return change * sqrt(1 - time * time) + start;
176   }
177 };
178
179 class BackTweener : public Tweener
180 {
181 public:
182   BackTweener(float s=1.70158) { _s=s; }
183
184   virtual float Tween(float time, float start, float change, float duration)
185   {
186     float s = _s;
187     switch (m_tweenerType)
188       {
189       case EASE_IN:
190         time /= duration;
191         return change * time * time * ((s + 1) * time - s) + start;
192         break;
193
194       case EASE_OUT:
195         time /= duration;
196         time--;
197         return change * (time * time * ((s + 1) * time + s) + 1) + start;
198         break;
199
200       case EASE_INOUT:
201         time /= duration/2;
202         s*=(1.525f);
203         if ((time ) < 1)
204         {
205           return (change/2) * (time * time * ((s + 1) * time - s)) + start;
206         }
207         time-=2;
208         return (change/2) * (time * time * ((s + 1) * time + s) + 2) + start;
209         break;
210       }
211     return change * ((time-1) * time * ((s + 1) * time + s) + 1) + start;
212   }
213 private:
214   float _s;
215
216 };
217
218
219 class SineTweener : public Tweener
220 {
221 public:
222   virtual float Tween(float time, float start, float change, float duration)
223   {
224     time /= duration;
225     switch (m_tweenerType)
226       {
227       case EASE_IN:
228         return change * (1 - cos(time * M_PI / 2.0f)) + start;
229         break;
230
231       case EASE_OUT:
232         return change * sin(time * M_PI / 2.0f) + start;
233         break;
234
235       case EASE_INOUT:
236         return change/2 * (1 - cos(M_PI * time)) + start;
237         break;
238       }
239     return (change/2) * (1 - cos(M_PI * time)) + start;
240   }
241 };
242
243
244 class BounceTweener : public Tweener
245 {
246 public:
247   virtual float Tween(float time, float start, float change, float duration)
248   {
249     switch (m_tweenerType)
250       {
251       case EASE_IN:
252         return (change - easeOut(duration - time, 0, change, duration)) + start;
253         break;
254
255       case EASE_OUT:
256         return easeOut(time, start, change, duration);
257         break;
258
259       case EASE_INOUT:
260         if (time < duration/2)
261           return (change - easeOut (duration - (time * 2), 0, change, duration) + start) * .5f + start;
262         else
263           return (easeOut (time * 2 - duration, 0, change, duration) * .5f + change * .5f) + start;
264         break;
265       }
266
267     return easeOut(time, start, change, duration);
268   }
269 protected:
270   float easeOut(float time, float start, float change, float duration)
271   {
272     time /= duration;
273     if (time < (1/2.75)) {
274       return  change * (7.5625f * time * time) + start;
275     } else if (time < (2/2.75)) {
276       time -= (1.5f/2.75f);
277       return change * (7.5625f * time * time + .75f) + start;
278     } else if (time < (2.5/2.75)) {
279       time -= (2.25f/2.75f);
280       return change * (7.5625f * time * time + .9375f) + start;
281     } else {
282       time -= (2.625f/2.75f);
283       return change * (7.5625f * time * time + .984375f) + start;
284     }
285   }
286 };
287
288
289 class ElasticTweener : public Tweener
290 {
291 public:
292   ElasticTweener(float a=0.0, float p=0.0) { _a=a; _p=p; }
293
294   virtual float Tween(float time, float start, float change, float duration)
295   {
296     switch (m_tweenerType)
297       {
298       case EASE_IN:
299         return easeIn(time, start, change, duration);
300         break;
301
302       case EASE_OUT:
303         return easeOut(time, start, change, duration);
304         break;
305
306       case EASE_INOUT:
307         return easeInOut(time, start, change, duration);
308         break;
309       }
310     return easeOut(time, start, change, duration);
311   }
312 protected:
313   float _a;
314   float _p;
315
316   float easeIn(float time, float start, float change, float duration)
317   {
318     float s=0;
319     float a=_a;
320     float p=_p;
321
322     if (time==0)
323       return start;
324     time /= duration;
325     if (time==1)
326         return start + change;
327     if (!p)
328       p=duration*.3f;
329     if (!a || a < fabs(change))
330     {
331       a = change;
332       s = p / 4.0f;
333     }
334     else
335     {
336       s = p / (2 * M_PI) * asin (change / a);
337     }
338     time--;
339     return -(a * pow(2.0f, 10*time) * sin((time * duration - s) * (2 * M_PI) / p )) + start;
340   }
341
342   float easeOut(float time, float start, float change, float duration)
343   {
344     float s=0;
345     float a=_a;
346     float p=_p;
347
348     if (time==0)
349       return start;
350     time /= duration;
351     if (time==1)
352         return start + change;
353     if (!p)
354       p=duration*.3f;
355     if (!a || a < fabs(change))
356     {
357       a = change;
358       s = p / 4.0f;
359     }
360     else
361     {
362       s = p / (2 * M_PI) * asin (change / a);
363     }
364     return (a * pow(2.0f, -10*time) * sin((time * duration - s) * (2 * M_PI) / p )) + change + start;
365   }
366
367   float easeInOut(float time, float start, float change, float duration)
368   {
369     float s=0;
370     float a=_a;
371     float p=_p;
372
373     if (time==0)
374       return start;
375     time /= duration/2;
376     if (time==2)
377         return start + change;
378     if (!p)
379       p=duration*.3f*1.5f;
380     if (!a || a < fabs(change))
381     {
382       a = change;
383       s = p / 4.0f;
384     }
385     else
386     {
387       s = p / (2 * M_PI) * asin (change / a);
388     }
389
390     if (time < 1)
391     {
392       time--;
393       return -.5f * (a * pow(2.0f, 10 * (time)) * sin((time * duration - s) * (2 * M_PI) / p )) + start;
394     }
395     time--;
396     return a * pow(2.0f, -10 * (time)) * sin((time * duration-s) * (2 * M_PI) / p ) * .5f + change + start;
397   }
398 };
399
400
401
402 #endif // __TWEEN_H__