Commit 7d7372af authored by Emmanuele Bassi's avatar Emmanuele Bassi

[animation] Move the alpha value to floating point

The current Alpha value is an unsigned integer that can be used
implicitly as a fixed point value. This makes writing an alpha
function overshooting below and above the current range basically
impossible without complicating an already complex code, and
creating weird corner cases.

For this reason, the Alpha value should be defined as a floating
point normalized value, spanning a range between 0.0 and 1.0; in
order to allow overshooting, the valid range is extended one unit
below and one unit above, thus making it -1.0 .. 2.0.

This commit updates the various users of the ClutterAlpha API
and the tests cases.

This commit also removes all the current alpha functions exposed
in the public API.
parent 6d4cd416
This diff is collapsed.
......@@ -8,7 +8,8 @@
* Emmanuele Bassi <ebassi@openedhand.com>
* Tomas Frydrych <tf@openedhand.com>
*
* Copyright (C) 2006, 2007 OpenedHand
* Copyright (C) 2006, 2007, 2008 OpenedHand
* Copyright (C) 2009 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -52,15 +53,14 @@ typedef struct _ClutterAlphaPrivate ClutterAlphaPrivate;
* @alpha: a #ClutterAlpha
* @user_data: user data passed to the function
*
* A function of time, which returns a value between 0 and
* %CLUTTER_ALPHA_MAX_ALPHA.
* A function returning a value depending on the position of
* the #ClutterTimeline bound to @alpha.
*
* Return value: an unsigned integer value, between 0 and
* %CLUTTER_ALPHA_MAX_ALPHA.
* Return value: a floating point value
*
* Since: 0.2
*/
typedef guint32 (*ClutterAlphaFunc) (ClutterAlpha *alpha,
typedef gdouble (*ClutterAlphaFunc) (ClutterAlpha *alpha,
gpointer user_data);
/**
......@@ -76,6 +76,7 @@ struct _ClutterAlpha
{
/*< private >*/
GInitiallyUnowned parent;
ClutterAlphaPrivate *priv;
};
......@@ -98,15 +99,6 @@ struct _ClutterAlphaClass
void (*_clutter_alpha_5) (void);
};
/**
* CLUTTER_ALPHA_MAX_ALPHA:
*
* Maximum value returned by #ClutterAlphaFunc
*
* Since: 0.2
*/
#define CLUTTER_ALPHA_MAX_ALPHA (0xffff)
GType clutter_alpha_get_type (void) G_GNUC_CONST;
ClutterAlpha * clutter_alpha_new (void);
......@@ -117,7 +109,7 @@ ClutterAlpha * clutter_alpha_new_with_func (ClutterTimeline *timeline,
gpointer data,
GDestroyNotify destroy);
guint32 clutter_alpha_get_alpha (ClutterAlpha *alpha);
gdouble clutter_alpha_get_alpha (ClutterAlpha *alpha);
void clutter_alpha_set_func (ClutterAlpha *alpha,
ClutterAlphaFunc func,
gpointer data,
......@@ -135,56 +127,6 @@ gulong clutter_alpha_register_func (ClutterAlphaFunc func,
gpointer data);
gulong clutter_alpha_register_closure (GClosure *closure);
/* convenience functions */
guint32 clutter_ramp_inc_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_ramp_dec_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_ramp_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_sine_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_sine_inc_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_sine_dec_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_sine_half_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_sine_in_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_sine_out_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_sine_in_out_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_square_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_smoothstep_inc_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_smoothstep_dec_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_exp_inc_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_exp_dec_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_ease_in_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_ease_out_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_ease_in_out_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_exp_in_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_exp_out_func (ClutterAlpha *alpha,
gpointer dummy);
guint32 clutter_exp_in_out_func (ClutterAlpha *alpha,
gpointer dummy);
G_END_DECLS
#endif /* __CLUTTER_ALPHA_H__ */
......@@ -664,7 +664,7 @@ on_alpha_notify (GObject *gobject,
{
ClutterAnimationPrivate *priv = animation->priv;
GList *properties, *p;
guint32 alpha_value;
gdouble alpha_value;
gboolean is_animatable = FALSE;
ClutterAnimatable *animatable = NULL;
......@@ -683,7 +683,6 @@ on_alpha_notify (GObject *gobject,
{
const gchar *p_name = p->data;
ClutterInterval *interval;
gdouble factor;
GValue value = { 0, };
interval = g_hash_table_lookup (priv->properties, p_name);
......@@ -691,8 +690,6 @@ on_alpha_notify (GObject *gobject,
g_value_init (&value, clutter_interval_get_value_type (interval));
factor = (gdouble) alpha_value / CLUTTER_ALPHA_MAX_ALPHA;
if (is_animatable)
{
const GValue *initial, *final;
......@@ -704,7 +701,7 @@ on_alpha_notify (GObject *gobject,
clutter_animatable_animate_property (animatable, animation,
p_name,
initial, final,
factor,
alpha_value,
&value);
g_object_set_property (priv->object, p_name, &value);
......@@ -713,7 +710,7 @@ on_alpha_notify (GObject *gobject,
{
CLUTTER_NOTE (ANIMATION, "Standard property `%s'", p_name);
if (clutter_interval_compute_value (interval, factor, &value))
if (clutter_interval_compute_value (interval, alpha_value, &value))
g_object_set_property (priv->object, p_name, &value);
}
......
......@@ -74,7 +74,7 @@ alpha_notify_foreach (ClutterBehaviour *behaviour,
static void
clutter_behaviour_depth_alpha_notify (ClutterBehaviour *behaviour,
guint32 alpha_value)
gdouble alpha_value)
{
ClutterFixed factor;
ClutterBehaviourDepthPrivate *priv;
......@@ -83,11 +83,11 @@ clutter_behaviour_depth_alpha_notify (ClutterBehaviour *behaviour,
priv = CLUTTER_BEHAVIOUR_DEPTH (behaviour)->priv;
/* Need to create factor as to avoid borking signedness */
factor = COGL_FIXED_FROM_INT (alpha_value) / CLUTTER_ALPHA_MAX_ALPHA;
factor = COGL_FIXED_FROM_FLOAT (alpha_value);
depth = priv->depth_start
+ COGL_FIXED_TO_INT (factor * (priv->depth_end - priv->depth_start));
CLUTTER_NOTE (BEHAVIOUR, "alpha: %d, depth: %d", alpha_value, depth);
CLUTTER_NOTE (BEHAVIOUR, "alpha: %.4f, depth: %d", alpha_value, depth);
clutter_behaviour_actors_foreach (behaviour,
alpha_notify_foreach,
......
......@@ -205,7 +205,7 @@ clamp_angle (ClutterAngle a)
static void
clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave,
guint32 alpha)
gdouble alpha)
{
ClutterBehaviourEllipse *self = CLUTTER_BEHAVIOUR_ELLIPSE (behave);
ClutterBehaviourEllipsePrivate *priv = self->priv;
......@@ -225,7 +225,7 @@ clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave,
end -= 1024;
}
angle = (end - start) * alpha / CLUTTER_ALPHA_MAX_ALPHA + start;
angle = (end - start) * alpha + start;
clutter_behaviour_ellipse_advance (self, angle, &knot);
......
......@@ -87,7 +87,7 @@ alpha_notify_foreach (ClutterBehaviour *behaviour,
static void
clutter_behaviour_alpha_notify (ClutterBehaviour *behave,
guint32 alpha_value)
gdouble alpha_value)
{
ClutterBehaviourOpacityPrivate *priv;
guint8 opacity;
......@@ -96,10 +96,9 @@ clutter_behaviour_alpha_notify (ClutterBehaviour *behave,
opacity = alpha_value
* (priv->opacity_end - priv->opacity_start)
/ CLUTTER_ALPHA_MAX_ALPHA
+ priv->opacity_start;
CLUTTER_NOTE (BEHAVIOUR, "alpha: %u, opacity: %u",
CLUTTER_NOTE (BEHAVIOUR, "alpha: %.4f, opacity: %u",
alpha_value,
opacity);
......
......@@ -123,7 +123,7 @@ actor_apply_knot_foreach (ClutterBehaviour *behaviour,
static void
clutter_behaviour_path_alpha_notify (ClutterBehaviour *behave,
guint32 alpha_value)
gdouble alpha_value)
{
ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (behave);
ClutterBehaviourPathPrivate *priv = pathb->priv;
......@@ -131,10 +131,7 @@ clutter_behaviour_path_alpha_notify (ClutterBehaviour *behave,
guint knot_num;
if (priv->path)
knot_num = clutter_path_get_position (priv->path,
alpha_value
/ (gdouble) CLUTTER_ALPHA_MAX_ALPHA,
&position);
knot_num = clutter_path_get_position (priv->path, alpha_value, &position);
else
{
memset (&position, 0, sizeof (position));
......
......@@ -117,7 +117,7 @@ ClutterFixed clamp_angle (ClutterFixed a)
static void
clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour,
guint32 alpha_value)
gdouble alpha_value)
{
ClutterFixed factor, angle, start, end;
ClutterBehaviourRotate *rotate_behaviour;
......@@ -126,7 +126,7 @@ clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour,
rotate_behaviour = CLUTTER_BEHAVIOUR_ROTATE (behaviour);
priv = rotate_behaviour->priv;
factor = COGL_FIXED_FROM_INT (alpha_value) / CLUTTER_ALPHA_MAX_ALPHA;
factor = COGL_FIXED_FROM_FLOAT (alpha_value);
angle = 0;
start = priv->angle_start;
......
......@@ -90,7 +90,7 @@ scale_frame_foreach (ClutterBehaviour *behaviour,
static void
clutter_behaviour_scale_alpha_notify (ClutterBehaviour *behave,
guint32 alpha_value)
gdouble alpha_value)
{
ClutterBehaviourScalePrivate *priv;
ClutterFixed scale_x, scale_y;
......@@ -101,7 +101,7 @@ clutter_behaviour_scale_alpha_notify (ClutterBehaviour *behave,
/* Fix the start/end values, avoids potential rounding errors on large
* values.
*/
if (alpha_value == CLUTTER_ALPHA_MAX_ALPHA)
if (alpha_value == 1.0)
{
scale_x = priv->x_scale_end;
scale_y = priv->y_scale_end;
......@@ -115,7 +115,7 @@ clutter_behaviour_scale_alpha_notify (ClutterBehaviour *behave,
{
ClutterFixed factor;
factor = COGL_FIXED_FROM_INT (alpha_value) / CLUTTER_ALPHA_MAX_ALPHA;
factor = COGL_FIXED_FROM_FLOAT (alpha_value);
scale_x =
COGL_FIXED_FAST_MUL (factor, (priv->x_scale_end - priv->x_scale_start));
......
......@@ -240,7 +240,7 @@ clutter_behaviour_get_property (GObject *object,
static void
clutter_behaviour_alpha_notify_unimplemented (ClutterBehaviour *behaviour,
guint32 alpha_value)
gdouble alpha_value)
{
g_warning ("ClutterBehaviourClass::alpha_notify not implemented for `%s'",
g_type_name (G_TYPE_FROM_INSTANCE (behaviour)));
......@@ -533,11 +533,9 @@ notify_cb (GObject *object,
if (klass->alpha_notify)
{
guint32 alpha_value;
gdouble alpha_value = clutter_alpha_get_alpha (behave->priv->alpha);
alpha_value = clutter_alpha_get_alpha (behave->priv->alpha);
CLUTTER_NOTE (BEHAVIOUR, "calling %s::alpha_notify (%p, %d)",
CLUTTER_NOTE (BEHAVIOUR, "calling %s::alpha_notify (%p, %.4f)",
g_type_name (G_TYPE_FROM_CLASS (klass)),
behave, alpha_value);
......
......@@ -113,7 +113,7 @@ struct _ClutterBehaviourClass
/*< public >*/
/* vfunc, not signal */
void (*alpha_notify) (ClutterBehaviour *behave,
guint32 alpha_value);
gdouble alpha_value);
/* signals */
void (*applied) (ClutterBehaviour *behave,
......
......@@ -891,8 +891,6 @@ clutter_interval_compute_value (ClutterInterval *interval,
g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), FALSE);
g_return_val_if_fail (value != NULL, FALSE);
factor = CLAMP (factor, 0.0, 1.0);
return CLUTTER_INTERVAL_GET_CLASS (interval)->compute_value (interval,
factor,
value);
......
BOOLEAN:BOXED
BOOLEAN:STRING,UINT,ENUM
DOUBLE:VOID
UINT:VOID
VOID:BOXED
VOID:INT
......
......@@ -528,30 +528,8 @@ static const struct
ClutterAlphaFunc symbol;
} clutter_alphas[] = {
#define ALPHA_FUNC(func,nick) { #func, nick, func }
ALPHA_FUNC (clutter_ramp_inc_func, "ramp-inc"),
ALPHA_FUNC (clutter_ramp_dec_func, "ramp-dec"),
ALPHA_FUNC (clutter_ramp_func, "ramp"),
ALPHA_FUNC (clutter_sine_inc_func, "sine-inc"),
ALPHA_FUNC (clutter_sine_dec_func, "sine-dec"),
ALPHA_FUNC (clutter_sine_half_func, "sine-half"),
ALPHA_FUNC (clutter_sine_in_func, "sine-in"),
ALPHA_FUNC (clutter_sine_out_func, "sine-out"),
ALPHA_FUNC (clutter_sine_in_out_func, "sine-in-out"),
ALPHA_FUNC (clutter_sine_func, "sine"),
ALPHA_FUNC (clutter_square_func, "square"),
ALPHA_FUNC (clutter_smoothstep_inc_func, "smoothstep-inc"),
ALPHA_FUNC (clutter_smoothstep_dec_func, "smoothstep-dec"),
ALPHA_FUNC (clutter_exp_inc_func, "exp-inc"),
ALPHA_FUNC (clutter_exp_dec_func, "exp-dec"),
ALPHA_FUNC (clutter_ramp_inc_func, "linear"),
ALPHA_FUNC (clutter_ease_in_func, "ease-in"),
ALPHA_FUNC (clutter_ease_out_func, "ease-out"),
ALPHA_FUNC (clutter_ease_in_out_func, "ease-in-out"),
ALPHA_FUNC (clutter_exp_in_func, "exp-in"),
ALPHA_FUNC (clutter_exp_out_func, "exp-out"),
ALPHA_FUNC (clutter_exp_in_out_func, "exp-in-out"),
ALPHA_FUNC (clutter_smoothstep_inc_func, "smooth-in-out")
#undef ALPHA_FUNC
{ NULL, NULL, NULL }
};
static const gint n_clutter_alphas = G_N_ELEMENTS (clutter_alphas);
......
......@@ -123,6 +123,16 @@ frame_cb (ClutterTimeline *timeline,
}
}
static gdouble
my_sine_wave (ClutterAlpha *alpha,
gpointer dummy G_GNUC_UNUSED)
{
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
gdouble progress = clutter_timeline_get_progress (timeline);
return sin (progress * G_PI);
}
G_MODULE_EXPORT int
test_actors_main (int argc, char *argv[])
{
......@@ -168,8 +178,7 @@ test_actors_main (int argc, char *argv[])
g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), oh);
/* Set up some behaviours to handle scaling */
alpha = clutter_alpha_new_with_func (timeline, clutter_sine_func,
NULL, NULL);
alpha = clutter_alpha_new_with_func (timeline, my_sine_wave, NULL, NULL);
scaler_1 = clutter_behaviour_scale_new (alpha,
0.5, 0.5,
......
......@@ -765,7 +765,7 @@ test_layout_main (int argc, char *argv[])
G_CALLBACK (relayout_on_frame),
NULL);
alpha = clutter_alpha_new_full (main_timeline, CLUTTER_SINE_IN_OUT);
alpha = clutter_alpha_new_full (main_timeline, CLUTTER_LINEAR);
behaviour = clutter_behaviour_scale_new (alpha, 1.0, 1.0, 2.0, 2.0);
box = my_thing_new (10, 10);
......
......@@ -160,6 +160,16 @@ hand_post_paint (ClutterActor *actor,
oh->paint_guards[actor_num] = FALSE;
}
static gdouble
my_sine_wave (ClutterAlpha *alpha,
gpointer dummy G_GNUC_UNUSED)
{
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
gdouble progress = clutter_timeline_get_progress (timeline);
return sin (progress * G_PI);
}
G_MODULE_EXPORT int
test_paint_wrapper_main (int argc, char *argv[])
{
......@@ -205,7 +215,7 @@ test_paint_wrapper_main (int argc, char *argv[])
g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), oh);
/* Set up some behaviours to handle scaling */
alpha = clutter_alpha_new_full (timeline, CLUTTER_SINE_IN_OUT);
alpha = clutter_alpha_new_with_func (timeline, my_sine_wave, NULL, NULL);
scaler_1 = clutter_behaviour_scale_new (alpha,
0.5, 0.5,
......
......@@ -36,6 +36,15 @@ set_next_gravity (ClutterActor *actor)
gindex = 0;
}
static gdouble
my_ramp_func (ClutterAlpha *alpha,
gpointer unused)
{
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
return clutter_timeline_get_progress (timeline);
}
G_MODULE_EXPORT int
test_scale_main (int argc, char *argv[])
{
......@@ -79,7 +88,7 @@ test_scale_main (int argc, char *argv[])
timeline = clutter_timeline_new_for_duration (750);
alpha = clutter_alpha_new_with_func (timeline,
clutter_ramp_func,
my_ramp_func,
NULL, NULL);
behave = clutter_behaviour_scale_new (alpha,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment