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