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);
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);
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);

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

ecore_animator_timeline_add(5, _advance_frame, rect);

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);

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);

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;
}

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);

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;
}

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;
}

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;
}

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;
}
static Eina_Bool
_thaw_third_anim(void *data)
{
ecore_animator_thaw(data);
return ECORE_CALLBACK_CANCEL;
}