diff options
author | Jaehyun Cho <jae_hyun.cho@samsung.com> | 2017-07-21 16:59:25 +0900 |
---|---|---|
committer | Jaehyun Cho <jae_hyun.cho@samsung.com> | 2017-08-18 12:06:01 +0900 |
commit | fc56473d5db1a2b4ebb0e7011ef6c3ac783bfb1a (patch) | |
tree | 33aff30ca2250811484ce5dfec98a0db0d5a5408 | |
parent | 79230ed40616c68a1e79bf2eefcb1250dd8b43c7 (diff) | |
download | efl-fc56473d5db1a2b4ebb0e7011ef6c3ac783bfb1a.tar.gz |
efl_animation: Add repeat_mode property
To not display original state when the reverse repeat starts, the
animators in group parallel and group sequential are deleted.
-rw-r--r-- | src/lib/evas/Evas_Internal.h | 11 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation.c | 35 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation.eo | 9 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_alpha.c | 3 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_group_parallel.c | 3 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_group_sequential.c | 3 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_instance.c | 121 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_instance_group_parallel.c | 255 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_instance_group_sequential.c | 268 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_rotate.c | 3 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_scale.c | 3 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_translate.c | 3 | ||||
-rw-r--r-- | src/lib/evas/canvas/efl_animation_types.eot | 8 |
13 files changed, 600 insertions, 125 deletions
diff --git a/src/lib/evas/Evas_Internal.h b/src/lib/evas/Evas_Internal.h index 3296fea633..1d3a37cd8c 100644 --- a/src/lib/evas/Evas_Internal.h +++ b/src/lib/evas/Evas_Internal.h @@ -96,6 +96,15 @@ EOAPI double efl_animation_instance_duration_get(const Eo *obj); EOAPI void efl_animation_instance_start_delay_set(Eo *obj, double delay_time); EOAPI double efl_animation_instance_start_delay_get(const Eo *obj); +typedef enum +{ + EFL_ANIMATION_INSTANCE_REPEAT_MODE_RESTART = 0, + EFL_ANIMATION_INSTANCE_REPEAT_MODE_REVERSE +} Efl_Animation_Instance_Repeat_Mode; + +EOAPI void efl_animation_instance_repeat_mode_set(Eo *obj, Efl_Animation_Instance_Repeat_Mode mode); +EOAPI Efl_Animation_Instance_Repeat_Mode efl_animation_instance_repeat_mode_get(const Eo *obj); + EOAPI void efl_animation_instance_repeat_count_set(Eo *obj, int count); EOAPI int efl_animation_instance_repeat_count_get(const Eo *obj); @@ -103,6 +112,8 @@ EOAPI Eina_Bool efl_animation_instance_is_deleted(Eo *obj); EOAPI void efl_animation_instance_member_start(Eo *obj); +EOAPI void efl_animation_instance_reverse_member_start(Eo *obj); + EOAPI void efl_animation_instance_map_reset(Eo *obj); EOAPI void efl_animation_instance_final_state_show(Eo *obj); diff --git a/src/lib/evas/canvas/efl_animation.c b/src/lib/evas/canvas/efl_animation.c index e1265c761d..d83d8fab29 100644 --- a/src/lib/evas/canvas/efl_animation.c +++ b/src/lib/evas/canvas/efl_animation.c @@ -30,15 +30,16 @@ struct _Evas_Object_Animation_Data * int current_loop; //Default value is 1 * Eina_Bool is_reverse; */ - Efl_Canvas_Object *target; + Efl_Canvas_Object *target; - double duration; - double start_delay_time; + double duration; + double start_delay_time; - int repeat_count; + Efl_Animation_Repeat_Mode repeat_mode; + int repeat_count; - Eina_Bool deleted : 1; - Eina_Bool state_keep : 1; + Eina_Bool deleted : 1; + Eina_Bool state_keep : 1; }; static void @@ -95,6 +96,27 @@ _efl_animation_duration_get(Eo *eo_obj, Evas_Object_Animation_Data *pd) } EOLIAN static void +_efl_animation_repeat_mode_set(Eo *eo_obj, + Evas_Object_Animation_Data *pd, + Efl_Animation_Repeat_Mode mode) +{ + EFL_ANIMATION_CHECK_OR_RETURN(eo_obj); + + if ((mode == EFL_ANIMATION_REPEAT_MODE_RESTART) || + (mode == EFL_ANIMATION_REPEAT_MODE_REVERSE)) + pd->repeat_mode = mode; +} + +EOLIAN static Efl_Animation_Repeat_Mode +_efl_animation_repeat_mode_get(Eo *eo_obj, Evas_Object_Animation_Data *pd) +{ + EFL_ANIMATION_CHECK_OR_RETURN(eo_obj, + EFL_ANIMATION_REPEAT_MODE_RESTART); + + return pd->repeat_mode; +} + +EOLIAN static void _efl_animation_repeat_count_set(Eo *eo_obj, Evas_Object_Animation_Data *pd, int count) @@ -175,6 +197,7 @@ _efl_animation_efl_object_constructor(Eo *eo_obj, pd->duration = 0.0; pd->start_delay_time = 0.0; + pd->repeat_mode = EFL_ANIMATION_REPEAT_MODE_RESTART; pd->repeat_count = 0; pd->deleted = EINA_FALSE; diff --git a/src/lib/evas/canvas/efl_animation.eo b/src/lib/evas/canvas/efl_animation.eo index aed41751a8..4f5f12369d 100644 --- a/src/lib/evas/canvas/efl_animation.eo +++ b/src/lib/evas/canvas/efl_animation.eo @@ -33,6 +33,15 @@ abstract Efl.Animation (Efl.Object) duration: double; [[Duration value]] } } + @property repeat_mode { + set { + } + get { + } + values { + mode: Efl.Animation.Repeat_Mode; [[Repeat mode. EFL_ANIMATION_REPEAT_MODE_RESTART restarts animation when the animation ends and EFL_ANIMATION_REPEAT_MODE_REVERSE reverses animation when the animation ends.]] + } + } @property repeat_count { set { } diff --git a/src/lib/evas/canvas/efl_animation_alpha.c b/src/lib/evas/canvas/efl_animation_alpha.c index e3f255ff8f..d515063197 100644 --- a/src/lib/evas/canvas/efl_animation_alpha.c +++ b/src/lib/evas/canvas/efl_animation_alpha.c @@ -70,6 +70,9 @@ _efl_animation_alpha_efl_animation_instance_create(Eo *eo_obj, Evas_Object_Anima double start_delay_time = efl_animation_start_delay_get(eo_obj); efl_animation_instance_start_delay_set(instance, start_delay_time); + Efl_Animation_Repeat_Mode repeat_mode = efl_animation_repeat_mode_get(eo_obj); + efl_animation_instance_repeat_mode_set(instance, (Efl_Animation_Instance_Repeat_Mode)repeat_mode); + int repeat_count = efl_animation_repeat_count_get(eo_obj); efl_animation_instance_repeat_count_set(instance, repeat_count); diff --git a/src/lib/evas/canvas/efl_animation_group_parallel.c b/src/lib/evas/canvas/efl_animation_group_parallel.c index 3007664f90..fd5c6c3243 100644 --- a/src/lib/evas/canvas/efl_animation_group_parallel.c +++ b/src/lib/evas/canvas/efl_animation_group_parallel.c @@ -54,6 +54,9 @@ _efl_animation_group_parallel_efl_animation_instance_create(Eo *eo_obj, double start_delay_time = efl_animation_start_delay_get(eo_obj); efl_animation_instance_start_delay_set(group_inst, start_delay_time); + Efl_Animation_Repeat_Mode repeat_mode = efl_animation_repeat_mode_get(eo_obj); + efl_animation_instance_repeat_mode_set(group_inst, (Efl_Animation_Instance_Repeat_Mode)repeat_mode); + int repeat_count = efl_animation_repeat_count_get(eo_obj); efl_animation_instance_repeat_count_set(group_inst, repeat_count); diff --git a/src/lib/evas/canvas/efl_animation_group_sequential.c b/src/lib/evas/canvas/efl_animation_group_sequential.c index 9b2c3dd705..6fe3de4939 100644 --- a/src/lib/evas/canvas/efl_animation_group_sequential.c +++ b/src/lib/evas/canvas/efl_animation_group_sequential.c @@ -54,6 +54,9 @@ _efl_animation_group_sequential_efl_animation_instance_create(Eo *eo_obj, double start_delay_time = efl_animation_start_delay_get(eo_obj); efl_animation_instance_start_delay_set(group_inst, start_delay_time); + Efl_Animation_Repeat_Mode repeat_mode = efl_animation_repeat_mode_get(eo_obj); + efl_animation_instance_repeat_mode_set(group_inst, (Efl_Animation_Instance_Repeat_Mode)repeat_mode); + int repeat_count = efl_animation_repeat_count_get(eo_obj); efl_animation_instance_repeat_count_set(group_inst, repeat_count); diff --git a/src/lib/evas/canvas/efl_animation_instance.c b/src/lib/evas/canvas/efl_animation_instance.c index cb0c3a0b0c..2d8da7c7e5 100644 --- a/src/lib/evas/canvas/efl_animation_instance.c +++ b/src/lib/evas/canvas/efl_animation_instance.c @@ -37,10 +37,10 @@ struct _Evas_Object_Animation_Instance_Data * int current_loop; //Default value is 1 * Eina_Bool is_reverse; */ - Ecore_Animator *animator; + Ecore_Animator *animator; - Ecore_Timer *start_delay_timer; - double start_delay_time; + Ecore_Timer *start_delay_timer; + double start_delay_time; struct { @@ -49,23 +49,26 @@ struct _Evas_Object_Animation_Instance_Data double pause_begin; } time; - Efl_Canvas_Object *target; - Target_State *target_state; - - double progress; - double duration; - double paused_time; - - int repeat_count; - int remaining_repeat_count; - - Eina_Bool deleted : 1; - Eina_Bool started : 1; - Eina_Bool cancelled : 1; - Eina_Bool ended : 1; - Eina_Bool paused : 1; - Eina_Bool state_keep : 1; - Eina_Bool is_group_member : 1; + Efl_Canvas_Object *target; + Target_State *target_state; + + double progress; + double duration; + double paused_time; + + Efl_Animation_Instance_Repeat_Mode repeat_mode; + int repeat_count; + int remaining_repeat_count; + + Eina_Bool deleted : 1; + Eina_Bool started : 1; + Eina_Bool reverse_started : 1; + Eina_Bool cancelled : 1; + Eina_Bool ended : 1; + Eina_Bool paused : 1; + Eina_Bool state_keep : 1; + Eina_Bool is_group_member : 1; + Eina_Bool direction_forward : 1; }; static void @@ -125,6 +128,27 @@ _efl_animation_instance_duration_get(const Eo *eo_obj, } EOLIAN static void +_efl_animation_instance_repeat_mode_set(Eo *eo_obj, + Evas_Object_Animation_Instance_Data *pd, + Efl_Animation_Instance_Repeat_Mode mode) +{ + EFL_ANIMATION_INSTANCE_CHECK_OR_RETURN(eo_obj); + + if ((mode == EFL_ANIMATION_INSTANCE_REPEAT_MODE_RESTART) || + (mode == EFL_ANIMATION_INSTANCE_REPEAT_MODE_REVERSE)) + pd->repeat_mode = mode; +} + +EOLIAN static Efl_Animation_Instance_Repeat_Mode +_efl_animation_instance_repeat_mode_get(const Eo *eo_obj, + Evas_Object_Animation_Instance_Data *pd) +{ + EFL_ANIMATION_INSTANCE_CHECK_OR_RETURN((Eo *)eo_obj, EFL_ANIMATION_INSTANCE_REPEAT_MODE_RESTART); + + return pd->repeat_mode; +} + +EOLIAN static void _efl_animation_instance_repeat_count_set(Eo *eo_obj, Evas_Object_Animation_Instance_Data *pd, int count) @@ -146,7 +170,6 @@ _efl_animation_instance_repeat_count_get(const Eo *eo_obj, return pd->repeat_count; } - EOLIAN static Eina_Bool _efl_animation_instance_is_deleted(Eo *eo_obj, Evas_Object_Animation_Instance_Data *pd) @@ -240,10 +263,19 @@ _animator_cb(void *data) if ((duration == 0.0) || ((elapsed_time - paused_time) > duration)) { elapsed_time = duration + paused_time; - pd->progress = 1.0; + + if (pd->direction_forward) + pd->progress = 1.0; + else + pd->progress = 0.0; } else - pd->progress = (elapsed_time - paused_time) / duration; + { + if (pd->direction_forward) + pd->progress = (elapsed_time - paused_time) / duration; + else + pd->progress = 1.0 - ((elapsed_time - paused_time) / duration); + } Efl_Animation_Instance_Animate_Event_Info event_info; event_info.progress = pd->progress; @@ -272,6 +304,9 @@ end: pd->time.begin = ecore_loop_time_get(); pd->paused_time = 0.0; + if (pd->repeat_mode == EFL_ANIMATION_INSTANCE_REPEAT_MODE_REVERSE) + pd->direction_forward = !pd->direction_forward; + _target_state_restore(pd->target, pd->target_state); return ECORE_CALLBACK_RENEW; @@ -282,6 +317,9 @@ end: pd->time.begin = ecore_loop_time_get(); pd->paused_time = 0.0; + if (pd->repeat_mode == EFL_ANIMATION_INSTANCE_REPEAT_MODE_REVERSE) + pd->direction_forward = !pd->direction_forward; + _target_state_restore(pd->target, pd->target_state); return ECORE_CALLBACK_RENEW; @@ -315,6 +353,11 @@ _init_start(Eo *eo_obj, Evas_Object_Animation_Instance_Data *pd) pd->remaining_repeat_count = pd->repeat_count; + if (pd->reverse_started) + pd->direction_forward = EINA_FALSE; + else + pd->direction_forward = EINA_TRUE; + ecore_animator_del(pd->animator); pd->animator = NULL; @@ -367,6 +410,7 @@ _efl_animation_instance_start(Eo *eo_obj, if (pd->start_delay_timer) return; pd->is_group_member = EINA_FALSE; + pd->reverse_started = EINA_FALSE; if (pd->start_delay_time > 0.0) { @@ -386,11 +430,33 @@ _efl_animation_instance_member_start(Eo *eo_obj, if (pd->paused) return; + if (pd->start_delay_timer) return; + + pd->is_group_member = EINA_TRUE; + pd->reverse_started = EINA_FALSE; + + if (pd->start_delay_time > 0.0) + { + pd->start_delay_timer = ecore_timer_add(pd->start_delay_time, + _start_delay_timer_cb, eo_obj); + return; + } + + _start(eo_obj, pd); +} + +EOLIAN static void +_efl_animation_instance_reverse_member_start(Eo *eo_obj, + Evas_Object_Animation_Instance_Data *pd) +{ + EFL_ANIMATION_INSTANCE_CHECK_OR_RETURN(eo_obj); + if (pd->paused) return; if (pd->start_delay_timer) return; pd->is_group_member = EINA_TRUE; + pd->reverse_started = EINA_TRUE; if (pd->start_delay_time > 0.0) { @@ -523,6 +589,7 @@ _efl_animation_instance_efl_object_constructor(Eo *eo_obj, pd->progress = 0.0; pd->duration = 0.0; + pd->repeat_mode = EFL_ANIMATION_INSTANCE_REPEAT_MODE_RESTART; pd->repeat_count = 0; pd->deleted = EINA_FALSE; @@ -577,6 +644,9 @@ EOAPI EFL_FUNC_BODY_CONST(efl_animation_instance_duration_get, double, 0); EOAPI EFL_VOID_FUNC_BODYV(efl_animation_instance_start_delay_set, EFL_FUNC_CALL(delay_time), double delay_time); EOAPI EFL_FUNC_BODY_CONST(efl_animation_instance_start_delay_get, double, 0); +EOAPI EFL_VOID_FUNC_BODYV(efl_animation_instance_repeat_mode_set, EFL_FUNC_CALL(mode), Efl_Animation_Instance_Repeat_Mode mode); +EOAPI EFL_FUNC_BODY_CONST(efl_animation_instance_repeat_mode_get, Efl_Animation_Instance_Repeat_Mode, 0); + EOAPI EFL_VOID_FUNC_BODYV(efl_animation_instance_repeat_count_set, EFL_FUNC_CALL(count), int count); EOAPI EFL_FUNC_BODY_CONST(efl_animation_instance_repeat_count_get, int, 0); @@ -584,6 +654,8 @@ EOAPI EFL_FUNC_BODY(efl_animation_instance_is_deleted, Eina_Bool, 0); EOAPI EFL_VOID_FUNC_BODY(efl_animation_instance_member_start); +EOAPI EFL_VOID_FUNC_BODY(efl_animation_instance_reverse_member_start); + EOAPI EFL_VOID_FUNC_BODY(efl_animation_instance_map_reset); EOAPI EFL_VOID_FUNC_BODY(efl_animation_instance_final_state_show); @@ -604,10 +676,13 @@ EWAPI const Efl_Event_Description _EFL_ANIMATION_INSTANCE_EVENT_POST_END = EFL_OBJECT_OP_FUNC(efl_animation_instance_duration_get, _efl_animation_instance_duration_get), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_start_delay_set, _efl_animation_instance_start_delay_set), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_start_delay_get, _efl_animation_instance_start_delay_get), \ + EFL_OBJECT_OP_FUNC(efl_animation_instance_repeat_mode_set, _efl_animation_instance_repeat_mode_set), \ + EFL_OBJECT_OP_FUNC(efl_animation_instance_repeat_mode_get, _efl_animation_instance_repeat_mode_get), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_repeat_count_set, _efl_animation_instance_repeat_count_set), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_repeat_count_get, _efl_animation_instance_repeat_count_get), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_is_deleted, _efl_animation_instance_is_deleted), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_member_start, _efl_animation_instance_member_start), \ + EFL_OBJECT_OP_FUNC(efl_animation_instance_reverse_member_start, _efl_animation_instance_reverse_member_start), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_map_reset, _efl_animation_instance_map_reset), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_final_state_show, NULL) diff --git a/src/lib/evas/canvas/efl_animation_instance_group_parallel.c b/src/lib/evas/canvas/efl_animation_instance_group_parallel.c index 6a2d4b8e68..47d300e52c 100644 --- a/src/lib/evas/canvas/efl_animation_instance_group_parallel.c +++ b/src/lib/evas/canvas/efl_animation_instance_group_parallel.c @@ -22,8 +22,6 @@ struct _Evas_Object_Animation_Instance_Group_Parallel_Data { - Ecore_Animator *start_animator; - Ecore_Timer *start_delay_timer; double start_delay_time; @@ -34,10 +32,14 @@ struct _Evas_Object_Animation_Instance_Group_Parallel_Data Eina_List *finished_inst_list; Eina_Bool started : 1; + Eina_Bool reverse_started : 1; Eina_Bool paused : 1; Eina_Bool is_group_member : 1; + Eina_Bool direction_forward : 1; }; +static void _parallel_animation_start(Eo *eo_obj, Evas_Object_Animation_Instance_Group_Parallel_Data *pd); + static void _pre_animate_cb(void *data, const Efl_Event *event) { @@ -45,7 +47,13 @@ _pre_animate_cb(void *data, const Efl_Event *event) EFL_ANIMATION_INSTANCE_GROUP_PARALLEL_DATA_GET(eo_obj, pd); - if (pd->animate_inst_index == 0) + /* animate_inst_index should be increased before any other operation in this + * function. + * Because _pre_animate_cb() could call _pre_animate_cb() recursively. + */ + pd->animate_inst_index++; + + if (pd->animate_inst_index == 1) { //pre animate event is supported within class only (protected event) efl_event_callback_call(eo_obj, @@ -78,36 +86,10 @@ _pre_animate_cb(void *data, const Efl_Event *event) } } - pd->animate_inst_index++; - if (pd->animate_inst_index >= pd->animate_inst_count) pd->animate_inst_index = 0; } -static Eina_Bool -_start_animator_cb(void *data) -{ - Eo *eo_obj = data; - - EFL_ANIMATION_INSTANCE_GROUP_PARALLEL_DATA_GET(eo_obj, pd); - - Eina_List *instances = - efl_animation_instance_group_instances_get(eo_obj); - Eina_List *l; - Efl_Animation *inst; - - EINA_LIST_FOREACH(instances, l, inst) - { - //Data should be registered before animation instance starts - efl_animation_instance_member_start(inst); - pd->animate_inst_count++; - } - - pd->start_animator = NULL; - - return ECORE_CALLBACK_CANCEL; -} - static void _post_end_cb(void *data, const Efl_Event *event) { @@ -115,11 +97,20 @@ _post_end_cb(void *data, const Efl_Event *event) EFL_ANIMATION_INSTANCE_GROUP_PARALLEL_DATA_GET(eo_obj, pd); - //Save finished instances - if (!eina_list_data_find(pd->finished_inst_list, event->object)) + if (pd->direction_forward) { - pd->finished_inst_list - = eina_list_append(pd->finished_inst_list, event->object); + //Save finished instances + if (!eina_list_data_find(pd->finished_inst_list, event->object)) + { + pd->finished_inst_list + = eina_list_append(pd->finished_inst_list, event->object); + } + } + else + { + //Remove the finished instance from the finished instance list + pd->finished_inst_list = + eina_list_remove(pd->finished_inst_list, event->object); } //member post end event is supported within class only (protected event) @@ -137,21 +128,85 @@ _post_end_cb(void *data, const Efl_Event *event) pd->remaining_repeat_count--; if (pd->remaining_repeat_count >= 0) { - eina_list_free(pd->finished_inst_list); - pd->finished_inst_list = NULL; + if (efl_animation_instance_repeat_mode_get(eo_obj) == + EFL_ANIMATION_INSTANCE_REPEAT_MODE_REVERSE) + pd->direction_forward = !pd->direction_forward; + + if (pd->direction_forward) + { + eina_list_free(pd->finished_inst_list); + pd->finished_inst_list = NULL; + } + else + { + Eina_List *l; + Eina_List *l_next; + Efl_Animation_Instance *inst; + /* The finished instances should be removed from the + * finished instance list because the finished instances + * will be animated from the next animation frmae by + * calling reverse_member_start(). + * However, group animation instances may have more than + * one member animation instances. So the member + * animation instances except the last member animation + * instance should be remained as finished instances. + */ + EINA_LIST_FOREACH_SAFE(pd->finished_inst_list, l, l_next, inst) + { + const char *inst_class = efl_class_name_get(inst); + const char *group_class = "Efl.Animation.Instance.Group"; + int class_len = strlen(group_class); + if (!inst_class || strncmp(inst_class, group_class, class_len)) + { + pd->finished_inst_list = + eina_list_remove_list(pd->finished_inst_list, l); + } + } + } + _parallel_animation_start(eo_obj, pd); - pd->start_animator = ecore_animator_add(_start_animator_cb, - eo_obj); return; } } else if (repeat_count == -1) { - eina_list_free(pd->finished_inst_list); - pd->finished_inst_list = NULL; + if (efl_animation_instance_repeat_mode_get(eo_obj) == + EFL_ANIMATION_INSTANCE_REPEAT_MODE_REVERSE) + pd->direction_forward = !pd->direction_forward; + + if (pd->direction_forward) + { + eina_list_free(pd->finished_inst_list); + pd->finished_inst_list = NULL; + } + else + { + Eina_List *l; + Eina_List *l_next; + Efl_Animation_Instance *inst; + /* The finished instances should be removed from the + * finished instance list because the finished instances + * will be animated from the next animation frmae by + * calling reverse_member_start(). + * However, group animation instances may have more than + * one member animation instances. So the member + * animation instances except the last member animation + * instance should be remained as finished instances. + */ + EINA_LIST_FOREACH_SAFE(pd->finished_inst_list, l, l_next, inst) + { + const char *inst_class = efl_class_name_get(inst); + const char *group_class = "Efl.Animation.Instance.Group"; + int class_len = strlen(group_class); + if (!inst_class || strncmp(inst_class, group_class, class_len)) + { + pd->finished_inst_list = + eina_list_remove_list(pd->finished_inst_list, l); + } + } + } + _parallel_animation_start(eo_obj, pd); - pd->start_animator = ecore_animator_add(_start_animator_cb, - eo_obj); return; } @@ -169,11 +224,20 @@ _member_post_end_cb(void *data, const Efl_Event *event) EFL_ANIMATION_INSTANCE_GROUP_PARALLEL_DATA_GET(eo_obj, pd); - //Save finished instances - if (!eina_list_data_find(pd->finished_inst_list, event->object)) + if (pd->direction_forward) { - pd->finished_inst_list - = eina_list_append(pd->finished_inst_list, event->object); + //Save finished instances + if (!eina_list_data_find(pd->finished_inst_list, event->object)) + { + pd->finished_inst_list + = eina_list_append(pd->finished_inst_list, event->object); + } + } + else + { + //Remove the finished instance from the finished instance list + pd->finished_inst_list = + eina_list_remove(pd->finished_inst_list, event->object); } //member post end event is supported within class only (protected event) @@ -183,11 +247,36 @@ _member_post_end_cb(void *data, const Efl_Event *event) } static void -_init_start(Eo *eo_obj, Evas_Object_Animation_Instance_Group_Parallel_Data *pd) +_parallel_animation_start(Eo *eo_obj, + Evas_Object_Animation_Instance_Group_Parallel_Data *pd) { - ecore_animator_del(pd->start_animator); - pd->start_animator = NULL; + Eina_List *instances = efl_animation_instance_group_instances_get(eo_obj); + Eina_List *l; + Efl_Animation *inst; + + pd->animate_inst_count = eina_list_count(instances); + + if (pd->direction_forward) + { + EINA_LIST_FOREACH(instances, l, inst) + { + //Data should be registered before animation instance starts + efl_animation_instance_member_start(inst); + } + } + else + { + EINA_LIST_REVERSE_FOREACH(instances, l, inst) + { + //Data should be registered before animation instance starts + efl_animation_instance_reverse_member_start(inst); + } + } +} +static void +_init_start(Eo *eo_obj, Evas_Object_Animation_Instance_Group_Parallel_Data *pd) +{ pd->animate_inst_count = 0; pd->animate_inst_index = 0; @@ -198,6 +287,40 @@ _init_start(Eo *eo_obj, Evas_Object_Animation_Instance_Group_Parallel_Data *pd) eina_list_free(pd->finished_inst_list); pd->finished_inst_list = NULL; + if (pd->reverse_started) + { + Eina_List *instances = + efl_animation_instance_group_instances_get(eo_obj); + pd->finished_inst_list = eina_list_clone(instances); + + Eina_List *l; + Eina_List *l_next; + Efl_Animation_Instance *inst; + /* The finished instances should be removed from the + * finished instance list because the finished instances + * will be animated from the next animation frmae by + * calling reverse_member_start(). + * However, group animation instances may have more than + * one member animation instances. So the member + * animation instances except the last member animation + * instance should be remained as finished instances. + */ + EINA_LIST_FOREACH_SAFE(pd->finished_inst_list, l, l_next, inst) + { + const char *inst_class = efl_class_name_get(inst); + const char *group_class = "Efl.Animation.Instance.Group"; + int class_len = strlen(group_class); + if (!inst_class || strncmp(inst_class, group_class, class_len)) + { + pd->finished_inst_list = + eina_list_remove_list(pd->finished_inst_list, l); + } + } + pd->direction_forward = EINA_FALSE; + } + else + pd->direction_forward = EINA_TRUE; + efl_event_callback_call(eo_obj, EFL_ANIMATION_INSTANCE_EVENT_START, NULL); } @@ -206,15 +329,7 @@ _start(Eo *eo_obj, Evas_Object_Animation_Instance_Group_Parallel_Data *pd) { _init_start(eo_obj, pd); - Eina_List *instances = efl_animation_instance_group_instances_get(eo_obj); - Eina_List *l; - Efl_Animation *inst; - EINA_LIST_FOREACH(instances, l, inst) - { - //Data should be registered before animation instance starts - efl_animation_instance_member_start(inst); - pd->animate_inst_count++; - } + _parallel_animation_start(eo_obj, pd); } static Eina_Bool @@ -244,6 +359,7 @@ _efl_animation_instance_group_parallel_efl_animation_instance_start(Eo *eo_obj, if (pd->start_delay_timer) return; pd->is_group_member = EINA_FALSE; + pd->reverse_started = EINA_FALSE; if (pd->start_delay_time > 0.0) { @@ -266,6 +382,30 @@ _efl_animation_instance_group_parallel_efl_animation_instance_member_start(Eo *e if (pd->start_delay_timer) return; pd->is_group_member = EINA_TRUE; + pd->reverse_started = EINA_FALSE; + + if (pd->start_delay_time > 0.0) + { + pd->start_delay_timer = ecore_timer_add(pd->start_delay_time, + _start_delay_timer_cb, eo_obj); + return; + } + + _start(eo_obj, pd); +} + +EOLIAN static void +_efl_animation_instance_group_parallel_efl_animation_instance_reverse_member_start(Eo *eo_obj, + Evas_Object_Animation_Instance_Group_Parallel_Data *pd) +{ + EFL_ANIMATION_INSTANCE_GROUP_PARALLEL_CHECK_OR_RETURN(eo_obj); + + if (pd->paused) return; + + if (pd->start_delay_timer) return; + + pd->is_group_member = EINA_TRUE; + pd->reverse_started = EINA_TRUE; if (pd->start_delay_time > 0.0) { @@ -409,6 +549,7 @@ _efl_animation_instance_group_parallel_efl_animation_instance_group_instance_del #define EFL_ANIMATION_INSTANCE_GROUP_PARALLEL_EXTRA_OPS \ EFL_OBJECT_OP_FUNC(efl_animation_instance_member_start, _efl_animation_instance_group_parallel_efl_animation_instance_member_start), \ + EFL_OBJECT_OP_FUNC(efl_animation_instance_reverse_member_start, _efl_animation_instance_group_parallel_efl_animation_instance_reverse_member_start), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_final_state_show, _efl_animation_instance_group_parallel_efl_animation_instance_final_state_show), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_group_instance_add, _efl_animation_instance_group_parallel_efl_animation_instance_group_instance_add), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_group_instance_del, _efl_animation_instance_group_parallel_efl_animation_instance_group_instance_del), \ diff --git a/src/lib/evas/canvas/efl_animation_instance_group_sequential.c b/src/lib/evas/canvas/efl_animation_instance_group_sequential.c index 65148de055..c488296035 100644 --- a/src/lib/evas/canvas/efl_animation_instance_group_sequential.c +++ b/src/lib/evas/canvas/efl_animation_instance_group_sequential.c @@ -22,23 +22,23 @@ struct _Evas_Object_Animation_Instance_Group_Sequential_Data { - Ecore_Animator *start_animator; - Ecore_Timer *start_delay_timer; double start_delay_time; - unsigned int current_index; + int current_index; int remaining_repeat_count; Eina_List *finished_inst_list; Eina_Bool started : 1; + Eina_Bool reverse_started : 1; Eina_Bool paused : 1; Eina_Bool is_group_member : 1; + Eina_Bool direction_forward : 1; }; -static void _index_animation_start(Eo *eo_obj, int index); +static void _index_animation_start(Eo *eo_obj, int index, Eina_Bool direction_forward); static void _pre_animate_cb(void *data, const Efl_Event *event) @@ -68,20 +68,6 @@ _pre_animate_cb(void *data, const Efl_Event *event) } } -static Eina_Bool -_start_animator_cb(void *data) -{ - Eo *eo_obj = data; - - EFL_ANIMATION_INSTANCE_GROUP_SEQUENTIAL_DATA_GET(eo_obj, pd); - - _index_animation_start(eo_obj, pd->current_index); - - pd->start_animator = NULL; - - return ECORE_CALLBACK_CANCEL; -} - static void _post_end_cb(void *data, const Efl_Event *event) { @@ -89,11 +75,50 @@ _post_end_cb(void *data, const Efl_Event *event) EFL_ANIMATION_INSTANCE_GROUP_SEQUENTIAL_DATA_GET(eo_obj, pd); - //Save finished instances - if (!eina_list_data_find(pd->finished_inst_list, event->object)) + if (pd->direction_forward) { - pd->finished_inst_list - = eina_list_append(pd->finished_inst_list, event->object); + //Save finished instances + if (!eina_list_data_find(pd->finished_inst_list, event->object)) + { + pd->finished_inst_list + = eina_list_append(pd->finished_inst_list, event->object); + } + } + else + { + /* Remove the finished instance from the finished instance list. + * In this case, the finished instance is group instance. + */ + pd->finished_inst_list = + eina_list_remove(pd->finished_inst_list, event->object); + + /* The last finished instance should be removed from the + * finished instance list because the last finished + * instance will be animated from the next animation + * frame by calling reverse_member_start(). + * However, group animation instances may have more than + * one member animation instances. So the member + * animation instances except the last member animation + * instance should be remained as finished instances. + */ + Efl_Animation_Instance *last_inst = NULL; + + Eina_List *last_inst_list = + eina_list_last(pd->finished_inst_list); + if (last_inst_list) + last_inst = eina_list_data_get(last_inst_list); + + if (last_inst) + { + const char *inst_class = efl_class_name_get(last_inst); + const char *group_class = "Efl.Animation.Instance.Group"; + int class_len = strlen(group_class); + if (!inst_class || strncmp(inst_class, group_class, class_len)) + { + pd->finished_inst_list = + eina_list_remove(pd->finished_inst_list, last_inst); + } + } } //member post end event is supported within class only (protected event) @@ -101,30 +126,122 @@ _post_end_cb(void *data, const Efl_Event *event) EFL_ANIMATION_INSTANCE_GROUP_EVENT_MEMBER_POST_END, NULL); - pd->current_index++; + if (pd->direction_forward) + pd->current_index++; + else + pd->current_index--; Eina_List *instances = efl_animation_instance_group_instances_get(eo_obj); - if (eina_list_count(instances) == pd->current_index) + + Eina_Bool group_finished = EINA_FALSE; + if (pd->direction_forward) { - pd->current_index = 0; + if ((int)eina_list_count(instances) == pd->current_index) + group_finished = EINA_TRUE; + } + else + { + if (pd->current_index < 0) + group_finished = EINA_TRUE; + } + if (group_finished) + { int repeat_count = efl_animation_instance_repeat_count_get(eo_obj); if (repeat_count > 0) { pd->remaining_repeat_count--; if (pd->remaining_repeat_count >= 0) { - eina_list_free(pd->finished_inst_list); - pd->finished_inst_list = NULL; - + if (efl_animation_instance_repeat_mode_get(eo_obj) == + EFL_ANIMATION_INSTANCE_REPEAT_MODE_REVERSE) + pd->direction_forward = !pd->direction_forward; + + if (pd->direction_forward) + { + eina_list_free(pd->finished_inst_list); + pd->finished_inst_list = NULL; + + pd->current_index = 0; + } + else + { + /* The last finished instance should be removed from the + * finished instance list because the last finished + * instance will be animated from the next animation + * frame by calling reverse_member_start(). + * However, group animation instances may have more than + * one member animation instances. So the member + * animation instances except the last member animation + * instance should be remained as finished instances. + */ + Efl_Animation_Instance *last_inst = NULL; + + Eina_List *last_inst_list = + eina_list_last(pd->finished_inst_list); + if (last_inst_list) + last_inst = eina_list_data_get(last_inst_list); + + if (last_inst) + { + const char *inst_class = efl_class_name_get(last_inst); + const char *group_class = "Efl.Animation.Instance.Group"; + int class_len = strlen(group_class); + if (!inst_class || strncmp(inst_class, group_class, class_len)) + { + pd->finished_inst_list = + eina_list_remove(pd->finished_inst_list, last_inst); + } + } + pd->current_index = eina_list_count(instances) - 1; + } goto next_start; } } else if (repeat_count == -1) { - eina_list_free(pd->finished_inst_list); - pd->finished_inst_list = NULL; + if (efl_animation_instance_repeat_mode_get(eo_obj) == + EFL_ANIMATION_INSTANCE_REPEAT_MODE_REVERSE) + pd->direction_forward = !pd->direction_forward; + + if (pd->direction_forward) + { + eina_list_free(pd->finished_inst_list); + pd->finished_inst_list = NULL; + pd->current_index = 0; + } + else + { + /* The last finished instance should be removed from the + * finished instance list because the last finished + * instance will be animated from the next animation + * frame by calling reverse_member_start(). + * However, group animation instances may have more than + * one member animation instances. So the member + * animation instances except the last member animation + * instance should be remained as finished instances. + */ + Efl_Animation_Instance *last_inst = NULL; + + Eina_List *last_inst_list = + eina_list_last(pd->finished_inst_list); + if (last_inst_list) + last_inst = eina_list_data_get(last_inst_list); + + if (last_inst) + { + const char *inst_class = efl_class_name_get(last_inst); + const char *group_class = "Efl.Animation.Instance.Group"; + int class_len = strlen(group_class); + if (!inst_class || strncmp(inst_class, group_class, class_len)) + { + pd->finished_inst_list = + eina_list_remove(pd->finished_inst_list, last_inst); + } + } + pd->current_index = eina_list_count(instances) - 1; + } goto next_start; } @@ -136,7 +253,7 @@ _post_end_cb(void *data, const Efl_Event *event) } next_start: - pd->start_animator = ecore_animator_add(_start_animator_cb, eo_obj); + _index_animation_start(eo_obj, pd->current_index, pd->direction_forward); } static void @@ -152,6 +269,11 @@ _member_post_end_cb(void *data, const Efl_Event *event) pd->finished_inst_list = eina_list_append(pd->finished_inst_list, event->object); } + /* The finished instance in this function is a group instance. + * Since a group instance should not be removed before the group instance is + * finally finished, the finished instance should be removed only in + * _post_end_cb() function. + */ //member post end event is supported within class only (protected event) efl_event_callback_call(eo_obj, @@ -160,24 +282,22 @@ _member_post_end_cb(void *data, const Efl_Event *event) } static void -_index_animation_start(Eo *eo_obj, int index) +_index_animation_start(Eo *eo_obj, int index, Eina_Bool direction_forward) { Efl_Animation_Instance *inst = eina_list_nth(efl_animation_instance_group_instances_get(eo_obj), index); if (!inst || efl_animation_instance_is_deleted(inst)) return; - efl_animation_instance_member_start(inst); + if (direction_forward) + efl_animation_instance_member_start(inst); + else + efl_animation_instance_reverse_member_start(inst); } static void _init_start(Eo *eo_obj, Evas_Object_Animation_Instance_Group_Sequential_Data *pd) { - ecore_animator_del(pd->start_animator); - pd->start_animator = NULL; - - pd->current_index = 0; - pd->started = EINA_TRUE; pd->remaining_repeat_count = efl_animation_instance_repeat_count_get(eo_obj); @@ -185,6 +305,50 @@ _init_start(Eo *eo_obj, Evas_Object_Animation_Instance_Group_Sequential_Data *pd eina_list_free(pd->finished_inst_list); pd->finished_inst_list = NULL; + if (pd->reverse_started) + { + Eina_List *instances = + efl_animation_instance_group_instances_get(eo_obj); + pd->finished_inst_list = eina_list_clone(instances); + + /* The last finished instance should be removed from the + * finished instance list because the last finished + * instance will be animated from the next animation + * frame by calling reverse_member_start(). + * However, group animation instances may have more than + * one member animation instances. So the member + * animation instances except the last member animation + * instance should be remained as finished instances. + */ + Efl_Animation_Instance *last_inst = NULL; + + Eina_List *last_inst_list = + eina_list_last(pd->finished_inst_list); + if (last_inst_list) + last_inst = eina_list_data_get(last_inst_list); + + if (last_inst) + { + const char *inst_class = efl_class_name_get(last_inst); + const char *group_class = "Efl.Animation.Instance.Group"; + int class_len = strlen(group_class); + if (!inst_class || strncmp(inst_class, group_class, class_len)) + { + pd->finished_inst_list = + eina_list_remove(pd->finished_inst_list, last_inst); + } + } + pd->current_index = eina_list_count(instances) - 1; + + pd->direction_forward = EINA_FALSE; + } + else + { + pd->current_index = 0; + + pd->direction_forward = EINA_TRUE; + } + efl_event_callback_call(eo_obj, EFL_ANIMATION_INSTANCE_EVENT_START, NULL); } @@ -193,7 +357,7 @@ _start(Eo *eo_obj, Evas_Object_Animation_Instance_Group_Sequential_Data *pd) { _init_start(eo_obj, pd); - _index_animation_start(eo_obj, pd->current_index); + _index_animation_start(eo_obj, pd->current_index, pd->direction_forward); } static Eina_Bool @@ -223,6 +387,7 @@ _efl_animation_instance_group_sequential_efl_animation_instance_start(Eo *eo_obj if (pd->start_delay_timer) return; pd->is_group_member = EINA_FALSE; + pd->reverse_started = EINA_FALSE; if (pd->start_delay_time > 0.0) { @@ -245,6 +410,30 @@ _efl_animation_instance_group_sequential_efl_animation_instance_member_start(Eo if (pd->start_delay_timer) return; pd->is_group_member = EINA_TRUE; + pd->reverse_started = EINA_FALSE; + + if (pd->start_delay_time > 0.0) + { + pd->start_delay_timer = ecore_timer_add(pd->start_delay_time, + _start_delay_timer_cb, eo_obj); + return; + } + + _start(eo_obj, pd); +} + +EOLIAN static void +_efl_animation_instance_group_sequential_efl_animation_instance_reverse_member_start(Eo *eo_obj, + Evas_Object_Animation_Instance_Group_Sequential_Data *pd) +{ + EFL_ANIMATION_INSTANCE_GROUP_SEQUENTIAL_CHECK_OR_RETURN(eo_obj); + + if (pd->paused) return; + + if (pd->start_delay_timer) return; + + pd->is_group_member = EINA_TRUE; + pd->reverse_started = EINA_TRUE; if (pd->start_delay_time > 0.0) { @@ -388,6 +577,7 @@ _efl_animation_instance_group_sequential_efl_animation_instance_final_state_show #define EFL_ANIMATION_INSTANCE_GROUP_SEQUENTIAL_EXTRA_OPS \ EFL_OBJECT_OP_FUNC(efl_animation_instance_member_start, _efl_animation_instance_group_sequential_efl_animation_instance_member_start), \ + EFL_OBJECT_OP_FUNC(efl_animation_instance_reverse_member_start, _efl_animation_instance_group_sequential_efl_animation_instance_reverse_member_start), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_final_state_show, _efl_animation_instance_group_sequential_efl_animation_instance_final_state_show), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_group_instance_add, _efl_animation_instance_group_sequential_efl_animation_instance_group_instance_add), \ EFL_OBJECT_OP_FUNC(efl_animation_instance_group_instance_del, _efl_animation_instance_group_sequential_efl_animation_instance_group_instance_del), \ diff --git a/src/lib/evas/canvas/efl_animation_rotate.c b/src/lib/evas/canvas/efl_animation_rotate.c index 9696b47b26..31481ece69 100644 --- a/src/lib/evas/canvas/efl_animation_rotate.c +++ b/src/lib/evas/canvas/efl_animation_rotate.c @@ -241,6 +241,9 @@ _efl_animation_rotate_efl_animation_instance_create(Eo *eo_obj, double start_delay_time = efl_animation_start_delay_get(eo_obj); efl_animation_instance_start_delay_set(instance, start_delay_time); + Efl_Animation_Repeat_Mode repeat_mode = efl_animation_repeat_mode_get(eo_obj); + efl_animation_instance_repeat_mode_set(instance, (Efl_Animation_Instance_Repeat_Mode)repeat_mode); + int repeat_count = efl_animation_repeat_count_get(eo_obj); efl_animation_instance_repeat_count_set(instance, repeat_count); diff --git a/src/lib/evas/canvas/efl_animation_scale.c b/src/lib/evas/canvas/efl_animation_scale.c index a6f6c43825..4c37500abc 100644 --- a/src/lib/evas/canvas/efl_animation_scale.c +++ b/src/lib/evas/canvas/efl_animation_scale.c @@ -267,6 +267,9 @@ _efl_animation_scale_efl_animation_instance_create(Eo *eo_obj, double start_delay_time = efl_animation_start_delay_get(eo_obj); efl_animation_instance_start_delay_set(instance, start_delay_time); + Efl_Animation_Repeat_Mode repeat_mode = efl_animation_repeat_mode_get(eo_obj); + efl_animation_instance_repeat_mode_set(instance, (Efl_Animation_Instance_Repeat_Mode)repeat_mode); + int repeat_count = efl_animation_repeat_count_get(eo_obj); efl_animation_instance_repeat_count_set(instance, repeat_count); diff --git a/src/lib/evas/canvas/efl_animation_translate.c b/src/lib/evas/canvas/efl_animation_translate.c index a336ce9072..7e255204fb 100644 --- a/src/lib/evas/canvas/efl_animation_translate.c +++ b/src/lib/evas/canvas/efl_animation_translate.c @@ -196,6 +196,9 @@ _efl_animation_translate_efl_animation_instance_create(Eo *eo_obj, double start_delay_time = efl_animation_start_delay_get(eo_obj); efl_animation_instance_start_delay_set(instance, start_delay_time); + Efl_Animation_Repeat_Mode repeat_mode = efl_animation_repeat_mode_get(eo_obj); + efl_animation_instance_repeat_mode_set(instance, (Efl_Animation_Instance_Repeat_Mode)repeat_mode); + int repeat_count = efl_animation_repeat_count_get(eo_obj); efl_animation_instance_repeat_count_set(instance, repeat_count); diff --git a/src/lib/evas/canvas/efl_animation_types.eot b/src/lib/evas/canvas/efl_animation_types.eot index b16e73056b..720f0dc269 100644 --- a/src/lib/evas/canvas/efl_animation_types.eot +++ b/src/lib/evas/canvas/efl_animation_types.eot @@ -11,4 +11,12 @@ enum Efl.Animation.Event_Type hide, [["hide" event type]] clicked, [["clicked" event type]] count [[total count of event type]] +} + +enum Efl.Animation.Repeat_Mode +{ + [[Animation repeat mode]] + + restart = 0, [[Restart animation when the animation ends.]] + reverse [[Reverse animation when the animation ends.]] }
\ No newline at end of file |