introduce efl_canvas_object_animation

this brings the animation to the canvas object. All the controls of the
animation now do now require a player object anymore, you can just use
the API that is directly on the Efl.Canvas.Object object.

wip animation player replacement

Differential Revision: https://phab.enlightenment.org/D10615
This commit is contained in:
Marcel Hollerbach 2019-11-07 11:24:21 +01:00
parent 9bb2df9966
commit fa93893548
8 changed files with 599 additions and 2 deletions

View File

@ -0,0 +1,179 @@
/**
* Example of animation in efl canvas
*
* You'll need at least one engine built for it (excluding the buffer
* one). See stdout/stderr for output.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Ecore.h>
#include <Ecore_Evas.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define WIDTH (640)
#define HEIGHT (480)
struct example_data
{
Ecore_Evas *ee;
Evas *evas;
Evas_Object *bg, *scale;
double current_speed;
};
static struct example_data d;
static Evas_Object * /* new rectangle to be put in the box */
_new_rectangle_add(Evas *e)
{
Efl_Canvas_Rectangle *rect = efl_add(EFL_CANVAS_RECTANGLE_CLASS, e);
efl_gfx_entity_size_set(rect, EINA_SIZE2D(10, 10));
efl_gfx_color_set(rect, 0, 255, 0, 255);
efl_gfx_entity_visible_set(rect, EINA_TRUE);
return rect;
}
/* use the following commands to interact with this example - 'h' is
* the key for help */
static void
_on_keydown(void *data EINA_UNUSED, const Efl_Event *ev)
{
if (strcmp(efl_input_key_sym_get(ev->info) , "r") == 0)
{
Efl_Canvas_Animation *animation = efl_canvas_object_animation_get(d.scale);
double current_pos = efl_canvas_object_animation_progress_get(d.scale);
d.current_speed *= -1;
efl_canvas_object_animation_start(d.scale, animation, d.current_speed, 1.0 - current_pos);
}
if (strcmp(efl_input_key_sym_get(ev->info), "p") == 0)
{
efl_canvas_object_animation_pause_set(d.scale, !efl_canvas_object_animation_pause_get(d.scale));
}
}
static void
_on_delete(Ecore_Evas *ee EINA_UNUSED)
{
ecore_main_loop_quit();
}
static void /* adjust canvas' contents on resizes */
_canvas_resize_cb(Ecore_Evas *ee)
{
int w, h;
ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
efl_gfx_entity_geometry_set(d.bg, EINA_RECT(0, 0, w, h));
}
static void
print_help(void)
{
printf("evas-animation example\n Press r to reverse the animation of the red rect.\n Press p to pause the animation of the red rect.\n");
}
int
main(void)
{
if (!ecore_evas_init())
return EXIT_FAILURE;
/* this will give you a window with an Evas canvas under the first
* engine available */
d.ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
if (!d.ee)
goto panic;
print_help();
ecore_evas_name_class_set(d.ee, "Evas Animation example", "Evas Animation Example");
ecore_evas_callback_delete_request_set(d.ee, _on_delete);
ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
ecore_evas_show(d.ee);
d.evas = ecore_evas_get(d.ee);
d.bg = _new_rectangle_add(d.evas);
efl_gfx_color_set(d.bg, 255, 255, 255, 255);
efl_gfx_entity_visible_set(d.bg, EINA_TRUE);
efl_canvas_object_key_focus_set(d.bg, EINA_TRUE);
efl_event_callback_add(d.bg, EFL_EVENT_KEY_DOWN, _on_keydown, NULL);
_canvas_resize_cb(d.ee);
Evas_Object *scale_rect = _new_rectangle_add(d.evas);
efl_gfx_entity_geometry_set(scale_rect, EINA_RECT(50, 50, 50, 50));
efl_canvas_object_animation_start(scale_rect,
efl_new(EFL_CANVAS_ANIMATION_SCALE_CLASS,
efl_animation_scale_set(efl_added, EINA_VECTOR2(1.0, 1.0), EINA_VECTOR2(3.0, 3.0), scale_rect, EINA_VECTOR2(0.5, 0.5)),
efl_animation_start_delay_set(efl_added, 5.0),
efl_animation_duration_set(efl_added, 2.0),
efl_animation_repeat_count_set(efl_added, EFL_ANIMATION_REPEAT_INFINITE)
),
1.0, 0.0);
Evas_Object *scale_rect2 = _new_rectangle_add(d.evas);
efl_gfx_entity_geometry_set(scale_rect2, EINA_RECT(50, 200, 50, 50));
efl_canvas_object_animation_start(scale_rect2,
efl_new(EFL_CANVAS_ANIMATION_SCALE_CLASS,
efl_animation_scale_set(efl_added, EINA_VECTOR2(1.0, 1.0), EINA_VECTOR2(3.0, 3.0), scale_rect2, EINA_VECTOR2(0.5, 0.5)),
efl_animation_duration_set(efl_added, 2.0),
efl_animation_repeat_count_set(efl_added, EFL_ANIMATION_REPEAT_INFINITE),
efl_animation_repeat_mode_set(efl_added, EFL_CANVAS_ANIMATION_REPEAT_MODE_REVERSE)
),
1.0, 0.0);
Evas_Object *scale_rect3 = _new_rectangle_add(d.evas);
efl_gfx_entity_geometry_set(scale_rect3, EINA_RECT(50, 350, 50, 50));
efl_canvas_object_animation_start(scale_rect3,
efl_new(EFL_CANVAS_ANIMATION_SCALE_CLASS,
efl_animation_scale_set(efl_added, EINA_VECTOR2(1.0, 1.0), EINA_VECTOR2(3.0, 3.0), scale_rect3, EINA_VECTOR2(0.5, 0.5)),
efl_animation_duration_set(efl_added, 2.0),
efl_animation_repeat_count_set(efl_added, 3),
efl_animation_repeat_mode_set(efl_added, EFL_CANVAS_ANIMATION_REPEAT_MODE_REVERSE)
),
1.0, 0.0);
Evas_Object *scale_rect4 = _new_rectangle_add(d.evas);
efl_gfx_entity_geometry_set(scale_rect4, EINA_RECT(200, 50, 50, 50));
efl_canvas_object_animation_start(scale_rect4,
efl_new(EFL_CANVAS_ANIMATION_SCALE_CLASS,
efl_animation_scale_set(efl_added, EINA_VECTOR2(1.0, 1.0), EINA_VECTOR2(3.0, 3.0), scale_rect4, EINA_VECTOR2(0.5, 0.5)),
efl_animation_duration_set(efl_added, 2.0),
efl_animation_final_state_keep_set(efl_added, EINA_TRUE)
),
1.0, 0.0);
Evas_Object *scale_rect5 = d.scale = _new_rectangle_add(d.evas);
efl_gfx_color_set(scale_rect5, 255, 0, 0, 255);
efl_gfx_entity_geometry_set(scale_rect5, EINA_RECT(200, 200, 50, 50));
efl_canvas_object_animation_start(scale_rect5,
efl_new(EFL_CANVAS_ANIMATION_SCALE_CLASS,
efl_animation_scale_set(efl_added, EINA_VECTOR2(1.0, 1.0), EINA_VECTOR2(5.0, 5.0), scale_rect5, EINA_VECTOR2(0.5, 0.5)),
efl_animation_duration_set(efl_added, 5.0),
efl_animation_repeat_count_set(efl_added, EFL_ANIMATION_REPEAT_INFINITE)
),
1.0, 0.0);
d.current_speed = 1.0;
ecore_main_loop_begin();
ecore_evas_shutdown();
return 0;
panic:
fprintf(stderr, "error: Requires at least one Evas engine built and linked"
" to ecore-evas for this example to run properly.\n");
return -2;
}

View File

@ -50,6 +50,7 @@ examples = [
'evas-vg-batman',
'evas-vg-simple',
'evas-vg-json',
'efl-canvas-animation',
]
foreach example : examples

View File

@ -223,7 +223,7 @@ struct _Efl_Canvas_Object_Animation_Event
#include "gesture/efl_gesture_events.eo.h"
#include "canvas/efl_canvas_object.eo.h"
#include "canvas/efl_canvas_object_animation.eo.h"
#include "canvas/efl_canvas_animation.eo.h"
#include "canvas/efl_canvas_animation_alpha.eo.h"
#include "canvas/efl_canvas_animation_rotate.eo.h"

View File

@ -11,7 +11,7 @@ struct Efl.Event_Animator_Tick {
abstract Efl.Canvas.Object extends Efl.Loop_Consumer implements Efl.Gfx.Entity, Efl.Gfx.Color, Efl.Gfx.Stack,
Efl.Input.Interface, Efl.Gfx.Hint,
Efl.Gfx.Mapping, Efl.Canvas.Pointer, Efl.Gesture.Events
Efl.Gfx.Mapping, Efl.Canvas.Pointer, Efl.Gesture.Events, Efl.Canvas.Object_Animation
{
[[Efl canvas object abstract class

View File

@ -0,0 +1,197 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "evas_common_private.h"
#include "evas_private.h"
#include "efl_canvas_object_animation.eo.h"
#include <Ecore.h>
#define MY_CLASS EFL_CANVAS_OBJECT_ANIMATION_MIXIN
typedef struct
{
Efl_Canvas_Animation *animation;
double speed;
double progress;
double run_start_time;
double start_pos;
int remaining_repeats;
Efl_Loop_Timer *timer;
Eina_Bool pause_state : 1;
} Efl_Canvas_Object_Animation_Indirect_Data;
typedef struct
{
Efl_Canvas_Object_Animation_Indirect_Data *in;
} Efl_Canvas_Object_Animation_Data;
static void _end(Efl_Canvas_Object_Animation *obj, Efl_Canvas_Object_Animation_Data *pd);
static void
_animator_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
Eo *obj = data;
Efl_Canvas_Object_Animation_Data *pd = efl_data_scope_get(obj, MY_CLASS);
double duration, elapsed_time, vector, current;
EINA_SAFETY_ON_NULL_RETURN(pd->in);
current = ecore_loop_time_get();
EINA_SAFETY_ON_FALSE_RETURN(pd->in->run_start_time <= current);
duration = efl_animation_duration_get(pd->in->animation) / pd->in->speed;
elapsed_time = current - pd->in->run_start_time;
vector = elapsed_time / duration;
/* When animation player starts, _animator_cb() is called immediately so
* both elapsed time and progress are 0.0.
* Since it is the beginning of the animation if progress is 0.0, the
* following codes for animation should be executed. */
if (pd->in->speed < 0.0)
vector += 1.0;
pd->in->progress = CLAMP(0.0, vector, 1.0);
/* The previously applied map effect should be reset before applying the
* current map effect. Otherwise, the incrementally added map effects
* increase numerical error. */
efl_gfx_mapping_reset(obj);
efl_animation_apply(pd->in->animation, pd->in->progress, obj);
efl_event_callback_call(obj, EFL_CANVAS_OBJECT_ANIMATION_EVENT_ANIMATION_PROGRESS_UPDATED, &pd->in->progress);
//Not end. Keep going.
if ((pd->in->speed < 0 && EINA_DBL_EQ(pd->in->progress, 0)) ||
(pd->in->speed > 0 && EINA_DBL_EQ(pd->in->progress, 1.0)))
{
//Repeat animation
if ((efl_animation_repeat_count_get(pd->in->animation) == EFL_ANIMATION_REPEAT_INFINITE) ||
(pd->in->remaining_repeats > 0))
{
pd->in->remaining_repeats--;
if (efl_animation_repeat_mode_get(pd->in->animation) == EFL_CANVAS_ANIMATION_REPEAT_MODE_REVERSE)
pd->in->speed *= -1;
pd->in->run_start_time = current;
}
else
{
efl_canvas_object_animation_stop(obj);
}
}
}
static void
_end(Efl_Canvas_Object_Animation *obj, Efl_Canvas_Object_Animation_Data *pd)
{
EINA_SAFETY_ON_NULL_RETURN(pd->in);
efl_event_callback_del(obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_cb, obj);
}
static void
_start(Efl_Canvas_Object_Animation *obj, Efl_Canvas_Object_Animation_Data *pd, double delay)
{
EINA_SAFETY_ON_NULL_RETURN(pd->in);
pd->in->run_start_time = ecore_loop_time_get() - efl_animation_duration_get(pd->in->animation)*delay;
efl_event_callback_add(obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_cb, obj);
_animator_cb(obj, NULL);
}
static Eina_Value
_start_fcb(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Efl_Canvas_Object_Animation_Data *pd = efl_data_scope_safe_get(o, MY_CLASS);
if (!pd->in) return v; //animation was stopped before anything started
_start(o, pd, pd->in->start_pos);
return v;
}
EOLIAN static Efl_Canvas_Animation*
_efl_canvas_object_animation_animation_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Object_Animation_Data *pd)
{
if (!pd->in) return NULL;
return pd->in->animation;
}
EOLIAN static double
_efl_canvas_object_animation_animation_progress_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Object_Animation_Data *pd)
{
if (pd->in && pd->in->animation)
return (pd->in->speed < 0) ? fabs(1.0 - pd->in->progress) : pd->in->progress;
else
return -1.0;
}
EOLIAN static void
_efl_canvas_object_animation_animation_pause_set(Eo *obj, Efl_Canvas_Object_Animation_Data *pd, Eina_Bool pause)
{
EINA_SAFETY_ON_NULL_RETURN(pd->in);
if (pd->in->pause_state == pause) return;
if (pause)
_end(obj, pd);
else
_start(obj, pd,(pd->in->speed < 0) ? 1.0 - pd->in->progress : pd->in->progress);
pd->in->pause_state = pause;
}
EOLIAN static Eina_Bool
_efl_canvas_object_animation_animation_pause_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Object_Animation_Data *pd)
{
if (!pd->in) return EINA_FALSE;
return pd->in->pause_state;
}
EOLIAN static void
_efl_canvas_object_animation_animation_start(Eo *obj, Efl_Canvas_Object_Animation_Data *pd, Efl_Canvas_Animation *animation, double speed, double start_pos)
{
Efl_Canvas_Object_Animation_Indirect_Data *in;
if (pd->in && pd->in->animation)
efl_canvas_object_animation_stop(obj);
EINA_SAFETY_ON_FALSE_RETURN(!pd->in);
in = pd->in = calloc(1, sizeof(Efl_Canvas_Object_Animation_Indirect_Data));
EINA_SAFETY_ON_NULL_RETURN(animation);
EINA_SAFETY_ON_FALSE_RETURN(start_pos >= 0.0 && start_pos <= 1.0);
EINA_SAFETY_ON_FALSE_RETURN(!EINA_DBL_EQ(speed, 0.0));
EINA_SAFETY_ON_FALSE_RETURN(efl_playable_seekable_get(animation));
in->pause_state = EINA_FALSE;
in->animation = efl_ref(animation);
in->remaining_repeats = efl_animation_repeat_count_get(animation); // -1 because one run is already going on
in->speed = speed;
in->start_pos = start_pos;
efl_event_callback_call(obj, EFL_CANVAS_OBJECT_ANIMATION_EVENT_ANIMATION_CHANGED, in->animation);
if (efl_animation_start_delay_get(animation) > 0.0)
{
Eina_Future *f = efl_loop_timeout(efl_loop_get(obj), efl_animation_start_delay_get(animation));
efl_future_then(obj, f, .success = _start_fcb);
}
else
_start(obj, pd, start_pos);
}
EOLIAN static void
_efl_canvas_object_animation_animation_stop(Eo *obj, Efl_Canvas_Object_Animation_Data *pd)
{
if (!pd->in) return;
if (!efl_animation_final_state_keep_get(pd->in->animation))
efl_gfx_mapping_reset(obj);
_end(obj, pd);
efl_unref(pd->in->animation);
pd->in->animation = NULL;
efl_event_callback_call(obj, EFL_CANVAS_OBJECT_ANIMATION_EVENT_ANIMATION_CHANGED, pd->in->animation);
free(pd->in);
pd->in = NULL;
}
#include "efl_canvas_object_animation.eo.c"

View File

@ -0,0 +1,60 @@
mixin @beta Efl.Canvas.Object_Animation requires Efl.Object
{
methods {
@property animation {
[[The animation that is currently played on the canvas object.
$null in case that there is no animation running.]]
get {
}
values {
animation : Efl.Canvas.Animation; [[The animation which is currently applied on this object.]]
}
}
@property animation_progress {
[[The current progress of the animation, between 0.0 and 1.0.
Even if the animation is going backwards (speed < 0.0). the progress will still go from 0.0 to 1.0.
If there is no animation going on, this will return -1.0.
]]
get {
}
values {
progress : double; [[The progress the animation applying is currently in.]]
}
}
@property animation_pause {
[[Pause the animation
The animation will not be unset. When $pause is unset, the animation will be resumed at the same progress it has right now.
]]
values {
pause : bool;
}
}
animation_start {
[[Start a new animation.
If there is a animation going on, this is stopped. The previous @.animation object will be replaced. The lifetime is adjusted accordingly.
]]
params {
animation : Efl.Canvas.Animation @move; [[The animation to start. When not needed anymore, the reference that was passed is given up.]]
speed : double; [[The speed of the playback. `1.0` is normal playback. Negative values mean backward playback.]]
starting_progress : double; [[The progress to start, must be between 0.0 and 1.0.]]
}
}
animation_stop {
[[Stop the animation.
After this call, @.animation will return $null. The reference that was taken during @.animation_start will be given up on.
]]
}
}
events {
animation,changed: Efl.Canvas.Animation; [[The animation object got changed.]]
animation_progress,updated : double; [[The animation progress got changed.]]
}
}

