forked from enlightenment/efl
add animator runtime stuff to run animator for fixed timelength and an
interpolation mapping func. SVN revision: 58741
This commit is contained in:
parent
1eaba59607
commit
29992f0a49
|
@ -140,3 +140,12 @@
|
|||
2011-04-19 Mike Blumenkrantz
|
||||
|
||||
* +ecore_exe_data_set
|
||||
|
||||
2011-04-20 Carsten Haitzler (The Rasterman)
|
||||
|
||||
* Added ecore animator run, where animator runs for a
|
||||
specified time (in seconds) and then stops, but it also passes
|
||||
the position in the timeline (as a 0.0 to 1.0 value) to the
|
||||
callback which it can then use the new pos map call to map to
|
||||
some ease in/out, bounce, spring or whatever position.
|
||||
|
||||
|
|
|
@ -146,6 +146,21 @@ extern "C" {
|
|||
ECORE_POLLER_CORE = 0 /**< The core poller interval */
|
||||
};
|
||||
typedef enum _Ecore_Poller_Type Ecore_Poller_Type;
|
||||
|
||||
enum _Ecore_Pos_Map /* Position mappings */
|
||||
{
|
||||
ECORE_POS_MAP_LINEAR, /**< Linear 0.0 -> 1.0 */
|
||||
ECORE_POS_MAP_ACCELERATE, /**< Start slow then speed up */
|
||||
ECORE_POS_MAP_DECELERATE, /**< Start fast then slow down */
|
||||
ECORE_POS_MAP_SINUSOIDAL, /**< Start slow, speed up then slow down at end */
|
||||
ECORE_POS_MAP_ACCELERATE_FACTOR, /**< Start slow then speed up, v1 being a power factor, 0.0 being linear, 1.0 being normal accelerate, 2.0 being much more pronounced accelerate (squared), 3.0 being cubed, etc. */
|
||||
ECORE_POS_MAP_DECELERATE_FACTOR, /**< Start fast then slow down, v1 being a power factor, 0.0 being linear, 1.0 being normal decelerate, 2.0 being much more pronounced decelerate (squared), 3.0 being cubed, etc. */
|
||||
ECORE_POS_MAP_SINUSOIDAL_FACTOR, /**< Start slow, speed up then slow down at end, v1 being a power factor, 0.0 being linear, 1.0 being normal sinusoidal, 2.0 being much more pronounced sinusoidal (squared), 3.0 being cubed, etc. */
|
||||
ECORE_POS_MAP_DIVISOR_INTERP, /**< Start at gradient * v1, interpolated via power of v2 curve */
|
||||
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 decay factor of v1 */
|
||||
ECORE_POS_MAP_SPRING /**< Start at 0.0 then "wobble" like a sping rest position 1.0, and wobble v2 times, with decay factor of v1 */
|
||||
};
|
||||
typedef enum _Ecore_Pos_Map Ecore_Pos_Map;
|
||||
|
||||
typedef struct _Ecore_Exe Ecore_Exe; /**< A handle for spawned processes */
|
||||
typedef struct _Ecore_Timer Ecore_Timer; /**< A handle for timers */
|
||||
|
@ -218,9 +233,14 @@ extern "C" {
|
|||
typedef void (*Ecore_Thread_Notify_Cb) (void *data, Ecore_Thread *thread, void *msg_data);
|
||||
/**
|
||||
* @typedef Ecore_Task_Cb Ecore_Task_Cb
|
||||
* A callback run for a task (timer, idler, poller, animater, etc)
|
||||
* A callback run for a task (timer, idler, poller, animator, etc)
|
||||
*/
|
||||
typedef Eina_Bool (*Ecore_Task_Cb) (void *data);
|
||||
/**
|
||||
* @typedef Ecore_Timeline_Cb Ecore_Timeline_Cb
|
||||
* A callback run for a task (animators with runtimes)
|
||||
*/
|
||||
typedef Eina_Bool (*Ecore_Timeline_Cb) (void *data, double pos);
|
||||
/**
|
||||
* @typedef Ecore_Cb Ecore_Cb
|
||||
* A generic callback called as a hook when a certain point in execution is reached.
|
||||
|
@ -555,12 +575,14 @@ extern "C" {
|
|||
*/
|
||||
|
||||
EAPI Ecore_Animator *ecore_animator_add(Ecore_Task_Cb func, const void *data);
|
||||
EAPI Ecore_Animator *ecore_animator_run_add(double runtime, Ecore_Timeline_Cb func, const void *data);
|
||||
EAPI void *ecore_animator_del(Ecore_Animator *animator);
|
||||
EAPI void ecore_animator_freeze(Ecore_Animator *animator);
|
||||
EAPI void ecore_animator_thaw(Ecore_Animator *animator);
|
||||
EAPI void ecore_animator_frametime_set(double frametime);
|
||||
EAPI double ecore_animator_frametime_get(void);
|
||||
|
||||
EAPI double ecore_animator_pos_map(double pos, Ecore_Pos_Map map, double v1, double v2);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -16,12 +16,17 @@ struct _Ecore_Animator
|
|||
|
||||
Ecore_Task_Cb func;
|
||||
void *data;
|
||||
|
||||
double start, run;
|
||||
Ecore_Timeline_Cb run_func;
|
||||
void *run_data;
|
||||
|
||||
Eina_Bool delete_me : 1;
|
||||
Eina_Bool suspended : 1;
|
||||
};
|
||||
|
||||
|
||||
static Eina_Bool _ecore_animator_run(void *data);
|
||||
static Eina_Bool _ecore_animator(void *data);
|
||||
|
||||
static Ecore_Timer *timer = NULL;
|
||||
|
@ -81,10 +86,165 @@ ecore_animator_add(Ecore_Task_Cb func, const void *data)
|
|||
return animator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a animator that runs for a limited time
|
||||
* @param runtime The time to run in seconds
|
||||
* @param func The function to call when it ticks off
|
||||
* @param data The data to pass to the function
|
||||
* @return A handle to the new animator
|
||||
*
|
||||
* This function is just like ecore_animator_add() except the animator only
|
||||
* runs for a limited time specified in seconds by @p runtime. Once the runtime
|
||||
* the animator has elapsed (animator finished) it will automatically be
|
||||
* deleted. The callback function @p func can return ECORE_CALLBACK_RENEW to
|
||||
* keep the animator running or ECORE_CALLBACK_CANCEL ro stop it and have
|
||||
* it be deleted automatically at any time.
|
||||
*
|
||||
* The @p func will ALSO be passed a position parameter that will be in value
|
||||
* from 0.0 to 1.0 to indicate where along the timeline (0.0 start, 1.0 end)
|
||||
* the animator run is at. If the callback wishes not to have a linear
|
||||
* transition it can "map" this value to one of several curves and mappings
|
||||
* via ecore_animator_pos_map().
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
EAPI Ecore_Animator *
|
||||
ecore_animator_run_add(double runtime, Ecore_Timeline_Cb func, const void *data)
|
||||
{
|
||||
Ecore_Animator *animator;
|
||||
|
||||
if (runtime <= 0.0) runtime = 0.0;
|
||||
animator = ecore_animator_add(_ecore_animator_run, NULL);
|
||||
animator->data = animator;
|
||||
animator->run_func = func;
|
||||
animator->run_data = (void *)data;
|
||||
animator->start = ecore_loop_time_get();
|
||||
animator->run = runtime;
|
||||
return animator;
|
||||
}
|
||||
|
||||
static double
|
||||
_pos_map_accel_factor(double pos, double v1)
|
||||
{
|
||||
int i, fact = (int)v1;
|
||||
double p, o1 = pos, o2 = pos, v;
|
||||
p = 1.0 - sin((M_PI / 2.0) + ((pos * M_PI) / 2.0));
|
||||
o2 = p;
|
||||
for (i = 0; i < fact; i++)
|
||||
{
|
||||
o1 = o2;
|
||||
o2 = o2 * p;
|
||||
}
|
||||
v = v1 - (double)fact;
|
||||
pos = (v * o2) + ((1.0 - v) * o1);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static double
|
||||
_pos_map_pow(double pos, double divis, int p)
|
||||
{
|
||||
double v = 1.0;
|
||||
int i;
|
||||
for (i = 0; i < p; i++) v *= pos;
|
||||
return ((pos * divis) * (1.0 - v)) + (pos * v);
|
||||
}
|
||||
|
||||
static double
|
||||
_pos_map_spring(double pos, int bounces, double decfac)
|
||||
{
|
||||
int segnum, segpos, b1, b2;
|
||||
double len, decay, decpos, p2;
|
||||
if (bounces < 0) bounces = 0;
|
||||
p2 = _pos_map_pow(pos, 0.5, 3);
|
||||
len = (M_PI / 2.0) + ((double)bounces * M_PI);
|
||||
segnum = (bounces * 2) + 1;
|
||||
segpos = 2 * (((int)(p2 * segnum) + 1) / 2);
|
||||
b1 = segpos;
|
||||
b2 = segnum + 1;
|
||||
if (b1 < 0) b1 = 0;
|
||||
decpos = (double)b1 / (double)b2;
|
||||
decay = _pos_map_accel_factor(1.0 - decpos, decfac);
|
||||
return sin((M_PI / 2.0) + (p2 * len)) * decay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps an input position from 0.0 to 1.0 along a timeline to another position
|
||||
*
|
||||
* Takes an input position (0.0 to 1.0) and maps to a new position (normally
|
||||
* between 0.0 and 1.0, but it may go above/below 0.0 or 1.0 to show that it
|
||||
* has "overshot" the mark) using some interpolation (mapping) algorithm.
|
||||
*
|
||||
* You might normally use this like:
|
||||
* @code
|
||||
* double pos; // input position in a timeline from 0.0 to 1.0
|
||||
* double out; // output position after mapping
|
||||
* int x1, y1, x2, y2; // x1 & y1 are start position, x2 & y2 are end position
|
||||
* int x, y; // x & y are the calculated position
|
||||
*
|
||||
* out = ecore_animator_pos_map(pos, ECORE_POS_MAP_BOUNCE, 1.8, 7);
|
||||
* x = (x1 * out) + (x2 * (1.0 - out));
|
||||
* y = (y1 * out) + (y2 * (1.0 - out));
|
||||
* move_my_object_to(myobject, x, y);
|
||||
* @endcode
|
||||
*
|
||||
* @param pos The input position to map
|
||||
* @param map The mapping to use
|
||||
* @param v1 A parameter use by the mapping (pass 0.0 if not used)
|
||||
* @param v2 A parameter use by the mapping (pass 0.0 if not used)
|
||||
* @return The mapped value
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
EAPI double
|
||||
ecore_animator_pos_map(double pos, Ecore_Pos_Map map, double v1, double v2)
|
||||
{
|
||||
if (pos > 1.0) pos = 1.0;
|
||||
else if (pos < 0.0) pos = 0.0;
|
||||
switch (map)
|
||||
{
|
||||
case ECORE_POS_MAP_LINEAR:
|
||||
return pos;
|
||||
case ECORE_POS_MAP_ACCELERATE:
|
||||
pos = 1.0 - sin((M_PI / 2.0) + ((pos * M_PI) / 2.0));
|
||||
return pos;
|
||||
case ECORE_POS_MAP_DECELERATE:
|
||||
pos = sin((pos * M_PI) / 2.0);
|
||||
return pos;
|
||||
case ECORE_POS_MAP_SINUSOIDAL:
|
||||
pos = (1.0 - cos(pos * M_PI)) / 2.0;
|
||||
return pos;
|
||||
case ECORE_POS_MAP_ACCELERATE_FACTOR:
|
||||
pos = _pos_map_accel_factor(pos, v1);
|
||||
return pos;
|
||||
case ECORE_POS_MAP_DECELERATE_FACTOR:
|
||||
pos = 1.0 - _pos_map_accel_factor(1.0 - pos, v1);
|
||||
return pos;
|
||||
case ECORE_POS_MAP_SINUSOIDAL_FACTOR:
|
||||
if (pos < 0.5) pos = _pos_map_accel_factor(pos * 2.0, v1) / 2.0;
|
||||
else pos = 1.0 - (_pos_map_accel_factor((1.0 - pos) * 2.0, v1) / 2.0);
|
||||
return pos;
|
||||
case ECORE_POS_MAP_DIVISOR_INTERP:
|
||||
pos = _pos_map_pow(pos, v1, (int)v2);
|
||||
return pos;
|
||||
case ECORE_POS_MAP_BOUNCE:
|
||||
pos = _pos_map_spring(pos, (int)v2, v1);
|
||||
if (pos < 0.0) pos = -pos;
|
||||
pos = 1.0 - pos;
|
||||
return pos;
|
||||
case ECORE_POS_MAP_SPRING:
|
||||
pos = 1.0 - _pos_map_spring(pos, (int)v2, v1);
|
||||
return pos;
|
||||
default:
|
||||
return pos;
|
||||
}
|
||||
return pos;
|
||||
v2 = 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the specified animator from the animator list.
|
||||
* @param animator The animator to delete
|
||||
* @return The data pointer set for the animator
|
||||
* @return The data pointer set for the animator on add
|
||||
*
|
||||
* Delete the specified @p aqnimator from the set of animators that are executed
|
||||
* during main loop execution. This function returns the data parameter that
|
||||
|
@ -104,6 +264,7 @@ ecore_animator_del(Ecore_Animator *animator)
|
|||
if (animator->delete_me) return animator->data;
|
||||
animator->delete_me = EINA_TRUE;
|
||||
animators_delete_me++;
|
||||
if (animator->run_func) return animator->run_data;
|
||||
return animator->data;
|
||||
}
|
||||
|
||||
|
@ -199,6 +360,25 @@ _ecore_animator_shutdown(void)
|
|||
}
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ecore_animator_run(void *data)
|
||||
{
|
||||
Ecore_Animator *animator = data;
|
||||
double pos = 0.0, t;
|
||||
Eina_Bool run_ret;
|
||||
|
||||
t = ecore_loop_time_get();
|
||||
if (animator->run > 0.0)
|
||||
{
|
||||
pos = (t - animator->start) / animator->run;
|
||||
if (pos > 1.0) pos = 1.0;
|
||||
else if (pos < 0.0) pos = 0.0;
|
||||
}
|
||||
run_ret = animator->run_func(animator->run_data, pos);
|
||||
if (t >= (animator->start + animator->run)) run_ret = EINA_FALSE;
|
||||
return run_ret;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ecore_animator(void *data __UNUSED__)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue