summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/efl_animation_player.c
diff options
context:
space:
mode:
authorSungtaek Hong <sth253.hong@samsung.com>2018-01-16 20:31:15 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2018-01-16 22:04:55 +0900
commit588995da317520fc92660b89b0864bb1f25abc09 (patch)
tree18105ad544539753c5cddea93224bb8c3f2bd8c4 /src/lib/evas/canvas/efl_animation_player.c
parent1da72770f385489c259f3200df3ba72adedb2471 (diff)
efl_playable: split Efl.Player interface to Efl.Playable interface
Summary: Efl.Player interface simply provides play functions, but another interface which indicates Efl.Player will play is also needed. Test Plan: Run elementary_test->Efl.Animation tests Reviewers: woohyun, conr2d, Jaehyun_Cho, jpeg, cedric Differential Revision: https://phab.enlightenment.org/D5662
Diffstat (limited to '')
-rw-r--r--src/lib/evas/canvas/efl_animation_player.c384
1 files changed, 384 insertions, 0 deletions
diff --git a/src/lib/evas/canvas/efl_animation_player.c b/src/lib/evas/canvas/efl_animation_player.c
new file mode 100644
index 0000000000..8b31524f34
--- /dev/null
+++ b/src/lib/evas/canvas/efl_animation_player.c
@@ -0,0 +1,384 @@
1#include "efl_animation_player_private.h"
2
3static void
4_target_del_cb(void *data, const Efl_Event *event EINA_UNUSED)
5{
6 Efl_Animation_Player_Data *pd = data;
7 pd->target = NULL;
8}
9
10EOLIAN static void
11_efl_animation_player_target_set(Eo *eo_obj EINA_UNUSED,
12 Efl_Animation_Player_Data *pd,
13 Efl_Canvas_Object *target)
14{
15 efl_event_callback_add(target, EFL_EVENT_DEL, _target_del_cb, pd);
16
17 pd->target = target;
18}
19
20EOLIAN static Efl_Canvas_Object *
21_efl_animation_player_target_get(Eo *eo_obj EINA_UNUSED, Efl_Animation_Player_Data *pd)
22{
23 return pd->target;
24}
25
26EOLIAN static void
27_efl_animation_player_auto_del_set(Eo *eo_obj EINA_UNUSED,
28 Efl_Animation_Player_Data *pd,
29 Eina_Bool auto_del)
30{
31 pd->auto_del = auto_del;
32}
33
34EOLIAN static Eina_Bool
35_efl_animation_player_auto_del_get(Eo *eo_obj EINA_UNUSED,
36 Efl_Animation_Player_Data *pd)
37{
38 return pd->auto_del;
39}
40
41EOLIAN static void
42_efl_animation_player_animation_set(Eo *eo_obj,
43 Efl_Animation_Player_Data *pd,
44 Efl_Animation *anim)
45{
46 if (anim == pd->animation)
47 return;
48
49 if (!efl_isa(anim, EFL_ANIMATION_CLASS))
50 {
51 ERR("Passed argument [%p]:[%s] is not an Efl.Animation",
52 anim, efl_class_name_get(efl_class_get(anim)));
53 return;
54 }
55
56 if (pd->animation)
57 {
58 efl_player_stop(eo_obj);
59 efl_unref(pd->animation);
60 }
61 pd->animation = anim;
62 efl_ref(pd->animation);
63}
64
65EOLIAN static Efl_Animation *
66_efl_animation_player_animation_get(Eo *eo_obj EINA_UNUSED,
67 Efl_Animation_Player_Data *pd)
68{
69 return pd->animation;
70}
71
72static Eina_Bool
73_animator_cb(void *data)
74{
75 Eo *eo_obj = data;
76 EFL_ANIMATION_PLAYER_DATA_GET(eo_obj, pd);
77 EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
78 double duration, elapsed_time, vector;
79
80 if (efl_player_seekable_get(eo_obj))
81 {
82 pd->time.current = ecore_loop_time_get();
83
84 duration = efl_animation_duration_get(anim);
85 elapsed_time = pd->time.current - pd->time.prev;
86 vector = elapsed_time / duration;
87
88 if (vector <= DBL_EPSILON)
89 return ECORE_CALLBACK_RENEW; // There is no update.
90
91 //TODO: check negative play_speed.
92 if (!pd->is_direction_forward)
93 vector *= -1;
94 pd->progress += vector;
95
96 if (pd->progress > 1.0)
97 pd->progress = 1,0;
98 else if (pd->progress < 0.0)
99 pd->progress = 0,0;
100 }
101 else
102 {
103 pd->progress = (double)(pd->is_direction_forward);
104 }
105
106 efl_animation_apply(anim, pd->progress, efl_animation_player_target_get(eo_obj));
107
108 Efl_Animation_Player_Running_Event_Info event_info;
109 event_info.progress = pd->progress;
110 efl_event_callback_call(eo_obj, EFL_ANIMATION_PLAYER_EVENT_RUNNING,
111 &event_info);
112 pd->time.prev = pd->time.current;
113
114 //Not end. Keep going.
115 if (fabs((!!(pd->is_direction_forward)) - pd->progress) > DBL_EPSILON)
116 return ECORE_CALLBACK_RENEW;
117
118 //Repeat animation
119 if ((efl_animation_repeat_count_get(anim) == EFL_ANIMATION_REPEAT_INFINITE) ||
120 (pd->remaining_repeat_count > 0))
121 {
122 if (pd->remaining_repeat_count > 0)
123 pd->remaining_repeat_count--;
124
125 if (efl_animation_repeat_mode_get(anim) == EFL_ANIMATION_REPEAT_MODE_REVERSE)
126 {
127 pd->is_direction_forward = !pd->is_direction_forward;
128 }
129 else
130 {
131 pd->progress = 0.0;
132 }
133
134 return ECORE_CALLBACK_RENEW;
135 }
136 efl_player_stop(eo_obj);
137
138 return ECORE_CALLBACK_CANCEL;
139}
140
141static void
142_start(Eo *eo_obj, Efl_Animation_Player_Data *pd)
143{
144 EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
145
146 pd->is_direction_forward = EINA_TRUE;
147
148 pd->remaining_repeat_count = efl_animation_repeat_count_get(anim);
149
150 ecore_animator_del(pd->animator);
151 pd->animator = NULL;
152 pd->time.prev = ecore_loop_time_get();
153
154 //pre started event is supported within class only (protected event)
155 efl_event_callback_call(eo_obj, EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED,
156 NULL);
157 efl_event_callback_call(eo_obj, EFL_ANIMATION_PLAYER_EVENT_STARTED, NULL);
158
159 pd->animator = ecore_animator_add(_animator_cb, eo_obj);
160
161 _animator_cb(eo_obj);
162}
163
164static Eina_Bool
165_start_delay_timer_cb(void *data)
166{
167 Eo *eo_obj = data;
168 EFL_ANIMATION_PLAYER_DATA_GET(eo_obj, pd);
169
170 pd->start_delay_timer = NULL;
171
172 _start(eo_obj, pd);
173
174 return ECORE_CALLBACK_CANCEL;
175}
176
177EOLIAN static void
178_efl_animation_player_efl_player_start(Eo *eo_obj,
179 Efl_Animation_Player_Data *pd)
180{
181 double start_delay;
182 EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
183
184 if (!efl_player_playable_get(eo_obj)) return;
185 pd->is_play = EINA_TRUE;
186 //TODO: check this case is correct
187 if (pd->start_delay_timer) return;
188
189 pd->progress = 0.0;
190 start_delay = efl_animation_start_delay_get(anim);
191 if (start_delay > 0.0)
192 {
193 pd->start_delay_timer = ecore_timer_add(start_delay,
194 _start_delay_timer_cb, eo_obj);
195 return;
196 }
197
198 _start(eo_obj, pd);
199}
200
201EOLIAN static void
202_efl_animation_player_efl_player_stop(Eo *eo_obj,
203 Efl_Animation_Player_Data *pd)
204{
205 EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
206 Eina_Bool play = efl_player_play_get(eo_obj);
207 if (play)
208 {
209 efl_player_play_set(eo_obj, EINA_FALSE);
210 //Reset the state of the target to the initial state
211 if ((efl_animation_final_state_keep_get(anim)) &&
212 (efl_animation_repeat_mode_get(anim) != EFL_ANIMATION_REPEAT_MODE_REVERSE) &&
213 (!(efl_animation_repeat_count_get(anim) & 1)))
214 {
215 pd->progress = 1.0;
216 }
217 else
218 {
219 pd->progress = 0.0;
220 }
221 }
222 else
223 {
224 pd->progress = 0.0;
225 }
226 efl_animation_apply(anim, pd->progress, efl_animation_player_target_get(eo_obj));
227 if (play)
228 efl_event_callback_call(eo_obj, EFL_ANIMATION_PLAYER_EVENT_ENDED, NULL);
229
230 if (pd->auto_del) efl_del(eo_obj);
231}
232
233EOLIAN static void
234_efl_animation_player_efl_player_play_set(Eo *eo_obj,
235 Efl_Animation_Player_Data *pd,
236 Eina_Bool play)
237{
238 if (efl_player_play_get(eo_obj) == !!play)
239 return;
240
241 pd->is_play = play;
242 if (play)
243 {
244 //TODO: check this case is correct.
245 if (pd->start_delay_timer) return;
246
247 pd->time.prev = ecore_loop_time_get();
248 pd->animator = ecore_animator_add(_animator_cb, eo_obj);
249
250 _animator_cb(eo_obj);
251 }
252 else
253 {
254 ecore_timer_del(pd->start_delay_timer);
255 pd->start_delay_timer = NULL;
256 ecore_animator_del(pd->animator);
257 pd->animator = NULL;
258 }
259}
260
261EOLIAN static Eina_Bool
262_efl_animation_player_efl_player_play_get(Eo *eo_obj EINA_UNUSED,
263 Efl_Animation_Player_Data *pd)
264{
265 return pd->is_play;
266}
267
268EOLIAN static Eina_Bool
269_efl_animation_player_efl_player_playable_get(Eo *eo_obj,
270 Efl_Animation_Player_Data *pd EINA_UNUSED)
271{
272 Efl_Animation *anim = efl_animation_player_animation_get(eo_obj);
273
274 return efl_playable_get(anim);
275}
276
277EOLIAN static double
278_efl_animation_player_efl_player_position_get(Eo *eo_obj,
279 Efl_Animation_Player_Data *pd EINA_UNUSED)
280{
281 //TODO: this is not correct
282 Efl_Animation *anim = efl_animation_player_animation_get(eo_obj);
283 double length = efl_player_length_get(anim);
284
285 return length * efl_player_progress_get(anim);
286}
287
288EOLIAN static void
289_efl_animation_player_efl_player_position_set(Eo *eo_obj,
290 Efl_Animation_Player_Data *pd EINA_UNUSED,
291 double sec)
292{
293 //TODO: this is not correct
294 if (!efl_player_seekable_get(eo_obj))
295 return;
296
297 EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
298 double length = efl_player_length_get(anim);
299 pd->progress = sec / length;
300 efl_animation_apply(anim, pd->progress, efl_animation_player_target_get(eo_obj));
301}
302
303EOLIAN static double
304_efl_animation_player_efl_player_progress_get(Eo *eo_obj EINA_UNUSED,
305 Efl_Animation_Player_Data *pd)
306{
307 return pd->progress;
308}
309
310EOLIAN static void
311_efl_animation_player_efl_player_play_speed_set(Eo *eo_obj EINA_UNUSED,
312 Efl_Animation_Player_Data *pd,
313 double play_speed)
314{
315 //TODO: check reverse play case.
316 if (play_speed < 0)
317 return;
318 pd->play_speed = play_speed;
319}
320
321EOLIAN static double
322_efl_animation_player_efl_player_play_speed_get(Eo *eo_obj EINA_UNUSED,
323 Efl_Animation_Player_Data *pd)
324{
325 return pd->play_speed;
326}
327
328EOLIAN static double
329_efl_animation_player_efl_player_length_get(Eo *eo_obj,
330 Efl_Animation_Player_Data *pd EINA_UNUSED)
331{
332 EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
333 return efl_playable_length_get(anim);
334}
335
336EOLIAN static Eina_Bool
337_efl_animation_player_efl_player_seekable_get(Eo *eo_obj EINA_UNUSED,
338 Efl_Animation_Player_Data *pd EINA_UNUSED)
339{
340 EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
341 return efl_playable_seekable_get(anim);
342}
343
344EOLIAN static Efl_Object *
345_efl_animation_player_efl_object_constructor(Eo *eo_obj,
346 Efl_Animation_Player_Data *pd)
347{
348 eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS));
349
350 pd->time.begin = 0.0;
351 pd->time.current = 0.0;
352
353 pd->animation = NULL;
354
355 pd->progress = 0.0;
356
357 //pd->auto_del = EINA_TRUE;
358
359 return eo_obj;
360}
361
362EOLIAN static void
363_efl_animation_player_efl_object_destructor(Eo *eo_obj,
364 Efl_Animation_Player_Data *pd)
365{
366 if (pd->animator)
367 {
368 ecore_animator_del(pd->animator);
369 pd->animator = NULL;
370
371 //Reset the state of the target to the initial state
372 efl_player_stop(eo_obj);
373
374 efl_event_callback_call(eo_obj, EFL_ANIMATION_PLAYER_EVENT_ENDED, NULL);
375 }
376 efl_unref(pd->animation);
377
378 efl_destructor(efl_super(eo_obj, MY_CLASS));
379}
380
381EWAPI const Efl_Event_Description _EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED =
382 EFL_EVENT_DESCRIPTION("pre_started");
383
384#include "efl_animation_player.eo.c"