~~Title: Ecore Animator~~ {{page>index}} ---- ===== Ecore Animator ===== Ecore provides a facility for animations called ''Ecore_Animator''. Ecore animators use the Ecore main loop for creating animations, running a specific action on each tick of a timer in the main loop. === Table of Contents === * [[#Create_an_Ecore_Animation|Create an Ecore Animation]] * [[#Creating_an_Animation_with_a_Finite_Duration|Creating an Animation with a Finite Duration]] * [[#Position_Mappings|Position Mappings]] * [[#Using_Position_Mappings|Using Position Mappings]] * [[#Creating_an_Infinite_Animation|Creating an Infinite Animation]] * [[#Chaining_Animations|Chaining Animations]] * [[#Pausing_and_Resuming_Animations|Pausing and Resuming Animations]] * [[#Freeing_Up_Memory|Freeing Up Memory]] * [[#Frametime|Frametime]] * [[#Custom_Timer|Custom Timer]] === Related Info === * [[/develop/legacy/tutorial/effects_tutorial|Effects Tutorial]] * [[https://build.enlightenment.org/job/nightly_efl_gcc_x86_64/lastSuccessfulBuild/artifact/doc/html/group__Ecore__Animator__Group.html|Ecore Animator Functions API]] ([[https://build.enlightenment.org/job/nightly_efl_gcc_x86_64/lastSuccessfulBuild/artifact/doc/html/ecore_main.html|Ecore API]]) * [[https://build.enlightenment.org/job/nightly_efl_gcc_x86_64/lastSuccessfulBuild/artifact/doc/html/tutorial_ecore_animator.html|Ecore animator example]] ==== Create an Ecore Animation ==== To create an Ecore animation: - Determine the duration of the animation. - Define a callback function that performs the animation with that duration. To use Ecore animators in your application, you must include the '''' file. This file is included by default if you are already using the '''' file in your application. You then declare an ''Ecore_Animator*'' variable and use the variable in the ''ecore_animator_*'' functions. The following example shows how to create a simple animation with a finite duration: static Eina_Bool _do_animation(void *data, double pos) { evas_object_move(data, 100 * pos, 100 * pos); // Do some more animating... } ecore_animator_timeline_add(2, _do_animation, my_evas_object); In the above example, we create a linear transition to move ''my_evas_object'' from position (0,0) to position (100,100) in 2 seconds. ==== Creating an Animation with a Finite Duration ==== Most of the time, you will want to create animations that last for a predefined time. The ''ecore_animator_timeline_add()'' function allows you to define an animator that is automatically deleted after the animation is finished: Ecore_Animator* ecore_animator_timeline_add(double runtime, Ecore_Timeline_Cb func, const void *data ) * ''runtime'' is the duration of the animation in seconds. The duration is not affected by frame rate. * ''func'' is the callback function that performs the animation. * ''data'' is the parameter passed to the callback function. This is usually the Evas object to animate. The callback function can return ''ECORE_CALLBACK_RENEW'' to keep the animator running or ''ECORE_CALLBACK_CANCEL''> to stop the animator and have it be deleted automatically at any time. The callback function is also passed a timeline position parameter with a value between 0.0 (start) to 1.0 (end) to indicate where along the timeline the animator is running. The following example performs a linear horizontal translation of 500 pixels in 8 seconds: static Eina_Bool _my_animation(void *data, double pos) { Evas_Object *obj = data; // Get the target object int x, y, w, h; // Target object geometry evas_object_geometry_get(obj, &x, &y, &w, &h); // Get current object position and size attributes evas_object_move(obj, 500 * pos, y); // Linear translation of the Evas object } ecore_animator_timeline_add(8, _my_animation, my_evas_object); ==== Position Mappings ==== The ''Ecore_Pos_Map'' position mappings are used to define the evolution of a given position in accordance with the desired effects. The value ranges from 0.0 to 1.0 on a given timeline. This position variation allows you to apply dynamic changes to any attribute of your Evas object, such as position, width, height, scale, angle, and color. Ecore supports the following position mappings (with the listed v1 and v2 parameters): * ''ECORE_POS_MAP_LINEAR'': linear 0.0 - 1.0 * v1: not used * v2: not used * ''ECORE_POS_MAP_ACCELERATE'': start slow, then speed up * v1: not used * v2: not used * ''ECORE_POS_MAP_DECELERATE'': start fast, then slow down * v1: not used * v2: not used * ''ECORE_POS_MAP_SINUSOIDAL'': start slow, speed up, then slow down at the end * v1: not used * v2: not used * ''ECORE_POS_MAP_ACCELERATE_FACTOR'': start slow, then speed up * v1: power factor: 0.0 is linear, 1.0 is standard acceleration, 2.0 is a much more pronounced acceleration (squared), 4.0 is cubed, and so on * v2: not used * ''ECORE_POS_MAP_DECELERATE_FACTOR'': start fast, then slow down * v1: power factor: 0.0 is linear, 1.0 is standard deceleration, 2.0 is a much more pronounced deceleration (squared), 3.0 is cubed, and so on * v2: not used * ''ECORE_POS_MAP_SINUSOIDAL_FACTOR'': start slow, speed up, then slow down at the end * v1: power factor: 0.0 is linear, 1.0 is a standard sinusoidal, 2.1 is a much more pronounced sinusoidal (squared), 3.0 is cubed, and so on * v2: not used * ''ECORE_POS_MAP_DIVISOR_INTERP'': start at gradient * v1, interpolated via power of v2 curve * v1: multiplication factor for gradient * v2: curve value * ''ECORE_POS_MAP_BOUNCE'': start at 0.0, then "drop" like a ball bouncing to the ground at 1.0, and bounce v2 times, with a decay factor of v1 * v1: bounce decay factor * v2: number of bounces * ''ECORE_POS_MAP_SPRING'': start at 0.0, then "wobble" like a spring until rest position at 1.0, and wobble v2 times, with a decay factor of v1 * v1: wobble decay factor * v2: number of wobbles {{ :event_effect_ecore_animator_position_mapping.png }} ==== Using Position Mappings ==== When using the animation callback function, the animator passes a timeline position parameter with a value between 0.0 (start) and 1.0 (end) to indicate where along the timeline the animator is running. If you want to create a non-linear animation, map the position value to one of several curves and mappings: double ecore_animator_pos_map(double pos, Ecore_Pos_Map map, double v1, double v2 ) * ''pos'' is the current position value, which ranges from 0.0 to 1.0. * ''map'' is the position mapping you want to apply. * ''v1'' is the first parameter (v1) to pass to the position mapping. * ''v2'' is the second parameter (v2) to pass to the position mapping. The v1 and v2 arguments are specific to the chosen position mapping. For example, if you are using ''ECORE_POS_MAP_BOUNCE'', v1 represents the bouncing level and v2 the number of bounces. The following example performs a transition that bounces 7 times, diminishing by a factor of 1.8 over 5 seconds: static Eina_Bool _my_animation_callback(void *data, double pos) { Evas_Object *obj = data; // Get the target object int x, y, w, h; // Target object geometry double frame = pos; // Actual position variation frame = ecore_animator_pos_map(pos, ECORE_POS_MAP_BOUNCE, 1.8, 7); //Get frame relative position depending on desired effect evas_object_geometry_get(obj, &x, &y, &w, &h); // Get current object position and size attributes evas_object_move(obj, x, 600 * frame); // Move the Evas object according to desired effect return EINA_TRUE; } ecore_animator_timeline_add(5, _my_animation_callback, my_evas_object); ==== Creating an Infinite Animation ==== If you want the animation to run for an unspecified amount of time, use the ''ecore_animator_add()'' function. This function works the same way as the ''ecore_animation_timeline_add()'' function, except its interval is based on frame rate. Using frame rate as the basis benefits performance, especially if you define multiple animations, since you may want to have a different timer for each callback function. Ecore_Animator* ecore_animator_add(Ecore_Task_Cb func, const void *data ) * ''func'' is the callback function that performs the animation. * ''data'' is the parameter passed to the callback function. This is usually the Evas object to animate. The function returns a pointer to an ''Ecore_Animator'' object, which you can use to adjust the animation. The following example creates a rectangle sliding from left to right and back again. When the rectangle hits one edge of the screen, it changes direction. static Eina_Bool _slide_back_and_forth(void *data) { typedef enum {LEFT, RIGHT} direction_t; // Direction datatype static int x = 0; // Initial position static direction_t direction = RIGHT; // Initial direction if (x >= 250) direction = LEFT; // Change direction else if (x <= 0) direction = RIGHT; // Change direction if (direction == RIGHT) evas_object_move(data, ++x, 350); // Slide to right else if (direction == LEFT) evas_object_move(data, --x, 350); // Slide to left return EINA_TRUE; } int main(int argc, char *argv[]) { // Declarations // Ecore Evas init // Draw Evas objects // Animations go here anim = ecore_animator_add(_slide_back_and_forth, rectangle); // Ecore main loop // Free memory } To use this code, you have to merge it with the Ecore transition example above. ==== Chaining Animations ==== You may sometimes want to delay animating an object. This can be useful if, for example, you want to start an animation only after another one has finished. You can simply set a delay to the second animation equal to the duration of the first animation: static int runtime = 5; static int delay = runtime; static Eina_Bool _start_fold_animation(void *data) { ecore_animator_timeline_add(runtime, _fold_animation, data); return EINA_FALSE; } static Eina_Bool _start_unfold_animation(void *data) { ecore_animator_timeline_add(runtime, _unfold_animation, data); return EINA_FALSE; } _start_fold_animation(my_evas_object); ecore_timer_add(delay, _start_unfold_animation, my_evas_object); ==== Pausing and Resuming Animations ==== You can pause and resume Ecore animations. To pause a running animation, use the ''ecore_animator_freeze()'' function: The parameter is the ''Ecore_Animator'' to pause. ecore_animator_freeze(Ecore_Animator *animator) To resume the paused animation, use the ''ecore_animator_thaw()'' function: ecore_animation_thaw(Ecore_Animator *animator) The parameter is the ''Ecore_Animator'' to resume. The following example pauses a transition after 5 seconds and resumes it after 5 more seconds: static Eina_Bool _freeze_animation(void *data) { ecore_animator_freeze(data); return EINA_FALSE; } static Eina_Bool _thaw_animation(void *data) { ecore_animator_thaw(data); return EINA_FALSE; } ecore_timer_add(5, _freeze_animation, animator); ecore_timer_add(10, _thaw_animation, animator); ==== Freeing Up Memory ==== When you create an animation that does not have a timeout, you will have to manually free up the memory allocated to the ''Ecore_Animator'' object. By comparison, if the animation has a timeout, Ecore implements the mechanisms to automatically delete the animator from the list of pointers: When your animation callback returns 0 or ''ECORE_CALLBACK_CANCEL'', the animator manager takes care of freeing up the allocated memory. To manually free up the memory, delete the pointer by using the ''ecore_animator_del()'' function: ecore_animator_del(Ecore_Animator *animator) The argument is the ''Ecore_Animator'' whose memory allocation to free up. Regardless of the type of animation, it is good practice to always ensure that the allocated memory is freed up before the program exits: if (animator != NULL) ecore_animator_del(animator); ==== Frametime ==== In most cases, you will want to use the default timer ''ECORE_ANIMATOR_SOURCE_TIMER''. This timer ticks every "frametime" seconds and allows you to perform transitions within a predefined timeline. The timer uses the system clock to tick over every Nth second, with the default being 1/30th of a second. To tweak performance, you can change the frametime value: The argument is the new frametime value. ecore_animator_frametime_set(double frametime) Too small a value can cause performance issues, whereas too high a value can cause your animation to seem jerky. If you want to get the current frametime value, use the ''ecore_animator_frametime_get()'' function. ==== Custom Timer ==== You may want to specify a custom timer to match your animation to third-party events. For example, the filling speed of a progress bar will mainly depend on the time it takes for a task to complete and the velocity at which the remaining time estimation evolves. This kind of animation requires you to use a custom timer. To use a custom timer, first set ''ECORE_ANIMATOR_SOURCE_CUSTOM'' as the timer source, and then drive the timer based on an input tick source (such as another application via IPC or a vertical blanking interrupt): void ecore_animator_custom_source_tick_begin_callback_set(Ecore_Cb func, const void *data ) * ''func'' is the callback function to call on the tick start. * ''data'' is the data to pass to the callback function. void ecore_animator_custom_source_tick_end_callback_set(Ecore_Cb func, const void *data ) * ''func'' is the callback function to call on the tick end. * ''data'' is the data to pass to the callback function to set the functions that will be called to start and stop the ticking source. Next, trigger a tick over one frame: ecore_animator_custom_tick(void) The following example supposes a progress bar that will be refreshed every time some progress occurs: ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); void _on_progress_update() { // Called when some progress occurs ecore_animator_custom_tick(); // Tick (next frame in progress bar animation) } Finally, to get the current animator source, use the ''ecore_animator_source_get()'' function. \\ ------------ {{page>index}}