diff options
author | Jaehyun Cho <jae_hyun.cho@samsung.com> | 2017-04-25 14:34:28 +0900 |
---|---|---|
committer | Jaehyun Cho <jae_hyun.cho@samsung.com> | 2017-06-30 17:28:34 +0900 |
commit | b361f082991ed0bb141f5c0c48c40a347c47a1e8 (patch) | |
tree | c4581211811c97720fb0dcc8a71272ce3eb8a030 | |
parent | bc754f2d965954d2c4d1a8f9a6174c67c5d2182b (diff) | |
download | efl-b361f082991ed0bb141f5c0c48c40a347c47a1e8.tar.gz |
efl_animation: Implement animation function
-rw-r--r-- | src/lib/evas/Evas_Common.h | 5 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation.c | 133 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation.eo | 8 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_alpha.c | 8 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_rotate.c | 8 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_scale.c | 8 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_translate.c | 8 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_types.eot | 11 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_object_main.c | 174 |
9 files changed, 344 insertions, 19 deletions
diff --git a/src/lib/evas/Evas_Common.h b/src/lib/evas/Evas_Common.h index 090992646b..2c2e24ebb0 100644 --- a/src/lib/evas/Evas_Common.h +++ b/src/lib/evas/Evas_Common.h @@ -3329,6 +3329,11 @@ EAPI const Eina_List *evas_font_path_global_list(void) EINA_WARN_UNUSED_R */ EAPI void evas_font_reinit(void); +struct _Efl_Animation_Animate_Event_Info +{ + double progress; +}; + /** * @} */ diff --git a/src/lib/evas/canvas/efl_animation.c b/src/lib/evas/canvas/efl_animation.c index 408774ddf3..e1c8dfaaed 100644 --- a/src/lib/evas/canvas/efl_animation.c +++ b/src/lib/evas/canvas/efl_animation.c @@ -2,6 +2,7 @@ #include "evas_common_private.h" #include "evas_private.h" +#include <Ecore.h> #define MY_CLASS EFL_ANIMATION_CLASS #define MY_CLASS_NAME efl_class_name_get(MY_CLASS) @@ -18,6 +19,9 @@ } \ } while (0) +#define EFL_ANIMATION_DATA_GET(o, pd) \ + Evas_Object_Animation_Data *pd = efl_data_scope_get(o, EFL_ANIMATION_CLASS) + struct _Evas_Object_Animation_Data { /* @@ -30,18 +34,43 @@ struct _Evas_Object_Animation_Data * int current_loop; //Default value is 1 * Eina_Bool is_reverse; */ + Ecore_Animator *animator; + + struct + { + double begin; + double current; + } time; + Eo *target; + double progress; double duration; Eina_Bool deleted : 1; + Eina_Bool cancelled : 1; + Eina_Bool ended : 1; }; +static void +_target_del_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + Eo *eo_obj = data; + + EFL_ANIMATION_CHECK_OR_RETURN(eo_obj); + EFL_ANIMATION_DATA_GET(eo_obj, pd); + + pd->target = NULL; + efl_animation_cancel(eo_obj); +} + EOLIAN static void _efl_animation_target_set(Eo *eo_obj, Evas_Object_Animation_Data *pd, Evas_Object *target) { EFL_ANIMATION_CHECK_OR_RETURN(eo_obj); + efl_event_callback_add(target, EFL_EVENT_DEL, _target_del_cb, eo_obj); + pd->target = target; } @@ -80,38 +109,134 @@ _efl_animation_is_deleted(Eo *eo_obj, Evas_Object_Animation_Data *pd) return pd->deleted; } +static Eina_Bool +_animator_cb(void *data) +{ + Eo *eo_obj = data; + EFL_ANIMATION_DATA_GET(eo_obj, pd); + + if (pd->cancelled) goto end; + + double elapsed_time, duration; + + pd->time.current = ecore_loop_time_get(); + elapsed_time = pd->time.current - pd->time.begin; + duration = pd->duration; + if (elapsed_time > duration) + elapsed_time = duration; + + if (duration <= 0.0) goto end; + + pd->progress = elapsed_time / duration; + + Efl_Animation_Animate_Event_Info event_info; + event_info.progress = pd->progress; + + efl_event_callback_call(eo_obj, EFL_ANIMATION_EVENT_ANIMATE, &event_info); + + /* Not end. Keep going. */ + if (elapsed_time < duration) return ECORE_CALLBACK_RENEW; + +end: + pd->ended = EINA_TRUE; + pd->animator = NULL; + + efl_event_callback_call(eo_obj, EFL_ANIMATION_EVENT_END, NULL); + + //FIXME: Delete animation here + return ECORE_CALLBACK_CANCEL; +} + EOLIAN static Eina_Bool -_efl_animation_start(Eo *eo_obj, Evas_Object_Animation_Data *pd EINA_UNUSED) +_efl_animation_start(Eo *eo_obj, Evas_Object_Animation_Data *pd) { EFL_ANIMATION_CHECK_OR_RETURN(eo_obj, EINA_FALSE); + if (pd->duration <= 0.0) + return EINA_FALSE; + + pd->cancelled = EINA_FALSE; + pd->ended = EINA_FALSE; + + ecore_animator_del(pd->animator); + pd->animator = NULL; + + pd->time.begin = ecore_loop_time_get(); + pd->animator = ecore_animator_add(_animator_cb, eo_obj); + + _animator_cb(eo_obj); + return EINA_TRUE; } EOLIAN static Eina_Bool -_efl_animation_cancel(Eo *eo_obj, Evas_Object_Animation_Data *pd EINA_UNUSED) +_efl_animation_cancel(Eo *eo_obj, Evas_Object_Animation_Data *pd) { EFL_ANIMATION_CHECK_OR_RETURN(eo_obj, EINA_FALSE); + pd->cancelled = EINA_TRUE; + + if (pd->animator) + { + pd->ended = EINA_TRUE; + + ecore_animator_del(pd->animator); + pd->animator = NULL; + + efl_event_callback_call(eo_obj, EFL_ANIMATION_EVENT_END, NULL); + } + return EINA_TRUE; } +EOLIAN static Efl_Animation_State +_efl_animation_state_get(Eo *eo_obj, Evas_Object_Animation_Data *pd) +{ + EFL_ANIMATION_CHECK_OR_RETURN(eo_obj, EFL_ANIMATION_STATE_DELETED); + + if (pd->animator) + return EFL_ANIMATION_STATE_RUNNING; + else + return EFL_ANIMATION_STATE_STOPPED; +} + EOLIAN static Efl_Object * _efl_animation_efl_object_constructor(Eo *eo_obj, Evas_Object_Animation_Data *pd) { eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS)); - pd->duration = 0.0; + pd->time.begin = 0.0; + pd->time.current = 0.0; + pd->target = NULL; + pd->progress = 0.0; + pd->duration = 0.0; + pd->deleted = EINA_FALSE; + pd->cancelled = EINA_FALSE; + pd->ended = EINA_FALSE; return eo_obj; } EOLIAN static void -_efl_animation_efl_object_destructor(Eo *eo_obj, Evas_Object_Animation_Data *pd EINA_UNUSED) +_efl_animation_efl_object_destructor(Eo *eo_obj, Evas_Object_Animation_Data *pd) { + pd->deleted = EINA_TRUE; + + if (pd->animator) + { + ecore_animator_del(pd->animator); + pd->animator = NULL; + pd->ended = EINA_TRUE; + + efl_event_callback_call(eo_obj, EFL_ANIMATION_EVENT_END, NULL); + } + + if (pd->target) + efl_event_callback_del(pd->target, EFL_EVENT_DEL, _target_del_cb, eo_obj); + efl_destructor(efl_super(eo_obj, MY_CLASS)); } diff --git a/src/lib/evas/canvas/efl_animation.eo b/src/lib/evas/canvas/efl_animation.eo index 27e349193a..e80d93ecf0 100644 --- a/src/lib/evas/canvas/efl_animation.eo +++ b/src/lib/evas/canvas/efl_animation.eo @@ -36,9 +36,17 @@ abstract Efl.Animation (Efl.Object) [[Cancel animation.]] return: bool; [[$true on success, $false otherwise]] } + state_get { + [[Get the state of animation]] + return: Efl.Animation.State; [[Animation state]] + } } implements { Efl.Object.constructor; Efl.Object.destructor; } + events { + animate; [[Animation is animated.]] + end; [[Animation ended]] + } } diff --git a/src/lib/evas/canvas/efl_animation_alpha.c b/src/lib/evas/canvas/efl_animation_alpha.c index 8ddafd5361..a490c35648 100644 --- a/src/lib/evas/canvas/efl_animation_alpha.c +++ b/src/lib/evas/canvas/efl_animation_alpha.c @@ -49,6 +49,12 @@ _efl_animation_alpha_alpha_get(Eo *eo_obj EINA_UNUSED, Evas_Object_Animation_Alp *to_alpha = pd->to.alpha; } +static void +_animate_cb(void *data, const Efl_Event *event) +{ + Efl_Animation_Animate_Event_Info *event_info = event->info; +} + EOLIAN static Efl_Object * _efl_animation_alpha_efl_object_constructor(Eo *eo_obj, Evas_Object_Animation_Alpha_Data *pd) { @@ -57,6 +63,8 @@ _efl_animation_alpha_efl_object_constructor(Eo *eo_obj, Evas_Object_Animation_Al pd->from.alpha = 1.0; pd->to.alpha = 1.0; + efl_event_callback_add(eo_obj, EFL_ANIMATION_EVENT_ANIMATE, _animate_cb, NULL); + return eo_obj; } diff --git a/src/lib/evas/canvas/efl_animation_rotate.c b/src/lib/evas/canvas/efl_animation_rotate.c index da6e9961e1..4dd0ab0e54 100644 --- a/src/lib/evas/canvas/efl_animation_rotate.c +++ b/src/lib/evas/canvas/efl_animation_rotate.c @@ -119,6 +119,12 @@ _efl_animation_rotate_absolute_pivot_get(Eo *eo_obj, Evas_Object_Animation_Rotat *pivot_z = pd->abs_pivot.z; } +static void +_animate_cb(void *data, const Efl_Event *event) +{ + Efl_Animation_Animate_Event_Info *event_info = event->info; +} + EOLIAN static Efl_Object * _efl_animation_rotate_efl_object_constructor(Eo *eo_obj, Evas_Object_Animation_Rotate_Data *pd) { @@ -137,6 +143,8 @@ _efl_animation_rotate_efl_object_constructor(Eo *eo_obj, Evas_Object_Animation_R pd->use_rel_pivot = EINA_TRUE; + efl_event_callback_add(eo_obj, EFL_ANIMATION_EVENT_ANIMATE, _animate_cb, NULL); + return eo_obj; } diff --git a/src/lib/evas/canvas/efl_animation_scale.c b/src/lib/evas/canvas/efl_animation_scale.c index 74f8de84b0..3fe0d3b4d9 100644 --- a/src/lib/evas/canvas/efl_animation_scale.c +++ b/src/lib/evas/canvas/efl_animation_scale.c @@ -121,6 +121,12 @@ _efl_animation_scale_scale_z_get(Eo *eo_obj, Evas_Object_Animation_Scale_Data *p *to_z = pd->to.scale_z; } +static void +_animate_cb(void *data, const Efl_Event *event) +{ + Efl_Animation_Animate_Event_Info *event_info = event->info; +} + EOLIAN static Efl_Object * _efl_animation_scale_efl_object_constructor(Eo *eo_obj, Evas_Object_Animation_Scale_Data *pd) { @@ -130,6 +136,8 @@ _efl_animation_scale_efl_object_constructor(Eo *eo_obj, Evas_Object_Animation_Sc pd->from.scale_y = 1.0; pd->from.scale_z = 1.0; + efl_event_callback_add(eo_obj, EFL_ANIMATION_EVENT_ANIMATE, _animate_cb, NULL); + return eo_obj; } diff --git a/src/lib/evas/canvas/efl_animation_translate.c b/src/lib/evas/canvas/efl_animation_translate.c index 84bad4dfb9..5b09effb45 100644 --- a/src/lib/evas/canvas/efl_animation_translate.c +++ b/src/lib/evas/canvas/efl_animation_translate.c @@ -230,6 +230,12 @@ _efl_animation_translate_coordinate_z_get(Eo *eo_obj, Evas_Object_Animation_Tran *to_z = pd->to.z; } +static void +_animate_cb(void *data, const Efl_Event *event) +{ + Efl_Animation_Animate_Event_Info *event_info = event->info; +} + EOLIAN static Efl_Object * _efl_animation_translate_efl_object_constructor(Eo *eo_obj, Evas_Object_Animation_Translate_Data *pd) { @@ -251,6 +257,8 @@ _efl_animation_translate_efl_object_constructor(Eo *eo_obj, Evas_Object_Animatio pd->to.y = 0; pd->to.z = 0; + efl_event_callback_add(eo_obj, EFL_ANIMATION_EVENT_ANIMATE, _animate_cb, NULL); + return eo_obj; } diff --git a/src/lib/evas/canvas/efl_animation_types.eot b/src/lib/evas/canvas/efl_animation_types.eot index fed4c64e5f..6415e8cbaa 100644 --- a/src/lib/evas/canvas/efl_animation_types.eot +++ b/src/lib/evas/canvas/efl_animation_types.eot @@ -10,3 +10,14 @@ enum Efl.Animation.Event_Type clicked, [["clicked" event type]] count [[total count of event type]] } + +enum Efl.Animation.State +{ + [[Animation state]] + + running = 0, [[running state]] + stopped, [[stopped state]] + deleted [[deleted state]] +} + +struct Efl.Animation.Animate_Event_Info; [[Information of animate event]] diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c index 76eb2b71eb..ef635fb84f 100644 --- a/src/lib/evas/canvas/evas_object_main.c +++ b/src/lib/evas/canvas/evas_object_main.c @@ -51,6 +51,12 @@ typedef struct _Event_Animation Efl_Animation *anim; } Event_Animation; +typedef struct _Hide_Anim_Data +{ + Eina_Bool anim_started; + Eina_Bool anim_ended; +} Hide_Anim_Data; + static Eina_Bool _init_cow(void) { @@ -1062,6 +1068,20 @@ _efl_animation_event_type_get(const char *event_str) return -1; } +static void +_all_animations_cancel(Eo *eo_obj) +{ + Efl_Animation_Event_Type event_type; + for (event_type = EFL_ANIMATION_EVENT_TYPE_SHOW; + event_type < EFL_ANIMATION_EVENT_TYPE_COUNT; event_type++) + { + Efl_Animation *anim = efl_canvas_object_event_animation_get(eo_obj, + event_type); + if (anim) + efl_animation_cancel(anim); + } +} + EOLIAN static Eina_Bool _efl_canvas_object_efl_object_event_callback_call(Eo *eo_obj, Evas_Object_Protected_Data *obj EINA_UNUSED, @@ -1080,7 +1100,10 @@ _efl_canvas_object_efl_object_event_callback_call(Eo *eo_obj, Efl_Animation *anim = efl_canvas_object_event_animation_get(eo_obj, event_type); if (anim) - efl_animation_start(anim); + { + _all_animations_cancel(eo_obj); + efl_animation_start(anim); + } } } @@ -1106,7 +1129,10 @@ _efl_canvas_object_efl_object_event_callback_legacy_call(Eo *eo_obj, Efl_Animation *anim = efl_canvas_object_event_animation_get(eo_obj, event_type); if (anim) - efl_animation_start(anim); + { + _all_animations_cancel(eo_obj); + efl_animation_start(anim); + } } } @@ -1129,6 +1155,15 @@ _efl_canvas_object_efl_object_destructor(Eo *eo_obj, Evas_Object_Protected_Data int event_id; edata = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS); + + //Unset event animations + efl_canvas_object_event_animation_set(eo_obj, EFL_ANIMATION_EVENT_TYPE_SHOW, + NULL); + efl_canvas_object_event_animation_set(eo_obj, EFL_ANIMATION_EVENT_TYPE_HIDE, + NULL); + efl_canvas_object_event_animation_set(eo_obj, + EFL_ANIMATION_EVENT_TYPE_CLICKED, + NULL); evas_object_hide(eo_obj); if (obj->events) EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) @@ -1772,6 +1807,41 @@ evas_object_hide(Evas_Object *eo_obj) efl_gfx_visible_set(eo_obj, EINA_FALSE); } +static void _animation_intercept_hide(void *data, Evas_Object *eo_obj); + +static void +_animation_hide_end_cb(void *data, const Efl_Event *event) +{ + Hide_Anim_Data *hide_anim_data = data; + + hide_anim_data->anim_ended = EINA_TRUE; + + Eo *eo_obj = efl_animation_target_get(event->object); + _animation_intercept_hide(hide_anim_data, eo_obj); + + hide_anim_data->anim_started = EINA_FALSE; + hide_anim_data->anim_ended = EINA_FALSE; +} + +static void +_animation_intercept_hide(void *data, Evas_Object *eo_obj) +{ + Hide_Anim_Data *hide_anim_data = data; + + Efl_Animation *anim = + efl_canvas_object_event_animation_get(eo_obj, + EFL_ANIMATION_EVENT_TYPE_HIDE); + if (anim && !hide_anim_data->anim_started && !hide_anim_data->anim_ended) + { + hide_anim_data->anim_started = EINA_TRUE; + + _all_animations_cancel(eo_obj); + efl_animation_start(anim); + } + else + efl_gfx_visible_set(eo_obj, EINA_FALSE); +} + EAPI Eina_Bool evas_object_visible_get(const Evas_Object *obj) { @@ -1818,18 +1888,15 @@ _show(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj) efl_canvas_object_event_animation_get(eo_obj, EFL_ANIMATION_EVENT_TYPE_SHOW); if (anim) - efl_animation_start(anim); + { + _all_animations_cancel(eo_obj); + efl_animation_start(anim); + } } static void _hide(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj) { - Efl_Animation *anim = - efl_canvas_object_event_animation_get(eo_obj, - EFL_ANIMATION_EVENT_TYPE_HIDE); - if (anim) - efl_animation_start(anim); - if (obj->is_smart && obj->smart.smart && obj->smart.smart->smart_class->hide) { obj->smart.smart->smart_class->hide(eo_obj); @@ -2755,8 +2822,23 @@ _efl_animation_event_type_is_valid(Efl_Animation_Event_Type event) return EINA_TRUE; } +static void +_anim_del_cb(void *data, const Efl_Event *event) +{ + Eo *eo_obj = data; + Efl_Animation *anim = event->object; + Efl_Animation_Event_Type event_type; + + for (event_type = EFL_ANIMATION_EVENT_TYPE_SHOW; + event_type < EFL_ANIMATION_EVENT_TYPE_COUNT; event_type++) + { + if (anim == efl_canvas_object_event_animation_get(eo_obj, event_type)) + efl_canvas_object_event_animation_set(eo_obj, event_type, NULL); + } +} + EOLIAN void -_efl_canvas_object_event_animation_set(Eo *eo_obj EINA_UNUSED, +_efl_canvas_object_event_animation_set(Eo *eo_obj, Evas_Object_Protected_Data *pd, Efl_Animation_Event_Type event_type, Efl_Animation *animation) @@ -2765,13 +2847,75 @@ _efl_canvas_object_event_animation_set(Eo *eo_obj EINA_UNUSED, return; Event_Animation *event_anim = eina_array_data_get(pd->event_anims, event_type); - if (event_anim && event_anim->anim) + if (!event_anim) return; + + Efl_Animation *cur_anim = event_anim->anim; + Efl_Animation *new_anim = animation; + + //Unset for current event animation + if (cur_anim) + { + Eo *prev_target = + efl_animation_target_get(cur_anim); + + //Deallocate memory and Unset callbacks for Hide event + if (event_type == EFL_ANIMATION_EVENT_TYPE_HIDE) + { + Hide_Anim_Data *hide_anim_data + = evas_object_intercept_hide_callback_del(prev_target, + _animation_intercept_hide); + if (hide_anim_data) + { + efl_event_callback_del(cur_anim, EFL_ANIMATION_EVENT_END, + _animation_hide_end_cb, + hide_anim_data); + + if (hide_anim_data->anim_started && + !hide_anim_data->anim_ended) + efl_gfx_visible_set(prev_target, EINA_FALSE); + + free(hide_anim_data); + } + } + + //Unset callback + efl_event_callback_del(cur_anim, EFL_EVENT_DEL, + _anim_del_cb, prev_target); + + //Stop animation + efl_animation_cancel(cur_anim); + } + + //Replace current event animation with new event animation + event_anim->anim = new_anim; + + //Set for new event animation + if (new_anim) { - //Stop current animation - efl_animation_cancel(event_anim->anim); + //Set target object for the given animation + Eo *target = efl_animation_target_get(new_anim); + if (!target) + target = eo_obj; + efl_animation_target_set(new_anim, target); + + //Allocate memory and Set callbacks for Hide event + if (event_type == EFL_ANIMATION_EVENT_TYPE_HIDE) + { + Hide_Anim_Data *hide_anim_data = calloc(1, sizeof(Hide_Anim_Data)); + hide_anim_data->anim_started = EINA_FALSE; + hide_anim_data->anim_ended = EINA_FALSE; + + evas_object_intercept_hide_callback_add(target, + _animation_intercept_hide, + hide_anim_data); + + efl_event_callback_add(new_anim, EFL_ANIMATION_EVENT_END, + _animation_hide_end_cb, + hide_anim_data); + } - //Set new animation - event_anim->anim = animation; + //Set callback + efl_event_callback_add(new_anim, EFL_EVENT_DEL, _anim_del_cb, target); } } |