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;
ee = ecore_evas_new(NULL, 0, 0, 300, 400, NULL);
evas = ecore_evas_get(ee);
evas_object_resize(bg, 300, 400);
Evas wrapper functions.
EAPI int ecore_evas_init(void)
Inits the Ecore_Evas system.
Definition: ecore_evas.c:602
EAPI void ecore_evas_show(Ecore_Evas *ee)
Shows an Ecore_Evas' window.
Definition: ecore_evas.c:1480
EAPI Evas * ecore_evas_get(const Ecore_Evas *ee)
Gets an Ecore_Evas's Evas.
Definition: ecore_evas.c:1300
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:1039
unsigned char Eina_Bool
Type to mimic a boolean.
Definition: eina_types.h:527
Eo Evas
An opaque handle to an Evas canvas.
Definition: Evas_Common.h:163
EVAS_API void evas_object_show(Evas_Object *eo_obj)
Makes the given Evas object visible.
Definition: evas_object_main.c:1814
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition: Evas_Common.h:185
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_API Evas_Object * evas_object_rectangle_add(Evas *e)
Adds a rectangle to the given evas.
Definition: evas_object_rectangle.c:78
Opaque handle to manage Ecore Animator objects.
evas_object_color_set(rect, 0, 0, 255, 255);
evas_object_resize(rect, 50, 50);
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:

evas_object_color_set(rect2, 0, 55, 0, 255);
evas_object_resize(rect2, 50, 50);
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 * 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 * 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 * 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:

return 0;
}
void * ecore_animator_del(Ecore_Animator *animator)
Deletes the specified animator from the animator list.
Definition: ecore_anim.c:846
EAPI int ecore_evas_shutdown(void)
Shuts down the Ecore_Evas system.
Definition: ecore_evas.c:666
EAPI void ecore_evas_free(Ecore_Evas *ee)
Frees an Ecore_Evas.
Definition: ecore_evas.c:1083
void ecore_main_loop_begin(void)
Runs the application main loop.
Definition: ecore_main.c:1311
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;
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
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:2789

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);
}
#define ECORE_CALLBACK_RENEW
Return value to keep a callback.
Definition: Ecore_Common.h:153
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_timeline_add(20, _advance_frame2, data);
}
#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;
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);
}
@ 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:2786

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

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)
{
}
void ecore_animator_freeze(Ecore_Animator *animator)
Suspends the specified animator.
Definition: ecore_anim.c:892
static Eina_Bool
_thaw_third_anim(void *data)
{
}
void ecore_animator_thaw(Ecore_Animator *animator)
Restores execution of the specified animator.
Definition: ecore_anim.c:910