[elm_animator.c]
[framework/uifw/elementary.git] / src / lib / elm_animator.c
1 #include <Elementary.h>
2
3 /**
4  * @addtogroup Animator Animator
5  * @ingroup Elementary
6  *
7  * Support basic animation functions for Evas_Object
8 */
9
10 struct _Animator
11 {
12    Evas_Object *parent;
13    Ecore_Animator *animator;
14    double begin_time;
15    double cur_time;
16    double duration;
17    unsigned int repeat_cnt;
18    unsigned int cur_repeat_cnt;
19    double (*curve_op) (double frame);
20    void (*animator_op) (void *data, Elm_Animator *animator, double frame);
21    void *animator_arg;
22    void (*completion_op) (void *data);
23    void *completion_arg;
24    Eina_Bool auto_reverse:1;
25    Eina_Bool on_animating:1;
26 };
27
28 static double _animator_curve_linear(double frame);
29
30 static double _animator_curve_in_out(double frame);
31
32 static double _animator_curve_in(double frame);
33
34 static double _animator_curve_out(double frame);
35
36 static unsigned int _animator_compute_reverse_repeat_count(unsigned int cnt);
37
38 static unsigned int _animator_compute_no_reverse_repeat_count(unsigned int cnt);
39
40 static int _animator_animate_cb(void *data);
41
42 static void _delete_animator(Elm_Animator *animator);
43
44 static void _animator_parent_del(void *data);
45
46 static unsigned int
47 _animator_compute_reverse_repeat_count(unsigned int cnt)
48 {
49    return ((cnt + 1) * 2) - 1;
50 }
51
52 static unsigned int
53 _animator_compute_no_reverse_repeat_count(unsigned int cnt)
54 {
55    return cnt / 2;
56 }
57
58 static double
59 _animator_curve_linear(double frame)
60 {
61    return frame;
62 }
63
64 static double
65 _animator_curve_in_out(double frame)
66 {
67    if (frame < 0.5)
68       return _animator_curve_out(frame * 2) * 0.5;
69    else
70       return (_animator_curve_in(frame * 2 - 1) * 0.5) + 0.5;
71 }
72
73 static double
74 _animator_curve_in(double frame)
75 {
76    return sqrt(1 - pow(frame - 1, 2));
77 }
78
79 static double
80 _animator_curve_out(double frame)
81 {
82    return 1 - sqrt(1 - pow(frame, 2));
83 }
84
85 static void
86 _delete_animator(Elm_Animator *animator)
87 {
88    if (animator->animator)
89      {
90     ecore_animator_del(animator->animator);
91         animator->animator = NULL;
92      }
93 }
94
95 static int
96 _animator_animate_cb(void *data)
97 {
98    Elm_Animator *animator = (Elm_Animator *) data;
99
100    animator->cur_time = ecore_loop_time_get();
101    double elapsed_time = animator->cur_time - animator->begin_time;
102
103    //TODO: HOW TO MAKE IT PRECIOUS TIME? -> Use Interpolation!!
104    if (elapsed_time > animator->duration)
105       elapsed_time = animator->duration;
106
107    double frame = animator->curve_op(elapsed_time / animator->duration);
108
109    //Reverse?
110    if (animator->auto_reverse)
111      {
112         if ((animator->cur_repeat_cnt % 2) == 0)
113            frame = 1 - frame;
114      }
115
116    if (animator->duration > 0)
117       animator->animator_op(animator->animator_arg, animator, frame);
118
119    //Not end. Keep going.
120    if (elapsed_time < animator->duration)
121       return ECORE_CALLBACK_RENEW;
122
123    //Repeat and reverse and time done! 
124    if (animator->cur_repeat_cnt == 0)
125      {
126         animator->on_animating = EINA_FALSE;
127         _delete_animator(animator);
128         if (animator->completion_op)
129            animator->completion_op(animator->completion_arg);
130         return ECORE_CALLBACK_CANCEL;
131      }
132
133    //Repeat Case
134    --animator->cur_repeat_cnt;
135    animator->begin_time = ecore_loop_time_get();
136
137    return ECORE_CALLBACK_RENEW;
138 }
139
140 static void
141 _animator_parent_del(void *data)
142 {
143    elm_animator_del(data);
144 }
145
146 /**
147  * Get the value of reverse mode. 
148  *
149  * @param animator Animator object
150  * @return EINA_TRUE is reverse mode 
151  *
152  * @ingroup Animator 
153  */
154 EAPI Eina_Bool
155 elm_animator_auto_reverse_get(Elm_Animator *animator)
156 {
157    if (!animator)
158       return EINA_FALSE;
159    return animator->auto_reverse;
160 }
161
162 /**
163  * Get the value of repeat count.
164  *
165  * @param animator Animator object
166  * @return Repeat count
167  *
168  * @ingroup Animator 
169  */
170 EAPI unsigned int
171 elm_animator_repeat_get(Elm_Animator *animator)
172 {
173    if (!animator)
174       return EINA_FALSE;
175    return animator->repeat_cnt;
176 }
177
178 /**
179  * Set auto reverse function.  
180  *
181  * @param animator Animator object
182  * @param reverse Reverse or not
183  * 
184  * @ingroup Animator 
185  */
186 EAPI void
187 elm_animator_auto_reverse_set(Elm_Animator *animator, Eina_Bool reverse)
188 {
189    if (!animator)
190       return;
191    if (animator->auto_reverse == reverse)
192       return;
193    animator->auto_reverse = reverse;
194    if (reverse)
195       animator->repeat_cnt =
196          _animator_compute_reverse_repeat_count(animator->repeat_cnt);
197    else
198       animator->repeat_cnt =
199          _animator_compute_no_reverse_repeat_count(animator->repeat_cnt);
200 }
201
202 /**
203  * Set the animation acceleration style. 
204  *
205  * @param animator Animator object
206  * @param cs Curve style. Default is ELM_ANIMATOR_CURVE_LINEAR 
207  *
208  * @ingroup Animator
209  */
210 EAPI void
211 elm_animator_curve_style_set(Elm_Animator *animator,
212                              Elm_Animator_Curve_Style cs)
213 {
214    if (!animator)
215       return;
216
217    switch (cs)
218      {
219      case ELM_ANIMATOR_CURVE_LINEAR:
220         animator->curve_op = _animator_curve_linear;
221         break;
222      case ELM_ANIMATOR_CURVE_IN_OUT:
223         animator->curve_op = _animator_curve_in_out;
224         break;
225      case ELM_ANIMATOR_CURVE_IN:
226         animator->curve_op = _animator_curve_in;
227         break;
228      case ELM_ANIMATOR_CURVE_OUT:
229         animator->curve_op = _animator_curve_out;
230         break;
231      default:
232         animator->curve_op = _animator_curve_linear;
233         break;
234      }
235 }
236
237 /**
238  * Set the operation duration.  
239  *
240  * @param animator Animator object
241  * @param duration Duration in second 
242  *
243  * @ingroup Animator
244  */
245 EAPI void
246 elm_animator_duration_set(Elm_Animator *animator, double duration)
247 {
248    if (!animator)
249       return;
250    if (animator->on_animating)
251       return;
252    animator->duration = duration;
253 }
254
255 /**
256  * Set the callback function for animator operation.  
257  * The range of callback function frame data is to 0 ~ 1
258  * User can refer this frame value for one's animation frame data. 
259  * @param animator Animator object
260  * @param op Callback function pointer 
261  * @param data Callback function user argument 
262  *
263  * @ingroup Animator
264  */
265 EAPI void
266 elm_animator_operation_callback_set(Elm_Animator *animator,
267                                     void (*func) (void *data,
268                                                   Elm_Animator *animator,
269                                                   double frame), void *data)
270 {
271    if (!animator)
272       return;
273    if (animator->on_animating)
274       return;
275    animator->animator_op = func;
276    animator->animator_arg = data;
277 }
278
279 /**
280  * Add new animator. 
281  *
282  * @param parent Parent object
283  * @return animator object 
284  *
285  * @ingroup Animator
286  */
287 EAPI Elm_Animator *
288 elm_animator_add(Evas_Object *parent)
289 {
290    Elm_Animator *animator = calloc(1, sizeof(Elm_Animator));
291
292    if (!animator)
293       return NULL;
294    elm_animator_auto_reverse_set(animator, EINA_FALSE);
295    elm_animator_curve_style_set(animator, ELM_ANIMATOR_CURVE_LINEAR);
296
297    if (parent)
298       evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
299                                      _animator_parent_del, animator);
300
301    animator->parent = parent;
302
303    return animator;
304 }
305
306 /**
307  * Get the status for the animator operation.
308  *
309  * @param animator Animator object 
310  * @return EINA_TRUE is animator is operating. 
311  *
312  * @ingroup Animator
313  */
314 EAPI Eina_Bool
315 elm_animator_operating_get(Elm_Animator *animator)
316 {
317    if (!animator)
318       return EINA_FALSE;
319    return animator->on_animating;
320 }
321
322 /**
323  * Delete animator. 
324  *
325  * @param animator Animator object 
326  *
327  * @ingroup Animator
328  */
329 EAPI void
330 elm_animator_del(Elm_Animator *animator)
331 {
332    if (!animator)
333       return;
334    _delete_animator(animator);
335    
336    if(animator->parent) 
337         evas_object_event_callback_del(animator->parent, EVAS_CALLBACK_DEL, _animator_parent_del);
338    free(animator);
339 }
340
341 /**
342  * Set the callback function for the animator end.  
343  *
344  * @param  animator Animator object 
345  * @param  op Callback function pointer
346  * @param  data Callback function user argument 
347  *
348  * @ingroup Animator
349  */
350 EAPI void
351 elm_animator_completion_callback_set(Elm_Animator *animator,
352                                      void (*func) (void *data), void *data)
353 {
354    if (!animator)
355       return;
356    if (animator->on_animating)
357       return;
358    animator->completion_op = func;
359    animator->completion_arg = data;
360 }
361
362 /**
363  * Stop animator.
364  *
365  * @param animator Animator object 
366  *
367  * @ingroup Animator
368  */
369 EAPI void
370 elm_animator_stop(Elm_Animator *animator)
371 {
372    if (!animator)
373       return;
374    animator->on_animating = EINA_FALSE;
375    _delete_animator(animator);
376 }
377
378 /**
379  * Set the animator repeat count.
380  *
381  * @param  animator Animator object
382  * @param  repeat_cnt Repeat count
383  *
384  * @ingroup Animator
385  */
386 EAPI void
387 elm_animator_repeat_set(Elm_Animator *animator, unsigned int repeat_cnt)
388 {
389    if (!animator)
390       return;
391    if (!animator->auto_reverse)
392       animator->repeat_cnt = repeat_cnt;
393    else
394       animator->repeat_cnt = _animator_compute_reverse_repeat_count(repeat_cnt);
395 }
396
397 /**
398  * Animate now.
399  *
400  * @param animator Animator object
401  *
402  * @ingroup Animator
403  */
404 EAPI void
405 elm_animator_animate(Elm_Animator *animator)
406 {
407    if (!animator)
408       return;
409    if (!animator->animator_op)
410       return;
411    animator->begin_time = ecore_loop_time_get();
412    animator->on_animating = EINA_TRUE;
413    animator->cur_repeat_cnt = animator->repeat_cnt;
414    if (!animator->animator) 
415           animator->animator = ecore_animator_add(_animator_animate_cb, animator);
416    if (!animator->animator)
417       animator->on_animating = EINA_FALSE;
418 }