Ecore animator example

For this example we are going to animate a rectangle growing, moving and changing color, and then move it back to it's initial state with a different animation. We are also going to have a second rectangle moving along the bottom of the screen. To do this we are going to use ecore_evas, but since that is not the focus here we won't going into detail about it.

#include <Ecore.h>
#include <Ecore_Evas.h>
static Eina_Bool _advance_frame(void *data, double pos);
static Eina_Bool _advance_frame2(void *data, double pos);
static Eina_Bool _advance_frame3(void *data);
static Eina_Bool _start_second_anim(void *data);
static Eina_Bool _freeze_third_anim(void *data);
static Eina_Bool _thaw_third_anim(void *data);
int
main(void)
{
Evas_Object *rect, *bg, *rect2;
Ecore_Evas *ee;
Evas *evas;
Ecore_Animator *anim;
ecore_evas_init();
ee = ecore_evas_new(NULL, 0, 0, 300, 400, NULL);
ecore_evas_show(ee);
evas = ecore_evas_get(ee);
bg = evas_object_rectangle_add(evas);
evas_object_resize(bg, 300, 400);
evas_object_show(bg);
Ecore_Evas.h
Evas wrapper functions.
ecore_evas_init
EAPI int ecore_evas_init(void)
Inits the Ecore_Evas system.
Definition ecore_evas.c:608
ecore_evas_show
EAPI void ecore_evas_show(Ecore_Evas *ee)
Shows an Ecore_Evas' window.
Definition ecore_evas.c:1494
ecore_evas_get
EAPI Evas * ecore_evas_get(const Ecore_Evas *ee)
Gets an Ecore_Evas's Evas.
Definition ecore_evas.c:1314
ecore_evas_new
EAPI Ecore_Evas * ecore_evas_new(const char *engine_name, int x, int y, int w, int h, const char *extra_options)
Creates a new Ecore_Evas based on engine name and common parameters.
Definition ecore_evas.c:1053
Eina_Bool
unsigned char Eina_Bool
Type to mimic a boolean.
Definition eina_types.h:527
Evas
Eo Evas
An opaque handle to an Evas canvas.
Definition Evas_Common.h:163
evas_object_show
EVAS_API void evas_object_show(Evas_Object *eo_obj)
Makes the given Evas object visible.
Definition evas_object_main.c:1814
Evas_Object
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition Evas_Common.h:185
evas_object_resize
EVAS_API void evas_object_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
Changes the size of the given Evas object.
Definition evas_object_main.c:1236
evas_object_rectangle_add
EVAS_API Evas_Object * evas_object_rectangle_add(Evas *e)
Adds a rectangle to the given evas.
Definition evas_object_rectangle.c:78
Ecore_Animator
Opaque handle to manage Ecore Animator objects.
rect = evas_object_rectangle_add(evas);
evas_object_color_set(rect, 0, 0, 255, 255);
evas_object_resize(rect, 50, 50);
evas_object_show(rect);
evas_object_color_set
EVAS_API void evas_object_color_set(Evas_Object *obj, int r, int g, int b, int a)
Sets the general/main color of the given Evas object to the given one.
Definition evas_object_main.c:2024

All of this is just setup, not what we're interested in right now.

Now we are going to set the frametime for our animation to one fiftieth of a second, this will make our program consume more resources but should make our animation extra smooth:

rect2 = evas_object_rectangle_add(evas);
evas_object_color_set(rect2, 0, 55, 0, 255);
evas_object_resize(rect2, 50, 50);
evas_object_show(rect2);
ecore_animator_frametime_set(1. / 50);
ecore_animator_frametime_set
void ecore_animator_frametime_set(double frametime)
Sets the animator call interval in seconds.
Definition ecore_anim.c:874

And now we get right to the business of creating our ecore_animator:

ecore_animator_timeline_add(5, _advance_frame, rect);
ecore_animator_timeline_add
Ecore_Animator * ecore_animator_timeline_add(double runtime, Ecore_Timeline_Cb func, const void *data)
Adds an animator that runs for a limited time.
Definition ecore_anim.c:544

Note
  We are telling our animation to last 10 second and to call _advance_frame with rect as data.

So far we setup the first and second animations, the third one however is a bit different, this time we won't use a timeline animation, that's because we don't want our animation to stop:

anim = ecore_animator_add(_advance_frame3, rect2);
ecore_animator_add
Ecore_Animator * ecore_animator_add(Ecore_Task_Cb func, const void *data)
Adds an animator to call func at every animation tick during main loop execution.
Definition ecore_anim.c:537

Next we set a few timers to execute _start_second_anim, _freeze_third_anim and _thaw_thir_anim in 10, 5 and 10 seconds respectively:

ecore_timer_add(10, _start_second_anim, rect);
ecore_timer_add(5, _freeze_third_anim, anim);
ecore_timer_add(10, _thaw_third_anim, anim);
ecore_timer_add
Ecore_Timer * ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
Creates a timer to call the given function in the given period of time.
Definition ecore_timer.c:189

And now we tell ecore to begin the main loop and free some resources once it leaves the main loop:

ecore_main_loop_begin();
evas_object_del(rect);
ecore_evas_free(ee);
ecore_animator_del(anim);
ecore_evas_shutdown();
return 0;
}
ecore_animator_del
void * ecore_animator_del(Ecore_Animator *animator)
Deletes the specified animator from the animator list.
Definition ecore_anim.c:846
ecore_evas_shutdown
EAPI int ecore_evas_shutdown(void)
Shuts down the Ecore_Evas system.
Definition ecore_evas.c:672
ecore_evas_free
EAPI void ecore_evas_free(Ecore_Evas *ee)
Frees an Ecore_Evas.
Definition ecore_evas.c:1097
ecore_main_loop_begin
void ecore_main_loop_begin(void)
Runs the application main loop.
Definition ecore_main.c:1311
evas_object_del
EVAS_API void evas_object_del(Evas_Object *obj)
Marks the given Evas object for deletion (when Evas will free its memory).
Definition evas_object_main.c:928