View File

@ -56,6 +56,7 @@ pub_eo_files = [
'efl_gfx_mapping.eo',
'efl_canvas_event_grabber.eo',
'efl_canvas_text.eo',
'efl_canvas_object_animation.eo',
]
evas_canvas_eo_files = pub_eo_files
@ -207,6 +208,7 @@ evas_src += files([
'evas_canvas3d_primitive.c',
'evas_canvas3d_node_callback.h',
'evas_canvas3d_eet.c',
'efl_canvas_object_animation.c',
])
evas_include_directories += include_directories('.')

View File

@ -5,10 +5,17 @@
#include <stdio.h>
#include <Evas.h>
#define EFL_LOOP_PROTECTED //needed to set the loop time, we need that to simulate time passing for animation,tick
#include <Ecore.h>
#include "evas_suite.h"
#include "evas_tests_helpers.h"
static int called_changed;
static Efl_Canvas_Animation *animation_changed_ev;
static int called_running;
static double animation_running_position;
EFL_START_TEST(evas_object_various)
{
Evas *evas = EVAS_TEST_INIT_EVAS();
@ -51,8 +58,159 @@ EFL_START_TEST(evas_object_freeze_events)
}
EFL_END_TEST
EFL_START_TEST(evas_object_animation_simple)
{
Evas *evas = EVAS_TEST_INIT_EVAS();
Evas_Object *obj = evas_object_rectangle_add(evas);
Efl_Canvas_Animation *animation = efl_add(EFL_CANVAS_ANIMATION_CLASS, evas);
ck_assert_ptr_eq(efl_canvas_object_animation_get(obj) , NULL);
ck_assert(EINA_DBL_EQ(efl_canvas_object_animation_progress_get(obj), -1.0));
efl_canvas_object_animation_start(obj, animation, 1.0, 0.0);
ck_assert_ptr_eq(efl_canvas_object_animation_get(obj) , animation);
ck_assert(EINA_DBL_EQ(efl_canvas_object_animation_progress_get(obj), 0.0));
efl_canvas_object_animation_stop(obj);
ck_assert_ptr_eq(efl_canvas_object_animation_get(obj) , NULL);
ck_assert(EINA_DBL_EQ(efl_canvas_object_animation_progress_get(obj), -1.0));
efl_canvas_object_animation_start(obj, animation, 1.0, 0.0);
efl_canvas_object_animation_stop(obj);
efl_canvas_object_animation_start(obj, animation, -1.0, 1.0);
efl_canvas_object_animation_stop(obj);
efl_canvas_object_animation_stop(obj);
}
EFL_END_TEST
EFL_START_TEST(evas_object_animation_progress)
{
Evas *evas = EVAS_TEST_INIT_EVAS();
Evas_Object *obj = evas_object_rectangle_add(evas);
Efl_Canvas_Animation *animation = efl_add(EFL_CANVAS_ANIMATION_CLASS, evas, efl_animation_duration_set(efl_added, 1.0));
efl_canvas_object_animation_start(obj, animation, 1.0, 0.0);
efl_loop_time_set(efl_main_loop_get(), efl_loop_time_get(efl_main_loop_get()) + 0.5);
efl_event_callback_call(obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, NULL);
ck_assert(EINA_DBL_EQ(efl_canvas_object_animation_progress_get(obj), 0.5));
efl_canvas_object_animation_stop(obj);
}
EFL_END_TEST
static inline void
_simulate_time_passing(Eo *obj, double start, double jump)
{
efl_loop_time_set(efl_main_loop_get(), start + jump);
efl_event_callback_call(obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, NULL);
}
static inline void
_simulate_assert_time_passing(Eo *obj, double start, double jump, double expected_position)
{
_simulate_time_passing(obj, start, jump);
ck_assert_int_eq((efl_canvas_object_animation_progress_get(obj)-expected_position)*10000, 0);
}
EFL_START_TEST(evas_object_animation_pause)
{
Evas *evas = EVAS_TEST_INIT_EVAS();
Evas_Object *obj = evas_object_rectangle_add(evas);
double start = efl_loop_time_get(efl_main_loop_get());
Efl_Canvas_Animation *animation = efl_add(EFL_CANVAS_ANIMATION_CLASS, evas, efl_animation_duration_set(efl_added, 1.0));
efl_canvas_object_animation_start(obj, animation, 1.0, 0.0);
_simulate_assert_time_passing(obj, start, 0.2, 0.2);
efl_canvas_object_animation_pause_set(obj, EINA_TRUE);
_simulate_assert_time_passing(obj, start, 0.5, 0.2);
efl_canvas_object_animation_pause_set(obj, EINA_FALSE);
_simulate_assert_time_passing(obj, start, 0.7, 0.4);
efl_canvas_object_animation_stop(obj);
}
EFL_END_TEST
EFL_START_TEST(evas_object_animation_error)
{
Evas *evas = EVAS_TEST_INIT_EVAS();
Evas_Object *obj = evas_object_rectangle_add(evas);
Efl_Canvas_Animation *animation = efl_add(EFL_CANVAS_ANIMATION_CLASS, evas);
EXPECT_ERROR_START;
efl_canvas_object_animation_start(obj, NULL, 1.0, 0.0);
EXPECT_ERROR_END;
EXPECT_ERROR_START;
efl_canvas_object_animation_start(obj, animation, 0.0, 0.0);
EXPECT_ERROR_END;
efl_canvas_object_animation_stop(obj);
EXPECT_ERROR_START;
efl_canvas_object_animation_start(obj, animation, 1.0, 2.0);
EXPECT_ERROR_END;
efl_canvas_object_animation_stop(obj);
EXPECT_ERROR_START;
efl_canvas_object_animation_start(obj, animation, 1.0, -1.0);
EXPECT_ERROR_END;
efl_canvas_object_animation_stop(obj);
}
EFL_END_TEST
static void
_anim_changed_cb(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
{
animation_changed_ev = event->info;
called_changed ++;
}
static void
_anim_running_cb(void *data EINA_UNUSED, const Efl_Event *event)
{
animation_running_position = *((double*) event->info);
called_running ++;
}
EFL_CALLBACKS_ARRAY_DEFINE(animation_stats_cb,
{EFL_CANVAS_OBJECT_ANIMATION_EVENT_ANIMATION_CHANGED, _anim_changed_cb },
{EFL_CANVAS_OBJECT_ANIMATION_EVENT_ANIMATION_PROGRESS_UPDATED, _anim_running_cb },
)
EFL_START_TEST(evas_object_animation_events)
{
Evas *evas = EVAS_TEST_INIT_EVAS();
Evas_Object *obj = evas_object_rectangle_add(evas);
double start = efl_loop_time_get(efl_main_loop_get());
Efl_Canvas_Animation *animation = efl_add(EFL_CANVAS_ANIMATION_CLASS, evas, efl_animation_duration_set(efl_added, 1.0));
efl_event_callback_array_add(obj, animation_stats_cb(), NULL);
efl_canvas_object_animation_start(obj, animation, 1.0, 0.0);
ck_assert_int_eq(called_changed, 1);
ck_assert_ptr_eq(animation_changed_ev, animation);
ck_assert_int_eq(called_running, 1);
ck_assert(EINA_DBL_EQ(animation_running_position, 0.0));
_simulate_time_passing(obj, start, 1.0);
ck_assert_int_eq(called_changed, 2);
ck_assert_ptr_eq(animation_changed_ev, NULL);
ck_assert_int_eq(called_running, 2);
ck_assert(EINA_DBL_EQ(animation_running_position, 1.0));
ck_assert_ptr_eq(efl_canvas_object_animation_get(obj), NULL);
ck_assert(EINA_DBL_EQ(efl_canvas_object_animation_progress_get(obj), -1.0));
}
EFL_END_TEST
void evas_test_object(TCase *tc)
{
tcase_add_test(tc, evas_object_various);
tcase_add_test(tc, evas_object_freeze_events);
tcase_add_test(tc, evas_object_animation_simple);
tcase_add_test(tc, evas_object_animation_progress);
tcase_add_test(tc, evas_object_animation_pause);
tcase_add_test(tc, evas_object_animation_error);
tcase_add_test(tc, evas_object_animation_events);
}