mirror of
https://github.com/brl/mutter.git
synced 2025-06-14 01:09:30 +00:00
[animation] Allow registering custom progress function
A ClutterInterval can change the way the progress is computed by subclassing and overriding the ::compute_value() virtual function. It should also be possible to register a custom progress function in the same way it is possible to register a custom transformation function between two GValues. This commit adds an internal, global hash table that maintains a GType <-> progress function association; each ClutterInterval will check if there is a progress function registered for the GType of the initial and final values of the interval and, if it has been found, it will call it to compute the value of the interval depending on the progress factor.
This commit is contained in:
@ -62,6 +62,14 @@
|
||||
#include "clutter-interval.h"
|
||||
#include "clutter-units.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GType value_type;
|
||||
ClutterProgressFunc func;
|
||||
} ProgressData;
|
||||
|
||||
static GHashTable *progress_funcs = NULL;
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
@ -186,6 +194,25 @@ clutter_interval_real_compute_value (ClutterInterval *interval,
|
||||
|
||||
value_type = clutter_interval_get_value_type (interval);
|
||||
|
||||
if (G_UNLIKELY (progress_funcs != NULL))
|
||||
{
|
||||
ProgressData *p_data;
|
||||
|
||||
p_data =
|
||||
g_hash_table_lookup (progress_funcs, GUINT_TO_POINTER (value_type));
|
||||
|
||||
/* if we have a progress function, and that function was
|
||||
* successful in computing the progress, then we bail out
|
||||
* as fast as we can
|
||||
*/
|
||||
if (p_data != NULL)
|
||||
{
|
||||
retval = p_data->func (initial, final, factor, value);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
switch (G_TYPE_FUNDAMENTAL (value_type))
|
||||
{
|
||||
case G_TYPE_INT:
|
||||
@ -870,3 +897,81 @@ clutter_interval_compute_value (ClutterInterval *interval,
|
||||
factor,
|
||||
value);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_interval_register_progress_func:
|
||||
* @value_type: a #GType
|
||||
* @func: a #ClutterProgressFunc, or %NULL to unset a previously
|
||||
* set progress function
|
||||
*
|
||||
* Sets the progress function for a given @value_type, like:
|
||||
*
|
||||
* |[
|
||||
* clutter_interval_register_progress_func (MY_TYPE_FOO,
|
||||
* my_foo_progress);
|
||||
* ]|
|
||||
*
|
||||
* Whenever a #ClutterInterval instance using the default
|
||||
* #ClutterInterval::compute_value implementation is set as an
|
||||
* interval between two #GValue of type @value_type, it will call
|
||||
* @func to establish the value depending on the given progress,
|
||||
* for instance:
|
||||
*
|
||||
* |[
|
||||
* static gboolean
|
||||
* my_int_progress (const GValue *a,
|
||||
* const GValue *b,
|
||||
* gdouble progress,
|
||||
* GValue *retval)
|
||||
* {
|
||||
* gint ia = g_value_get_int (a);
|
||||
* gint ib = g_value_get_int (b);
|
||||
* gint res = factor * (ib - ia) + ia;
|
||||
*
|
||||
* g_value_set_int (retval, res);
|
||||
*
|
||||
* return TRUE;
|
||||
* }
|
||||
*
|
||||
* clutter_interval_register_progress_func (G_TYPE_INT, my_int_progress);
|
||||
* ]|
|
||||
*
|
||||
* To unset a previously set progress function of a #GType, pass %NULL
|
||||
* for @func.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_interval_register_progress_func (GType value_type,
|
||||
ClutterProgressFunc func)
|
||||
{
|
||||
ProgressData *progress_func;
|
||||
|
||||
g_return_if_fail (value_type != G_TYPE_INVALID);
|
||||
|
||||
if (G_UNLIKELY (progress_funcs == NULL))
|
||||
progress_funcs = g_hash_table_new (NULL, NULL);
|
||||
|
||||
progress_func =
|
||||
g_hash_table_lookup (progress_funcs, GUINT_TO_POINTER (value_type));
|
||||
if (G_UNLIKELY (progress_func))
|
||||
{
|
||||
if (func == NULL)
|
||||
{
|
||||
g_hash_table_remove (progress_funcs, GUINT_TO_POINTER (value_type));
|
||||
g_slice_free (ProgressData, progress_func);
|
||||
}
|
||||
else
|
||||
progress_func->func = func;
|
||||
}
|
||||
else
|
||||
{
|
||||
progress_func = g_slice_new (ProgressData);
|
||||
progress_func->value_type = value_type;
|
||||
progress_func->func = func;
|
||||
|
||||
g_hash_table_replace (progress_funcs,
|
||||
GUINT_TO_POINTER (value_type),
|
||||
progress_func);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user