Here we have the callback function for our first animation, which first takes `pos(where in the timeline we are)`, maps it to a SPRING curve that which will wobble 15 times and will decay by a factor of 1.2:

static Eina_Bool
_advance_frame(void *data, double pos)
{
double frame = pos;
frame = ecore_animator_pos_map(pos, ECORE_POS_MAP_SPRING, 1.2, 15);
ecore_animator_pos_map
double ecore_animator_pos_map(double pos, Ecore_Pos_Map map, double v1, double v2)
Maps an input position from 0.0 to 1.0 along a timeline to a position in a different curve.
Definition ecore_anim.c:833
ECORE_POS_MAP_SPRING
@ ECORE_POS_MAP_SPRING
Start at 0.0 then "wobble" like a spring rest position 1.0, and wobble v2 times, with decay factor of...
Definition Ecore_Common.h:2795

Now that we have the frame we can adjust the rectangle to its appropriate state:

evas_object_resize(data, 50 * (1 + frame), 50 * (1 + frame));
evas_object_move(data, 100 * frame, 100 * frame);
evas_object_color_set(data, 255 * frame, 0, 255 * (1 - frame), 255);
return ECORE_CALLBACK_RENEW;
}
ECORE_CALLBACK_RENEW
#define ECORE_CALLBACK_RENEW
Return value to keep a callback.
Definition Ecore_Common.h:153
evas_object_move
EVAS_API void evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
Move the given Evas object to the given location inside its canvas' viewport.
Definition evas_object_main.c:1171

And now the callback that will run 10 seconds after the program starts(5 seconds after the first animation finishes) and starts our second animation:

static Eina_Bool
_start_second_anim(void *data)
{
ecore_animator_frametime_set(1. / 10);
ecore_animator_timeline_add(20, _advance_frame2, data);
return ECORE_CALLBACK_CANCEL;
}
ECORE_CALLBACK_CANCEL
#define ECORE_CALLBACK_CANCEL
Return value to remove a callback.
Definition Ecore_Common.h:152

Note
  For this animation we made the frametime much larger which means our animation might get "jerky".

The callback for our second animation, our savvy reader no doubt noted that it's very similar to the callback for the first animation. What we change for this one is the type of animation to BOUNCE and the number of times it will bounce to 50:

static Eina_Bool
_advance_frame2(void *data, double pos)
{
double frame = pos;
frame = ecore_animator_pos_map(pos, ECORE_POS_MAP_BOUNCE, 1.2, 50);
evas_object_resize(data, 100 - (50 * frame), 100 - (50 * frame));
evas_object_move(data, 100 * (1 - frame), 100 * (1 - frame));
evas_object_color_set(data, 255 * (1 - frame), 0, 255 * frame, 255);
return ECORE_CALLBACK_RENEW;
}
ECORE_POS_MAP_BOUNCE
@ ECORE_POS_MAP_BOUNCE
Start at 0.0 then "drop" like a ball bouncing to the ground at 1.0, and bounce v2 times,...
Definition Ecore_Common.h:2792

And for our last animation callback something simpler, we just move our rectangle right by one pixel until it reaches the end of the screen and then start at the beginning again:

static Eina_Bool
_advance_frame3(void *data)
{
static int x = 0;
if (x >= 250)
x = 0;
evas_object_move(data, ++x, 350);
return ECORE_CALLBACK_RENEW;
}

Our next two functions respectively freezes and thaw our third animation, so that it won't happen for the 5 seconds after the first animation ends and the second animation begins:

static Eina_Bool
_freeze_third_anim(void *data)
{
ecore_animator_freeze(data);
return ECORE_CALLBACK_CANCEL;
}
ecore_animator_freeze
void ecore_animator_freeze(Ecore_Animator *animator)
Suspends the specified animator.
Definition ecore_anim.c:892
static Eina_Bool
_thaw_third_anim(void *data)
{
ecore_animator_thaw(data);
return ECORE_CALLBACK_CANCEL;
}
ecore_animator_thaw
void ecore_animator_thaw(Ecore_Animator *animator)
Restores execution of the specified animator.
Definition ecore_anim.c:910