[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:
parent
ff48c3ef7c
commit
28b0f432b7
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,34 @@ typedef struct _ClutterInterval ClutterInterval;
|
||||
typedef struct _ClutterIntervalPrivate ClutterIntervalPrivate;
|
||||
typedef struct _ClutterIntervalClass ClutterIntervalClass;
|
||||
|
||||
/**
|
||||
* ClutterProgressFunc:
|
||||
* @a: the initial value of an interval
|
||||
* @b: the final value of an interval
|
||||
* @progress: the progress factor, between 0 and 1
|
||||
* @retval: the value used to store the progress
|
||||
*
|
||||
* Prototype of the progress function used to compute the value
|
||||
* between the two ends @a and @b of an interval depending on
|
||||
* the value of @progress.
|
||||
*
|
||||
* The #GValue in @retval is already initialized with the same
|
||||
* type as @a and @b.
|
||||
*
|
||||
* This function will be called by #ClutterInterval if the
|
||||
* type of the values of the interval was registered using
|
||||
* clutter_interval_register_progress_func().
|
||||
*
|
||||
* Return value: %TRUE if the function successfully computed
|
||||
* the value and stored it inside @retval
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef gboolean (* ClutterProgressFunc) (const GValue *a,
|
||||
const GValue *b,
|
||||
gdouble progress,
|
||||
GValue *retval);
|
||||
|
||||
/**
|
||||
* ClutterInterval:
|
||||
*
|
||||
@ -126,6 +154,9 @@ gboolean clutter_interval_compute_value (ClutterInterval *interval,
|
||||
gdouble factor,
|
||||
GValue *value);
|
||||
|
||||
void clutter_interval_register_progress_func (GType value_type,
|
||||
ClutterProgressFunc func);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INTERVAL_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user