diff --git a/clutter/clutter-alpha.c b/clutter/clutter-alpha.c index 31c325363..4fab3426a 100644 --- a/clutter/clutter-alpha.c +++ b/clutter/clutter-alpha.c @@ -8,7 +8,8 @@ * Emmanuele Bassi * Tomas Frydrych * - * 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 @@ -31,8 +32,8 @@ * @short_description: A class for calculating an alpha value as a function * of time. * - * #ClutterAlpha is a class for calculating an integer value between - * 0 and %CLUTTER_ALPHA_MAX_ALPHA as a function of time. + * #ClutterAlpha is a class for calculating an floating point value + * dependent only on the position of a #ClutterTimeline. * * A #ClutterAlpha binds a #ClutterTimeline to a progress function which * translates the time T into an adimensional factor alpha. The factor can @@ -42,7 +43,8 @@ * You should provide a #ClutterTimeline and bind it to the #ClutterAlpha * instance using clutter_alpha_set_timeline(). You should also set an * "animation mode", either by using the #ClutterAnimatioMode values that - * Clutter itself provides or by registering custom functions. + * Clutter itself provides or by registering custom functions using + * clutter_alpha_register_func(). * * Instead of a #ClutterAnimationMode you may provide a function returning * the alpha value depending on the progress of the timeline, using @@ -54,11 +56,12 @@ * pause, stop or resume the #ClutterAlpha from calling the alpha function by * using the appropriate functions of the #ClutterTimeline object. * - * #ClutterAlpha is used to "drive" a #ClutterBehaviour instance. + * #ClutterAlpha is used to "drive" a #ClutterBehaviour instance, and it + * is internally used by the #ClutterAnimation API. * - *
- * Graphic representation of some alpha functions - * + *
+ * Easing modes provided by Clutter + * *
* * Since: 0.2 @@ -85,7 +88,7 @@ struct _ClutterAlphaPrivate ClutterTimeline *timeline; guint timeline_new_frame_id; - guint32 alpha; + gdouble alpha; GClosure *closure; @@ -160,7 +163,7 @@ clutter_alpha_get_property (GObject *object, break; case PROP_ALPHA: - g_value_set_uint (value, priv->alpha); + g_value_set_double (value, priv->alpha); break; case PROP_MODE: @@ -199,6 +202,7 @@ static void clutter_alpha_class_init (ClutterAlphaClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; object_class->set_property = clutter_alpha_set_property; object_class->get_property = clutter_alpha_get_property; @@ -214,29 +218,30 @@ clutter_alpha_class_init (ClutterAlphaClass *klass) * * Since: 0.2 */ - g_object_class_install_property (object_class, - PROP_TIMELINE, - g_param_spec_object ("timeline", - "Timeline", - "Timeline", - CLUTTER_TYPE_TIMELINE, - CLUTTER_PARAM_READWRITE)); + pspec = g_param_spec_object ("timeline", + "Timeline", + "Timeline used by the alpha", + CLUTTER_TYPE_TIMELINE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_TIMELINE, pspec); + /** * ClutterAlpha:alpha: * - * The alpha value as computed by the alpha function. + * The alpha value as computed by the alpha function. The linear + * interval is 0.0 to 1.0, but the Alpha allows overshooting by + * one unit in each direction, so the valid interval is -1.0 to 2.0. * * Since: 0.2 */ - g_object_class_install_property (object_class, - PROP_ALPHA, - g_param_spec_uint ("alpha", - "Alpha value", - "Alpha value", - 0, - CLUTTER_ALPHA_MAX_ALPHA, - 0, - CLUTTER_PARAM_READABLE)); + pspec = g_param_spec_double ("alpha", + "Alpha value", + "Alpha value", + -1.0, 2.0, + 0.0, + CLUTTER_PARAM_READABLE); + g_object_class_install_property (object_class, PROP_ALPHA, pspec); + /** * ClutterAlpha:mode: * @@ -250,15 +255,13 @@ clutter_alpha_class_init (ClutterAlphaClass *klass) * * Since: 1.0 */ - g_object_class_install_property (object_class, - PROP_MODE, - g_param_spec_ulong ("mode", - "Mode", - "Progress mode", - 0, G_MAXULONG, - CLUTTER_CUSTOM_MODE, - G_PARAM_CONSTRUCT | - CLUTTER_PARAM_READWRITE)); + pspec = g_param_spec_ulong ("mode", + "Mode", + "Progress mode", + 0, G_MAXULONG, + CLUTTER_CUSTOM_MODE, + G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_MODE, pspec); } static void @@ -269,6 +272,7 @@ clutter_alpha_init (ClutterAlpha *self) ClutterAlphaPrivate); self->priv->mode = CLUTTER_CUSTOM_MODE; + self->priv->alpha = 0.0; } /** @@ -281,11 +285,11 @@ clutter_alpha_init (ClutterAlpha *self) * * Since: 0.2 */ -guint32 +gdouble clutter_alpha_get_alpha (ClutterAlpha *alpha) { ClutterAlphaPrivate *priv; - guint32 retval = 0; + gdouble retval = 0; g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), 0); @@ -298,18 +302,14 @@ clutter_alpha_get_alpha (ClutterAlpha *alpha) g_object_ref (alpha); - g_value_init (&result_value, G_TYPE_UINT); + g_value_init (&result_value, G_TYPE_DOUBLE); g_value_init (¶ms, CLUTTER_TYPE_ALPHA); g_value_set_object (¶ms, alpha); - g_closure_invoke (priv->closure, - &result_value, - 1, - ¶ms, - NULL); + g_closure_invoke (priv->closure, &result_value, 1, ¶ms, NULL); - retval = g_value_get_uint (&result_value); + retval = g_value_get_double (&result_value); g_value_unset (&result_value); g_value_unset (¶ms); @@ -320,6 +320,37 @@ clutter_alpha_get_alpha (ClutterAlpha *alpha) return retval; } +/* + * clutter_alpha_set_closure_internal: + * @alpha: a #ClutterAlpha + * @closure: a #GClosure + * + * Sets the @closure for @alpha. This function does not + * set the #ClutterAlpha:mode property and does not emit + * the #GObject::notify signal for it. + */ +static inline void +clutter_alpha_set_closure_internal (ClutterAlpha *alpha, + GClosure *closure) +{ + ClutterAlphaPrivate *priv = alpha->priv; + + if (priv->closure) + g_closure_unref (priv->closure); + + /* need to take ownership of the closure before sinking it */ + priv->closure = g_closure_ref (closure); + g_closure_sink (closure); + + /* set the marshaller */ + if (G_CLOSURE_NEEDS_MARSHAL (closure)) + { + GClosureMarshal marshal = clutter_marshal_DOUBLE__VOID; + + g_closure_set_marshal (closure, marshal); + } +} + /** * clutter_alpha_set_closure: * @alpha: A #ClutterAlpha @@ -341,18 +372,7 @@ clutter_alpha_set_closure (ClutterAlpha *alpha, priv = alpha->priv; - if (priv->closure) - g_closure_unref (priv->closure); - - priv->closure = g_closure_ref (closure); - g_closure_sink (closure); - - if (G_CLOSURE_NEEDS_MARSHAL (closure)) - { - GClosureMarshal marshal = clutter_marshal_UINT__VOID; - - g_closure_set_marshal (closure, marshal); - } + clutter_alpha_set_closure_internal (alpha, closure); priv->mode = CLUTTER_CUSTOM_MODE; g_object_notify (G_OBJECT (alpha), "mode"); @@ -379,13 +399,19 @@ clutter_alpha_set_func (ClutterAlpha *alpha, gpointer data, GDestroyNotify destroy) { + ClutterAlphaPrivate *priv; GClosure *closure; g_return_if_fail (CLUTTER_IS_ALPHA (alpha)); g_return_if_fail (func != NULL); - + + priv = alpha->priv; + closure = g_cclosure_new (G_CALLBACK (func), data, (GClosureNotify) destroy); - clutter_alpha_set_closure (alpha, closure); + clutter_alpha_set_closure_internal (alpha, closure); + + priv->mode = CLUTTER_CUSTOM_MODE; + g_object_notify (G_OBJECT (alpha), "mode"); } /** @@ -553,6 +579,418 @@ clutter_alpha_get_mode (ClutterAlpha *alpha) return alpha->priv->mode; } +static gdouble +clutter_linear (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + + return clutter_timeline_get_progress (timeline); +} + +static gdouble +clutter_ease_in_quad (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble progress = clutter_timeline_get_progress (timeline); + + return progress * progress; +} + +static gdouble +clutter_ease_out_quad (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return -1.0 * (t /= d) * (t - 2); +} + +static gdouble +clutter_ease_in_out_quad (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + if ((t /= d / 2) < 1) + return 0.5 * t * t; + + return -0.5 * ((--t) * (t - 2) - 1); +} + +static gdouble +clutter_ease_in_cubic (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t /= d) * t * t; +} + +static gdouble +clutter_ease_out_cubic (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t = t / d - 1) * t * t + 1; +} + +static gdouble +clutter_ease_in_out_cubic (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + if ((t /= d / 2) < 1) + return 0.5 * t * t * t; + + return 0.5 * ((t -= 2) * t * t + 2); +} + +static gdouble +clutter_ease_in_quart (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t /= d) * t * t * t; +} + +static gdouble +clutter_ease_out_quart (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return -0.5 * ((t = t / d - 1) * t * t * t - 1); +} + +static gdouble +clutter_ease_in_out_quart (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + if ((t /= d / 2) < 1) + return 0.5 * t * t * t * t; + + return -0.5 * ((t -= 2) * t * t * t - 2); +} + +static gdouble +clutter_ease_in_quint (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) + { + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t /= d) * t * t * t * t; +} + +static gdouble +clutter_ease_out_quint (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t = t / d - 1) * t * t * t * t + 1; +} + +static gdouble +clutter_ease_in_out_quint (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + if ((t /= d / 2) < 1) + return 0.5 * t * t * t * t * t; + + return 0.5 * ((t -= 2) * t * t * t * t + 2); +} + +static gdouble +clutter_ease_in_sine (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return -1.0 * cos (t / d * G_PI_2) + 1.0; +} + +static gdouble +clutter_ease_out_sine (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return sin (t / d * G_PI_2); +} + +static gdouble +clutter_ease_in_out_sine (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return -0.5 * (cos (G_PI * t / d) - 1); +} + +static gdouble +clutter_ease_in_expo (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t == 0) ? 0.0 : pow (2, 10 * (t / d - 1)); +} + +static gdouble +clutter_ease_out_expo (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t == d) ? 1.0 : -pow (2, -10 * t / d) + 1; +} + +static gdouble +clutter_ease_in_out_expo (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + if (t == 0) + return 0.0; + + if (t == d) + return 1.0; + + if ((t /= d / 2) < 1) + return 0.5 * pow (2, 10 * (t - 1)); + + return 0.5 * (-pow (2, -10 * --t) + 2); +} + +static gdouble +clutter_ease_in_circ (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return -1.0 * (sqrt (1 - (t /= d) * t) - 1); +} + +static gdouble +clutter_ease_out_circ (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return sqrt (1 - (t = t / d - 1) * t); +} + +static gdouble +clutter_ease_in_out_circ (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + if ((t /= d / 2) < 1) + return -0.5 * (sqrt (1 - t * t) - 1); + + return 0.5 * (sqrt (1 - (t -= 2) * t) + 1); +} + +static gdouble +clutter_ease_in_elastic (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble p = d * .3; + gdouble s = p / 4; + + if ((t /= d) == 1) + return 1.0; + + return -(pow (2, 10 * (t -= 1)) * sin ((t * d - s) * (2 * G_PI) / p)); +} + +static gdouble +clutter_ease_out_elastic (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble p = d * .3; + gdouble s = p / 4; + + if ((t /= d) == 1) + return 1.0; + + return pow (2, -10 * t) * sin ((t * d - s) * (2 * G_PI) / p) + 1.0; +} + +static gdouble +clutter_ease_in_out_elastic (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble p = d * (.3 * 1.5); + gdouble s = p / 4; + + if ((t /= d / 2) == 2) + return 1.0; + + if (t < 1) + return -.5 * (pow (2, 10 * (t -= 1)) * sin ((t * d - s) * (2 * G_PI) / p)); + else + { + return pow (2, -10 * (t -= 1)) + * sin ((t * d - s) * (2 * G_PI) / p) + * .5 + 1.0; + } +} + +static gdouble +clutter_ease_in_back (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t /= d) * t * ((1.70158 + 1) * t - 1.70158); +} + +static gdouble +clutter_ease_out_back (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return (t = t / d - 1) * t * ((1.70158 + 1) * t + 1.70158) + 1; +} + +static gdouble +clutter_ease_in_out_back (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble s = 1.70158; + + if ((t /= d / 2) < 1) + return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s)); + + return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); +} + +static gdouble +ease_out_bounce_internal (gdouble t, + gdouble d) +{ + if ((t /= d) < (1 / 2.75)) + return 7.5625 * t * t; + else if (t < (2 / 2.75)) + return 7.5625 * (t -= (1.5 / 2.75)) * t + .75; + else if (t < (2.5 / 2.75)) + return 7.5625 * (t -= (2.25 / 2.75)) * t + .9375; + else + return 7.5625 * (t -= (2.625 / 2.75)) * t + .984375; +} + +static gdouble +ease_in_bounce_internal (gdouble t, + gdouble d) +{ + return 1.0 - ease_out_bounce_internal (d - t, d); +} + +static gdouble +clutter_ease_in_bounce (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return ease_in_bounce_internal (t, d); +} + +static gdouble +clutter_ease_out_bounce (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + return ease_out_bounce_internal (t, d); +} + +static gdouble +clutter_ease_in_out_bounce (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = alpha->priv->timeline; + gdouble t = clutter_timeline_get_current_frame (timeline); + gdouble d = clutter_timeline_get_n_frames (timeline); + + if (t < d / 2) + return ease_in_bounce_internal (t * 2, d) * 0.5; + else + return ease_out_bounce_internal (t * 2 - d, d) * 0.5 + 1.0 * 0.5; +} + /* static enum/function mapping table for the animation modes * we provide internally * @@ -562,19 +1000,41 @@ static const struct { gulong mode; ClutterAlphaFunc func; } animation_modes[] = { - { CLUTTER_CUSTOM_MODE, NULL }, - { CLUTTER_LINEAR, clutter_ramp_inc_func }, - { CLUTTER_SINE_IN, clutter_sine_in_func }, - { CLUTTER_SINE_OUT, clutter_sine_out_func }, - { CLUTTER_SINE_IN_OUT, clutter_sine_in_out_func }, - { CLUTTER_EASE_IN, clutter_ease_in_func }, - { CLUTTER_EASE_OUT, clutter_ease_out_func }, - { CLUTTER_EASE_IN_OUT, clutter_ease_in_out_func }, - { CLUTTER_EXPO_IN, clutter_exp_in_func }, - { CLUTTER_EXPO_OUT, clutter_exp_out_func }, - { CLUTTER_EXPO_IN_OUT, clutter_exp_in_out_func }, - { CLUTTER_SMOOTH_IN_OUT, clutter_smoothstep_inc_func }, - { CLUTTER_ANIMATION_LAST, NULL }, + { CLUTTER_CUSTOM_MODE, NULL }, + + { CLUTTER_LINEAR, clutter_linear }, + { CLUTTER_EASE_IN_QUAD, clutter_ease_in_quad }, + { CLUTTER_EASE_OUT_QUAD, clutter_ease_out_quad }, + { CLUTTER_EASE_IN_OUT_QUAD, clutter_ease_in_out_quad }, + { CLUTTER_EASE_IN_CUBIC, clutter_ease_in_cubic }, + { CLUTTER_EASE_OUT_CUBIC, clutter_ease_out_cubic }, + { CLUTTER_EASE_IN_OUT_CUBIC, clutter_ease_in_out_cubic }, + { CLUTTER_EASE_IN_QUART, clutter_ease_in_quart }, + { CLUTTER_EASE_OUT_QUART, clutter_ease_out_quart }, + { CLUTTER_EASE_IN_OUT_QUART, clutter_ease_in_out_quart }, + { CLUTTER_EASE_IN_QUINT, clutter_ease_in_quint }, + { CLUTTER_EASE_OUT_QUINT, clutter_ease_out_quint }, + { CLUTTER_EASE_IN_OUT_QUINT, clutter_ease_in_out_quint }, + { CLUTTER_EASE_IN_SINE, clutter_ease_in_sine }, + { CLUTTER_EASE_OUT_SINE, clutter_ease_out_sine }, + { CLUTTER_EASE_IN_OUT_SINE, clutter_ease_in_out_sine }, + { CLUTTER_EASE_IN_EXPO, clutter_ease_in_expo }, + { CLUTTER_EASE_OUT_EXPO, clutter_ease_out_expo }, + { CLUTTER_EASE_IN_OUT_EXPO, clutter_ease_in_out_expo }, + { CLUTTER_EASE_IN_CIRC, clutter_ease_in_circ }, + { CLUTTER_EASE_OUT_CIRC, clutter_ease_out_circ }, + { CLUTTER_EASE_IN_OUT_CIRC, clutter_ease_in_out_circ }, + { CLUTTER_EASE_IN_ELASTIC, clutter_ease_in_elastic }, + { CLUTTER_EASE_OUT_ELASTIC, clutter_ease_out_elastic }, + { CLUTTER_EASE_IN_OUT_ELASTIC, clutter_ease_in_out_elastic }, + { CLUTTER_EASE_IN_BACK, clutter_ease_in_back }, + { CLUTTER_EASE_OUT_BACK, clutter_ease_out_back }, + { CLUTTER_EASE_IN_OUT_BACK, clutter_ease_in_out_back }, + { CLUTTER_EASE_IN_BOUNCE, clutter_ease_in_bounce }, + { CLUTTER_EASE_OUT_BOUNCE, clutter_ease_out_bounce }, + { CLUTTER_EASE_IN_OUT_BOUNCE, clutter_ease_in_out_bounce }, + + { CLUTTER_ANIMATION_LAST, NULL }, }; typedef struct _AlphaData { @@ -610,15 +1070,24 @@ clutter_alpha_set_mode (ClutterAlpha *alpha, priv = alpha->priv; - if (mode < CLUTTER_ANIMATION_LAST) + if (mode == CLUTTER_CUSTOM_MODE) { + priv->mode = mode; + } + else if (mode < CLUTTER_ANIMATION_LAST) + { + GClosure *closure; + /* sanity check to avoid getting an out of sync * enum/function mapping */ g_assert (animation_modes[mode].mode == mode); + g_assert (animation_modes[mode].func != NULL); - if (G_LIKELY (animation_modes[mode].func != NULL)) - clutter_alpha_set_func (alpha, animation_modes[mode].func, NULL, NULL); + closure = g_cclosure_new (G_CALLBACK (animation_modes[mode].func), + NULL, + NULL); + clutter_alpha_set_closure_internal (alpha, closure); priv->mode = mode; } @@ -648,9 +1117,14 @@ clutter_alpha_set_mode (ClutterAlpha *alpha, if (alpha_data->closure_set) clutter_alpha_set_closure (alpha, alpha_data->closure); else - clutter_alpha_set_func (alpha, alpha_data->func, - alpha_data->data, - NULL); + { + GClosure *closure; + + closure = g_cclosure_new (G_CALLBACK (alpha_data->func), + alpha_data->data, + NULL); + clutter_alpha_set_closure_internal (alpha, closure); + } priv->mode = mode; } @@ -660,6 +1134,17 @@ clutter_alpha_set_mode (ClutterAlpha *alpha, g_object_notify (G_OBJECT (alpha), "mode"); } +static gulong +register_alpha_internal (AlphaData *alpha_data) +{ + if (G_UNLIKELY (clutter_alphas == NULL)) + clutter_alphas = g_ptr_array_new (); + + g_ptr_array_add (clutter_alphas, alpha_data); + + return clutter_alphas->len + CLUTTER_ANIMATION_LAST; +} + /** * clutter_alpha_register_func: * @func: a #ClutterAlphaFunc @@ -687,12 +1172,7 @@ clutter_alpha_register_func (ClutterAlphaFunc func, alpha_data->func = func; alpha_data->data = data; - if (G_UNLIKELY (clutter_alphas == NULL)) - clutter_alphas = g_ptr_array_new (); - - g_ptr_array_add (clutter_alphas, alpha_data); - - return clutter_alphas->len + CLUTTER_ANIMATION_LAST; + return register_alpha_internal (alpha_data); } /** @@ -713,893 +1193,13 @@ clutter_alpha_register_func (ClutterAlphaFunc func, gulong clutter_alpha_register_closure (GClosure *closure) { - AlphaData *data; + AlphaData *alpha_data; g_return_val_if_fail (closure != NULL, 0); - data = g_slice_new (AlphaData); - data->closure_set = TRUE; - data->closure = closure; + alpha_data = g_slice_new (AlphaData); + alpha_data->closure_set = TRUE; + alpha_data->closure = closure; - if (G_UNLIKELY (clutter_alphas == NULL)) - clutter_alphas = g_ptr_array_new (); - - g_ptr_array_add (clutter_alphas, data); - - return clutter_alphas->len + CLUTTER_ANIMATION_LAST; -} - -/** - * clutter_ramp_inc_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a monotonic increasing ramp. You - * can use this function as the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.2 - */ -guint32 -clutter_ramp_inc_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint current_frame_num, n_frames; - - timeline = clutter_alpha_get_timeline (alpha); - - current_frame_num = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - return (current_frame_num * CLUTTER_ALPHA_MAX_ALPHA) / n_frames; -} - -/** - * CLUTTER_ALPHA_RAMP_DEC: - * - * Convenience symbol for clutter_ramp_dec_func(). - * - * Since: 0.2 - */ - -/** - * clutter_ramp_dec_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a monotonic decreasing ramp. You - * can use this function as the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.2 - */ -guint32 -clutter_ramp_dec_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint current_frame_num, n_frames; - - timeline = clutter_alpha_get_timeline (alpha); - - current_frame_num = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - return (n_frames - current_frame_num) - * CLUTTER_ALPHA_MAX_ALPHA - / n_frames; -} - -/** - * CLUTTER_ALPHA_RAMP: - * - * Convenience symbol for clutter_ramp_func(). - * - * Since: 0.2 - */ - -/** - * clutter_ramp_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a full ramp function (increase for - * half the time, decrease for the remaining half). You can use this - * function as the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.2 - */ -guint32 -clutter_ramp_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint current_frame_num, n_frames; - - timeline = clutter_alpha_get_timeline (alpha); - - current_frame_num = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - if (current_frame_num > (n_frames / 2)) - { - return (n_frames - current_frame_num) - * CLUTTER_ALPHA_MAX_ALPHA - / (n_frames / 2); - } - else - { - return current_frame_num - * CLUTTER_ALPHA_MAX_ALPHA - / (n_frames / 2); - } -} - -#if 0 -/* - * The following three functions are left in place for reference - * purposes. - */ -static guint32 -sincx1024_func (ClutterAlpha *alpha, - float angle, - ClutterFixed offset) -{ - ClutterTimeline *timeline; - gint current_frame_num, n_frames; - float x; - ClutterFixed sine; - - timeline = clutter_alpha_get_timeline (alpha); - - current_frame_num = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - x = angle * current_frame_num / n_frames; - - x -= (512 * 512 / angle); - - sine = ((cogl_angle_sin (x) + offset) / 2) - * CLUTTER_ALPHA_MAX_ALPHA; - - sine = sine >> COGL_FIXED_Q; - - return sine; -} - -static guint32 -sincx_func (ClutterAlpha *alpha, - ClutterFixed angle, - ClutterFixed offset) -{ - ClutterTimeline *timeline; - gint current_frame_num, n_frames; - ClutterFixed x, sine; - - timeline = clutter_alpha_get_timeline (alpha); - - current_frame_num = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - x = angle * current_frame_num / n_frames; - x = CLUTTER_FIXED_MUL (x, CFX_PI) - - CLUTTER_FIXED_DIV (CFX_PI, angle); - - sine = (cogl_angle_sin (x) + offset) / 2; - - CLUTTER_NOTE (ALPHA, "sine: %2f\n", CLUTTER_FIXED_TO_DOUBLE (sine)); - - return (sine * CLUTTER_ALPHA_MAX_ALPHA); -} - -/* NB: angle is not in radians but in muliples of PI, i.e., 2.0 - * represents full circle. - */ -static guint32 -sinc_func (ClutterAlpha *alpha, - float angle, - float offset) -{ - ClutterTimeline *timeline; - gint current_frame_num, n_frames; - gdouble x, sine; - - timeline = clutter_alpha_get_timeline (alpha); - - current_frame_num = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - /* FIXME: fixed point, and fixed point sine() */ - - x = (gdouble) (current_frame_num * angle * G_PI) / n_frames ; - sine = (sin (x - (G_PI / angle)) + offset) * 0.5f; - - CLUTTER_NOTE (ALPHA, "sine: %2f\n",sine); - - return COGL_FLOAT_TO_INT ((sine * (gdouble) CLUTTER_ALPHA_MAX_ALPHA)); -} -#endif - -/** - * CLUTTER_ALPHA_SINE: - * - * Convenience symbol for clutter_sine_func(). - * - * Since: 0.2 - */ - -/** - * clutter_sine_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a sine wave. You can use this - * function as the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.2 - */ -guint32 -clutter_sine_func (ClutterAlpha *alpha, - gpointer dummy) -{ -#if 1 - ClutterTimeline *timeline; - gint current_frame_num, n_frames; - float radians, sine; - - timeline = clutter_alpha_get_timeline (alpha); - - current_frame_num = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - radians = ((float)current_frame_num / n_frames) * (2.0 * G_PI); - sine = sinf (radians); - - /* shift from range [-1, 1] -> [0, 1] */ - sine = (sine + 1.0) / 2.0; - - CLUTTER_NOTE (ALPHA, "sine: %2f\n", sine); - - return sine * CLUTTER_ALPHA_MAX_ALPHA; -#elif 0 - return sinc_func (alpha, 2.0, 1.0); -#elif 0 - /* 2.0 above represents full circle */ - return sincx1024_func (alpha, 1024, 1.0); -#endif -} - -/** - * CLUTTER_ALPHA_SINE_INC: - * - * Convenience symbol for clutter_sine_inc_func(). - * - * Since: 0.2 - */ - -/** - * clutter_sine_inc_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a sine wave over interval [0, pi / 2]. - * You can use this function as the alpha function for - * clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.2 - */ -guint32 -clutter_sine_inc_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline * timeline; - gint frame; - gint n_frames; - float radians; - float sine; - - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - radians = ((float)frame / n_frames) * (G_PI / 2); - sine = sinf (radians); - - return (guint32) (sine * CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * CLUTTER_ALPHA_SINE_DEC: - * - * Convenience symbol for clutter_sine_dec_func(). - * - * Since: 0.2 - */ - -/** - * clutter_sine_dec_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a sine wave over interval [pi / 2, pi]. - * You can use this function as the alpha function for - * clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.4 - */ -guint32 -clutter_sine_dec_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline * timeline; - gint frame; - gint n_frames; - float radians; - float sine; - - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - radians = ((float)frame / n_frames) * (G_PI / 2); - sine = sinf (radians + (G_PI / 2)); - - return (guint32) (sine * CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * CLUTTER_ALPHA_SINE_HALF: - * - * Convenience symbol for clutter_sine_half_func(). - * - * Since: 0.4 - */ - -/** - * clutter_sine_half_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a sine wave over interval [0, pi]. - * You can use this function as the alpha function for - * clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.4 - */ -guint32 -clutter_sine_half_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint frame; - gint n_frames; - float radians; - float sine; - - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - radians = ((float)frame / n_frames) * G_PI; - sine = sinf (radians); - - return (guint32) (sine * CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * clutter_sine_in_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for (sin(x) + 1) over the - * interval [-pi/2, 0]. - * - * You can use this function as the alpha function for - * clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 1.0 - */ -guint32 -clutter_sine_in_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint frame; - gint n_frames; - float radians; - float sine; - - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - radians = ((float)frame / n_frames) * (G_PI / 2); - sine = sinf (radians - (G_PI / 2)); - - /* shift from range [-1, 0] -> [0, 1] */ - sine = sine + 1.0; - - return (guint32) (sine * CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * clutter_sine_in_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for sin(x) over the interval [0, pi/2]. - * - * You can use this function as the alpha function for - * clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 1.0 - */ -guint32 -clutter_sine_out_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint frame; - gint n_frames; - float radians; - float sine; - - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - radians = ((float)frame / n_frames) * (G_PI / 2); - sine = sinf (radians); - - return (guint32) (sine * CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * clutter_sine_in_out_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for (sin(x) + 1) / 2 over the - * interval [-pi/2, pi/2]. - * - * You can use this function as the alpha function for - * clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 1.0 - */ -guint32 -clutter_sine_in_out_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint frame; - gint n_frames; - float radians; - float sine; - - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - radians = ((float)frame / n_frames) * G_PI; - sine = sinf (radians - (G_PI / 2)); - - /* shift from range [-1, 1] -> [0, 1] */ - sine = (sine + 1.0) / 2.0; - - return (guint32) (sine * CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * CLUTTER_ALPHA_SQUARE: - * - * Convenience symbol for clutter_square_func(). - * - * Since: 0.4 - * - * Deprecated: 1.0: Use clutter_square_func() instead - */ - -/** - * clutter_square_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a square wave. You can use this - * function as the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value - * - * Since: 0.4 - */ -guint32 -clutter_square_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint current_frame_num, n_frames; - - timeline = clutter_alpha_get_timeline (alpha); - - current_frame_num = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - return (current_frame_num > (n_frames / 2)) ? CLUTTER_ALPHA_MAX_ALPHA - : 0; -} - -/** - * CLUTTER_ALPHA_SMOOTHSTEP_INC: - * - * Convenience symbol for clutter_smoothstep_inc_func(). - * - * Since: 0.4 - */ - -/** - * clutter_smoothstep_inc_func: - * @alpha: a #ClutterAlpha - * @dummy: unused - * - * Convenience alpha function for a smoothstep curve. You can use this - * function as the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value - * - * Since: 0.4 - */ -guint32 -clutter_smoothstep_inc_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gint frame; - gint n_frames; - float r; - float x; - - /* - * The smoothstep function uses f(x) = -2x^3 + 3x^2 where x is from <0,1>, - * and precission is critical. - */ - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - x = (float)frame / n_frames; - - /* - * f(x) = -2x^3 + 3x^2 - */ - r = -2 * x * x * x + 3 * x * x; - - return (r * CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * CLUTTER_ALPHA_SMOOTHSTEP_DEC: - * - * Convenience symbol for clutter_smoothstep_dec_func(). - * - * Since: 0.4 - */ - -/** - * clutter_smoothstep_dec_func: - * @alpha: a #ClutterAlpha - * @dummy: unused - * - * Convenience alpha function for a downward smoothstep curve. You can use - * this function as the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value - * - * Since: 0.4 - */ -guint32 -clutter_smoothstep_dec_func (ClutterAlpha *alpha, - gpointer dummy) -{ - return CLUTTER_ALPHA_MAX_ALPHA - clutter_smoothstep_inc_func (alpha, dummy); -} - -/** - * CLUTTER_ALPHA_EXP_INC: - * - * Convenience symbol for clutter_exp_inc_func() - * - * Since: 0.4 - */ - -/** - * clutter_exp_inc_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a 2^x curve. You can use this function as the - * alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.4 - */ -guint32 -clutter_exp_inc_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline * timeline; - gint frame; - gint n_frames; - ClutterFixed x; - ClutterFixed x_alpha_max = 0x100000; - guint32 result; - - /* - * Choose x_alpha_max such that - * - * (2^x_alpha_max) - 1 == CLUTTER_ALPHA_MAX_ALPHA - */ - /* XXX: If this fails: - * Adjust x_alpha_max to match CLUTTER_ALPHA_MAX_ALPHA */ - g_assert (CLUTTER_ALPHA_MAX_ALPHA == 65535.0); - - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - x = x_alpha_max * frame / n_frames; - - result = CLAMP (powf (2, x) - 1, 0, CLUTTER_ALPHA_MAX_ALPHA); - - return result; -} - -/** - * CLUTTER_ALPHA_EXP_DEC: - * - * Convenience symbold for clutter_exp_dec_func(). - * - * Since: 0.4 - */ - -/** - * clutter_exp_dec_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a decreasing 2^x curve. You can use this - * function as the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 0.4 - */ -guint32 -clutter_exp_dec_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline * timeline; - gint frame; - gint n_frames; - ClutterFixed x; - ClutterFixed x_alpha_max = 0x100000; - guint32 result; - - /* - * Choose x_alpha_max such that - * - * (2^x_alpha_max) - 1 == CLUTTER_ALPHA_MAX_ALPHA - */ - /* XXX: If this fails: - * Adjust x_alpha_max to match CLUTTER_ALPHA_MAX_ALPHA */ - g_assert (CLUTTER_ALPHA_MAX_ALPHA == 65535.0); - - timeline = clutter_alpha_get_timeline (alpha); - frame = clutter_timeline_get_current_frame (timeline); - n_frames = clutter_timeline_get_n_frames (timeline); - - x = (x_alpha_max * (n_frames - frame)) / n_frames; - - result = CLAMP (powf (2, x) - 1, 0, CLUTTER_ALPHA_MAX_ALPHA); - - return result; -} - -static inline gdouble -clutter_cubic_bezier (ClutterAlpha *alpha, - gdouble x_1, - gdouble y_1, - gdouble x_2, - gdouble y_2) -{ - ClutterTimeline *timeline; - gdouble t, b_t, res; - - /* the cubic bezier has a parametric form of: - * - * B(t) = (1 - t)^3 * P_0 - * + 3t * (1 - t)^2 * P_1 - * + 3t^2 * (1 - t) * P_2 - * + t^3 * P_3 (with t included in [0, 1]) - * - * the P_0 and P_3 points are set to (0, 0) and (1, 1) respectively, - * and the curve never passes through P_1 and P_2 - with these two - * points merely acting as control points for the curve starting - * from P_0 and ending at P_3. - * - * since the starting point is (0, 0) we can simplify the previous - * parametric form to: - * - * B(t) = 3t * (1 - t)^2 * P_1 - * + 3t^2 * (1 - t) * P_2 - * + t^3 * P_3 (with t included in [0, 1]) - * - * and, similarly, since the final point is (1, 1) we can simplify - * it further to: - * - * B(t) = 3t * (1 - t)^2 * P_1 - * + 3t^2 * (1 - t) * P_2 - * + t^3 (with t included in [0, 1]) - * - * since an alpha function has only a time parameter and we have two - * coordinates for each point, we pass the time as the first - * coordinate for the point and then we solve the cubic beziér curve - * for the second coordinate at the same point. - */ - - timeline = clutter_alpha_get_timeline (alpha); - t = clutter_timeline_get_progress (timeline); - - b_t = 3 * t * pow (1 - t, 2) * x_1 - + 3 * pow (t, 2) * (1 - t) * x_2 - + pow (t, 3); - - res = 3 * b_t * pow (1 - b_t, 2) * y_1 - + 3 * pow (b_t, 2) * (1 - b_t) * y_2 - + pow (b_t, 3); - - return res; -} - -/** - * clutter_ease_in_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a cubic Beziér curve with control - * points at (0.42, 0) and (1, 0). You can use this function as the - * alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 1.0 - */ -guint32 -clutter_ease_in_func (ClutterAlpha *alpha, - gpointer dummy) -{ - gdouble res; - - res = clutter_cubic_bezier (alpha, 0.42, 0, 1, 0); - - return CLAMP (res * CLUTTER_ALPHA_MAX_ALPHA, 0, CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * clutter_ease_out_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a cubic Beziér curve with control - * points at (0, 0) and (0.58, 1). You can use this function as the - * alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 1.0 - */ -guint32 -clutter_ease_out_func (ClutterAlpha *alpha, - gpointer dummy) -{ - gdouble res; - - res = clutter_cubic_bezier (alpha, 0, 0, 0.58, 1); - - return CLAMP (res * CLUTTER_ALPHA_MAX_ALPHA, 0, CLUTTER_ALPHA_MAX_ALPHA); -} - -/** - * clutter_ease_in_out_func: - * @alpha: a #ClutterAlpha - * @dummy: unused argument - * - * Convenience alpha function for a cubic Beziér curve with control - * points at (0.42, 0) and (0.58, 1). You can use this function as - * the alpha function for clutter_alpha_set_func(). - * - * Return value: an alpha value. - * - * Since: 1.0 - */ -guint32 -clutter_ease_in_out_func (ClutterAlpha *alpha, - gpointer dummy) -{ - gdouble res; - - res = clutter_cubic_bezier (alpha, 0.42, 0, 0.58, 1); - - return CLAMP (res * CLUTTER_ALPHA_MAX_ALPHA, 0, CLUTTER_ALPHA_MAX_ALPHA); -} - -guint32 -clutter_exp_in_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gdouble progress, res; - - timeline = clutter_alpha_get_timeline (alpha); - progress = clutter_timeline_get_progress (timeline); - - res = pow (2, 10 * (progress - 1)); - res = CLAMP (res * CLUTTER_ALPHA_MAX_ALPHA, 0, CLUTTER_ALPHA_MAX_ALPHA); - - return res; -} - -guint32 -clutter_exp_out_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gdouble progress, res; - - timeline = clutter_alpha_get_timeline (alpha); - progress = clutter_timeline_get_progress (timeline); - - res = -pow (2, (-10 * progress)) + 1; - res = CLAMP (res * CLUTTER_ALPHA_MAX_ALPHA, 0, CLUTTER_ALPHA_MAX_ALPHA); - - return res; -} - -guint32 -clutter_exp_in_out_func (ClutterAlpha *alpha, - gpointer dummy) -{ - ClutterTimeline *timeline; - gdouble progress, res; - - timeline = clutter_alpha_get_timeline (alpha); - progress = clutter_timeline_get_progress (timeline); - - if (progress < 0.5) - res = 0.5 * pow (2, (10 * (progress - 1))); - else - res = 0.5 * -pow (2, (-10 * progress)) + 1; - - res = CLAMP (res * CLUTTER_ALPHA_MAX_ALPHA, 0, CLUTTER_ALPHA_MAX_ALPHA); - - return res; + return register_alpha_internal (alpha_data); } diff --git a/clutter/clutter-alpha.h b/clutter/clutter-alpha.h index 85f80547a..5f64d1d7d 100644 --- a/clutter/clutter-alpha.h +++ b/clutter/clutter-alpha.h @@ -8,7 +8,8 @@ * Emmanuele Bassi * Tomas Frydrych * - * 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 (65535.0f) - 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__ */ diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index 5994ff38e..900c5fba3 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -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); } diff --git a/clutter/clutter-behaviour-depth.c b/clutter/clutter-behaviour-depth.c index 0749b8e4d..cfb736fed 100644 --- a/clutter/clutter-behaviour-depth.c +++ b/clutter/clutter-behaviour-depth.c @@ -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,10 @@ clutter_behaviour_depth_alpha_notify (ClutterBehaviour *behaviour, priv = CLUTTER_BEHAVIOUR_DEPTH (behaviour)->priv; /* Need to create factor as to avoid borking signedness */ - factor = (float)(alpha_value) / CLUTTER_ALPHA_MAX_ALPHA; - depth = priv->depth_start - + (factor * (priv->depth_end - priv->depth_start)); + depth = (alpha_value * (priv->depth_end - priv->depth_start)) + + 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, diff --git a/clutter/clutter-behaviour-ellipse.c b/clutter/clutter-behaviour-ellipse.c index 0bd8c86fe..2d8091954 100644 --- a/clutter/clutter-behaviour-ellipse.c +++ b/clutter/clutter-behaviour-ellipse.c @@ -201,7 +201,7 @@ clamp_angle (float a) static void clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave, - guint32 alpha) + gdouble alpha) { ClutterBehaviourEllipse *self = CLUTTER_BEHAVIOUR_ELLIPSE (behave); ClutterBehaviourEllipsePrivate *priv = self->priv; @@ -221,7 +221,7 @@ clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave, end -= 360; } - angle = (end - start) * alpha / CLUTTER_ALPHA_MAX_ALPHA + start; + angle = (end - start) * alpha + start; clutter_behaviour_ellipse_advance (self, angle, &knot); diff --git a/clutter/clutter-behaviour-opacity.c b/clutter/clutter-behaviour-opacity.c index f31099442..0ad25c22b 100644 --- a/clutter/clutter-behaviour-opacity.c +++ b/clutter/clutter-behaviour-opacity.c @@ -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); diff --git a/clutter/clutter-behaviour-path.c b/clutter/clutter-behaviour-path.c index 7594fdbfb..eea1733b7 100644 --- a/clutter/clutter-behaviour-path.c +++ b/clutter/clutter-behaviour-path.c @@ -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)); diff --git a/clutter/clutter-behaviour-rotate.c b/clutter/clutter-behaviour-rotate.c index 8bfa16e14..b7402868a 100644 --- a/clutter/clutter-behaviour-rotate.c +++ b/clutter/clutter-behaviour-rotate.c @@ -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,11 +126,10 @@ clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, rotate_behaviour = CLUTTER_BEHAVIOUR_ROTATE (behaviour); priv = rotate_behaviour->priv; - factor = (float)(alpha_value) / CLUTTER_ALPHA_MAX_ALPHA; - angle = 0; - - start = priv->angle_start; - end = priv->angle_end; + factor = CLUTTER_FLOAT_TO_FIXED (alpha_value); + angle = 0; + start = priv->angle_start; + end = priv->angle_end; if (priv->direction == CLUTTER_ROTATE_CW && start >= end) { @@ -141,7 +140,8 @@ clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, end -= 360.0; } - angle = CLUTTER_FIXED_MUL ((end - start), factor) + start; + angle = CLUTTER_FIXED_MUL ((end - start), alpha_value) + + start; clutter_behaviour_actors_foreach (behaviour, alpha_notify_foreach, diff --git a/clutter/clutter-behaviour-scale.c b/clutter/clutter-behaviour-scale.c index 66d4542d2..89b56958f 100644 --- a/clutter/clutter-behaviour-scale.c +++ b/clutter/clutter-behaviour-scale.c @@ -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 = (float)(alpha_value) / CLUTTER_ALPHA_MAX_ALPHA; + factor = CLUTTER_FLOAT_TO_FIXED (alpha_value); scale_x = CLUTTER_FIXED_MUL (factor, (priv->x_scale_end - priv->x_scale_start)); diff --git a/clutter/clutter-behaviour.c b/clutter/clutter-behaviour.c index 006be1bda..f4bdf546f 100644 --- a/clutter/clutter-behaviour.c +++ b/clutter/clutter-behaviour.c @@ -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); diff --git a/clutter/clutter-behaviour.h b/clutter/clutter-behaviour.h index c190961e5..74ac9134c 100644 --- a/clutter/clutter-behaviour.h +++ b/clutter/clutter-behaviour.h @@ -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, diff --git a/clutter/clutter-interval.c b/clutter/clutter-interval.c index ea98ce113..1be5f38a7 100644 --- a/clutter/clutter-interval.c +++ b/clutter/clutter-interval.c @@ -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); diff --git a/clutter/clutter-marshal.list b/clutter/clutter-marshal.list index 613d84a9e..d68ce4b27 100644 --- a/clutter/clutter-marshal.list +++ b/clutter/clutter-marshal.list @@ -1,5 +1,6 @@ BOOLEAN:BOXED BOOLEAN:STRING,UINT,ENUM +DOUBLE:VOID UINT:VOID VOID:BOXED VOID:INT diff --git a/clutter/clutter-script.c b/clutter/clutter-script.c index d4b23754e..faeeede35 100644 --- a/clutter/clutter-script.c +++ b/clutter/clutter-script.c @@ -184,6 +184,7 @@ #include "clutter-script-private.h" #include "clutter-scriptable.h" +#include "clutter-enum-types.h" #include "clutter-private.h" #include "clutter-debug.h" @@ -517,63 +518,77 @@ construct_timeline (ClutterScript *script, return retval; } -/* ugh. if g_module_open() fails (*cough* python *cough*) we need a fallback - * for finding at least our own functions. keep the nick in sync with the - * ClutterAnimationMode enumeration +/* define the names of the animation modes to match the ones + * that developers might be more accustomed to */ static const struct { const gchar *name; - const gchar *short_name; - 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 + ClutterAnimationMode mode; +} animation_modes[] = { + { "linear", CLUTTER_LINEAR }, + { "easeInQuad", CLUTTER_EASE_IN_QUAD }, + { "easeOutQuad", CLUTTER_EASE_OUT_QUAD }, + { "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD }, + { "easeInCubic", CLUTTER_EASE_IN_CUBIC }, + { "easeOutCubic", CLUTTER_EASE_OUT_CUBIC }, + { "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC }, + { "easeInQuart", CLUTTER_EASE_IN_QUART }, + { "easeOutQuart", CLUTTER_EASE_OUT_QUART }, + { "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART }, + { "easeInQuint", CLUTTER_EASE_IN_QUINT }, + { "easeOutQuint", CLUTTER_EASE_OUT_QUINT }, + { "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT }, + { "easeInSine", CLUTTER_EASE_IN_SINE }, + { "easeOutSine", CLUTTER_EASE_OUT_SINE }, + { "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE }, + { "easeInExpo", CLUTTER_EASE_IN_EXPO }, + { "easeOutExpo", CLUTTER_EASE_OUT_EXPO }, + { "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO }, + { "easeInCirc", CLUTTER_EASE_IN_CIRC }, + { "easeOutCirc", CLUTTER_EASE_OUT_CIRC }, + { "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC }, + { "easeInElastic", CLUTTER_EASE_IN_ELASTIC }, + { "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC }, + { "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC }, + { "easeInBack", CLUTTER_EASE_IN_BACK }, + { "easeOutBack", CLUTTER_EASE_OUT_BACK }, + { "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK }, + { "easeInBounce", CLUTTER_EASE_IN_BOUNCE }, + { "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE }, + { "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE }, }; -static const gint n_clutter_alphas = G_N_ELEMENTS (clutter_alphas); +static const gint n_animation_modes = G_N_ELEMENTS (animation_modes); + +static ClutterAnimationMode +resolve_animation_mode (const gchar *name) +{ + gint i, res = 0; + + for (i = 0; i < n_animation_modes; i++) + { + if (strcmp (animation_modes[i].name, name) == 0) + return animation_modes[i].mode; + } + + if (clutter_script_enum_from_string (CLUTTER_TYPE_ANIMATION_MODE, + name, &res)) + return res; + + g_warning ("Unable to find the animation mode '%s'", name); + + return CLUTTER_CUSTOM_MODE; +} static ClutterAlphaFunc resolve_alpha_func (const gchar *name) { static GModule *module = NULL; ClutterAlphaFunc func; - gint i; CLUTTER_NOTE (SCRIPT, "Looking up `%s' alpha function", name); - for (i = 0; i < n_clutter_alphas; i++) - if (strcmp (name, clutter_alphas[i].name) == 0 || - strcmp (name, clutter_alphas[i].short_name) == 0) - { - CLUTTER_NOTE (SCRIPT, "Found `%s' alpha function in the whitelist", - name); - return clutter_alphas[i].symbol; - } - if (G_UNLIKELY (!module)) module = g_module_open (NULL, G_MODULE_BIND_LAZY); @@ -595,6 +610,7 @@ clutter_script_parse_alpha (ClutterScript *script, JsonObject *object; ClutterTimeline *timeline = NULL; ClutterAlphaFunc alpha_func = NULL; + ClutterAnimationMode mode = CLUTTER_CUSTOM_MODE; JsonNode *val; gboolean unref_timeline = FALSE; @@ -621,25 +637,39 @@ clutter_script_parse_alpha (ClutterScript *script, } } - val = json_object_get_member (object, "function"); + val = json_object_get_member (object, "mode"); if (val && json_node_get_string (val) != NULL) + mode = resolve_animation_mode (json_node_get_string (val)); + + if (mode == CLUTTER_CUSTOM_MODE) { - alpha_func = resolve_alpha_func (json_node_get_string (val)); - if (!alpha_func) + val = json_object_get_member (object, "function"); + if (val && json_node_get_string (val) != NULL) { - g_warning ("Unable to find the function `%s' in the " - "Clutter alpha functions or the symbols table", - json_node_get_string (val)); + alpha_func = resolve_alpha_func (json_node_get_string (val)); + if (!alpha_func) + { + g_warning ("Unable to find the function `%s' in the " + "Clutter alpha functions or the symbols table", + json_node_get_string (val)); + } } } - CLUTTER_NOTE (SCRIPT, "Parsed alpha: %s timeline (%p) and func:%p", + CLUTTER_NOTE (SCRIPT, "Parsed alpha: %s timeline (%p) (mode:%d, func:%p)", unref_timeline ? "implicit" : "explicit", timeline ? timeline : 0x0, + mode != CLUTTER_CUSTOM_MODE ? mode : 0, alpha_func ? alpha_func : 0x0); retval = g_object_new (CLUTTER_TYPE_ALPHA, NULL); - clutter_alpha_set_func (CLUTTER_ALPHA (retval), alpha_func, NULL, NULL); + + if (mode != CLUTTER_CUSTOM_MODE) + clutter_alpha_set_mode (CLUTTER_ALPHA (retval), mode); + + if (alpha_func != NULL) + clutter_alpha_set_func (CLUTTER_ALPHA (retval), alpha_func, NULL, NULL); + clutter_alpha_set_timeline (CLUTTER_ALPHA (retval), timeline); if (unref_timeline) g_object_unref (timeline); diff --git a/clutter/clutter-types.h b/clutter/clutter-types.h index 2e1856905..968a7a589 100644 --- a/clutter/clutter-types.h +++ b/clutter/clutter-types.h @@ -189,39 +189,127 @@ typedef enum { /** * ClutterAnimationMode: * @CLUTTER_CUSTOM_MODE: custom progress function - * @CLUTTER_LINEAR: linear progress - * @CLUTTER_SINE_IN: sine-in progress - * @CLUTTER_SINE_OUT: sine-out progress - * @CLUTTER_SINE_IN_OUT: sine-in-out progress - * @CLUTTER_EASE_IN: ease-in progress - * @CLUTTER_EASE_OUT: ease-out progress - * @CLUTTER_EASE_IN_OUT: ease-in-out progress - * @CLUTTER_EXPO_IN: exponential in progress - * @CLUTTER_EXPO_OUT: exponential out progress - * @CLUTTER_EXPO_IN_OUT: exponential in-out progress - * @CLUTTER_SMOOTH_IN_OUT: smoothstep in-out progress - * @CLUTTER_ANIMATION_LAST: last animation mode + * @CLUTTER_LINEAR: linear tweening + * @CLUTTER_EASE_IN_QUAD: quadratic tweening + * @CLUTTER_EASE_OUT_QUAD: quadratic tweening, inverse of + * %CLUTTER_EASE_IN_QUAD + * @CLUTTER_EASE_IN_OUT_QUAD: quadratic tweening, combininig + * %CLUTTER_EASE_IN_QUAD and %CLUTTER_EASE_OUT_QUAD + * @CLUTTER_EASE_IN_CUBIC: cubic tweening + * @CLUTTER_EASE_OUT_CUBIC: cubic tweening, invers of + * %CLUTTER_EASE_IN_CUBIC + * @CLUTTER_EASE_IN_OUT_CUBIC: cubic tweening, combining + * %CLUTTER_EASE_IN_CUBIC and %CLUTTER_EASE_OUT_CUBIC + * @CLUTTER_EASE_IN_QUART: quartic tweening + * @CLUTTER_EASE_OUT_QUART: quartic tweening, inverse of + * %CLUTTER_EASE_IN_QUART + * @CLUTTER_EASE_IN_OUT_QUART: quartic tweening, combining + * %CLUTTER_EASE_IN_QUART and %CLUTTER_EASE_OUT_QUART + * @CLUTTER_EASE_IN_QUINT: quintic tweening + * @CLUTTER_EASE_OUT_QUINT: quintic tweening, inverse of + * %CLUTTER_EASE_IN_QUINT + * @CLUTTER_EASE_IN_OUT_QUINT: fifth power tweening, combining + * %CLUTTER_EASE_IN_QUINT and %CLUTTER_EASE_OUT_QUINT + * @CLUTTER_EASE_IN_SINE: sinusoidal tweening + * @CLUTTER_EASE_OUT_SINE: sinusoidal tweening, inverse of + * %CLUTTER_EASE_IN_SINE + * @CLUTTER_EASE_IN_OUT_SINE: sine wave tweening, combining + * %CLUTTER_EASE_IN_SINE and %CLUTTER_EASE_OUT_SINE + * @CLUTTER_EASE_IN_EXPO: exponential tweening + * @CLUTTER_EASE_OUT_EXPO: exponential tweening, inverse of + * %CLUTTER_EASE_IN_EXPO + * @CLUTTER_EASE_IN_OUT_EXPO: exponential tweening, combining + * %CLUTTER_EASE_IN_EXPO and %CLUTTER_EASE_OUT_EXPO + * @CLUTTER_EASE_IN_CIRC: circular tweening + * @CLUTTER_EASE_OUT_CIRC: circular tweening, inverse of + * %CLUTTER_EASE_IN_CIRC + * @CLUTTER_EASE_IN_OUT_CIRC: circular tweening, combining + * %CLUTTER_EASE_IN_CIRC and %CLUTTER_EASE_OUT_CIRC + * @CLUTTER_EASE_IN_ELASTIC: elastic tweening, with offshoot on start + * @CLUTTER_EASE_OUT_ELASTIC: elastic tweening, with offshoot on end + * @CLUTTER_EASE_IN_OUT_ELASTIC: elastic tweening with offshoot on both ends + * @CLUTTER_EASE_IN_BACK: overshooting cubic tweening, with + * backtracking on start + * @CLUTTER_EASE_OUT_BACK: overshooting cubic tweening, with + * backtracking on end + * @CLUTTER_EASE_IN_OUT_BACK: overshooting cubic tweening, with + * backtracking on both ends + * @CLUTTER_EASE_IN_BOUNCE: exponentially decaying parabolic (bounce) + * tweening, with bounce on start + * @CLUTTER_EASE_OUT_BOUNCE: exponentially decaying parabolic (bounce) + * tweening, with bounce on end + * @CLUTTER_EASE_IN_OUT_BOUNCE: exponentially decaying parabolic (bounce) + * tweening, with bounce on both ends + * @CLUTTER_ANIMATION_LAST: last animation mode, used as a guard for + * registered global alpha functions * * The animation modes used by #ClutterAlpha and #ClutterAnimation. This - * enumeration can be expanded in later versions of Clutter. + * enumeration can be expanded in later versions of Clutter. See the + * #ClutterAlpha documentation for a graph of all the animation modes. + * + * Every global alpha function registered using clutter_alpha_register_func() + * or clutter_alpha_register_closure() will have a logical id greater than + * %CLUTTER_ANIMATION_LAST. * * Since: 1.0 */ typedef enum { CLUTTER_CUSTOM_MODE = 0, + /* linear */ CLUTTER_LINEAR, - CLUTTER_SINE_IN, - CLUTTER_SINE_OUT, - CLUTTER_SINE_IN_OUT, - CLUTTER_EASE_IN, - CLUTTER_EASE_OUT, - CLUTTER_EASE_IN_OUT, - CLUTTER_EXPO_IN, - CLUTTER_EXPO_OUT, - CLUTTER_EXPO_IN_OUT, - CLUTTER_SMOOTH_IN_OUT, + /* quadratic */ + CLUTTER_EASE_IN_QUAD, + CLUTTER_EASE_OUT_QUAD, + CLUTTER_EASE_IN_OUT_QUAD, + + /* cubic */ + CLUTTER_EASE_IN_CUBIC, + CLUTTER_EASE_OUT_CUBIC, + CLUTTER_EASE_IN_OUT_CUBIC, + + /* quartic */ + CLUTTER_EASE_IN_QUART, + CLUTTER_EASE_OUT_QUART, + CLUTTER_EASE_IN_OUT_QUART, + + /* quintic */ + CLUTTER_EASE_IN_QUINT, + CLUTTER_EASE_OUT_QUINT, + CLUTTER_EASE_IN_OUT_QUINT, + + /* sinusoidal */ + CLUTTER_EASE_IN_SINE, + CLUTTER_EASE_OUT_SINE, + CLUTTER_EASE_IN_OUT_SINE, + + /* exponential */ + CLUTTER_EASE_IN_EXPO, + CLUTTER_EASE_OUT_EXPO, + CLUTTER_EASE_IN_OUT_EXPO, + + /* circular */ + CLUTTER_EASE_IN_CIRC, + CLUTTER_EASE_OUT_CIRC, + CLUTTER_EASE_IN_OUT_CIRC, + + /* elastic */ + CLUTTER_EASE_IN_ELASTIC, + CLUTTER_EASE_OUT_ELASTIC, + CLUTTER_EASE_IN_OUT_ELASTIC, + + /* overshooting cubic */ + CLUTTER_EASE_IN_BACK, + CLUTTER_EASE_OUT_BACK, + CLUTTER_EASE_IN_OUT_BACK, + + /* exponentially decaying parabolic */ + CLUTTER_EASE_IN_BOUNCE, + CLUTTER_EASE_OUT_BOUNCE, + CLUTTER_EASE_IN_OUT_BOUNCE, + + /* guard, before registered alpha functions */ CLUTTER_ANIMATION_LAST } ClutterAnimationMode; diff --git a/doc/reference/clutter/Makefile.am b/doc/reference/clutter/Makefile.am index d03a283d0..e396ad68d 100644 --- a/doc/reference/clutter/Makefile.am +++ b/doc/reference/clutter/Makefile.am @@ -91,7 +91,7 @@ EXTRA_HFILES=\ # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES=\ actor-box.png \ - alpha-func.png \ + easing-modes.png \ event-flow.png \ path-alpha-func.png @@ -132,6 +132,7 @@ include $(top_srcdir)/gtk-doc.make EXTRA_DIST += \ version.xml.in \ actor-box.png \ - alpha-func.png \ + easing-modes.png \ + easing-modes.svg \ event-flow.png \ path-alpha-func.png diff --git a/doc/reference/clutter/alpha-func.png b/doc/reference/clutter/alpha-func.png deleted file mode 100644 index 292d49325..000000000 Binary files a/doc/reference/clutter/alpha-func.png and /dev/null differ diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 748691144..5d76f2044 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -98,46 +98,24 @@ clutter_behaviour_get_type ClutterAlpha ClutterAlpha ClutterAlphaClass +ClutterAlphaFunc clutter_alpha_new clutter_alpha_new_full clutter_alpha_new_with_func -clutter_alpha_get_alpha -CLUTTER_ALPHA_MAX_ALPHA -ClutterAlphaFunc -clutter_alpha_set_func -clutter_alpha_set_closure clutter_alpha_set_timeline clutter_alpha_get_timeline clutter_alpha_set_mode clutter_alpha_get_mode +clutter_alpha_get_alpha + + +clutter_alpha_set_func +clutter_alpha_set_closure clutter_alpha_register_closure clutter_alpha_register_func - -clutter_ramp_inc_func -clutter_ramp_dec_func -clutter_ramp_func -clutter_sine_func -clutter_sine_inc_func -clutter_sine_dec_func -clutter_sine_half_func -clutter_sine_in_func -clutter_sine_out_func -clutter_sine_in_out_func -clutter_square_func -clutter_smoothstep_inc_func -clutter_smoothstep_dec_func -clutter_exp_inc_func -clutter_exp_dec_func -clutter_exp_in_func -clutter_exp_out_func -clutter_exp_in_out_func -clutter_ease_in_func -clutter_ease_out_func -clutter_ease_in_out_func - CLUTTER_ALPHA CLUTTER_IS_ALPHA diff --git a/doc/reference/clutter/easing-modes.png b/doc/reference/clutter/easing-modes.png new file mode 100644 index 000000000..c1cbe1460 Binary files /dev/null and b/doc/reference/clutter/easing-modes.png differ diff --git a/doc/reference/clutter/easing-modes.svg b/doc/reference/clutter/easing-modes.svg new file mode 100644 index 000000000..34e0b34a3 --- /dev/null +++ b/doc/reference/clutter/easing-modes.svg @@ -0,0 +1,920 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/interactive/test-actors.c b/tests/interactive/test-actors.c index ded1e1a24..819adfaae 100644 --- a/tests/interactive/test-actors.c +++ b/tests/interactive/test-actors.c @@ -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, diff --git a/tests/interactive/test-animation.c b/tests/interactive/test-animation.c index ee0ff7337..54cf0fe89 100644 --- a/tests/interactive/test-animation.c +++ b/tests/interactive/test-animation.c @@ -64,7 +64,7 @@ on_button_press (ClutterActor *actor, vertex.y = CLUTTER_UNITS_FROM_FLOAT ((float) new_height / 2); animation = - clutter_actor_animate (actor, CLUTTER_EASE_IN, 2000, + clutter_actor_animate (actor, CLUTTER_EASE_IN_EXPO, 2000, "x", new_x, "y", new_y, "width", new_width, diff --git a/tests/interactive/test-easing.c b/tests/interactive/test-easing.c index 22048ad4e..d625d6cac 100644 --- a/tests/interactive/test-easing.c +++ b/tests/interactive/test-easing.c @@ -7,16 +7,36 @@ const struct { ClutterAnimationMode mode; } easing_modes[] = { { "linear", CLUTTER_LINEAR }, - { "sine-in", CLUTTER_SINE_IN }, - { "sine-out", CLUTTER_SINE_OUT }, - { "sine-in-out", CLUTTER_SINE_IN_OUT }, - { "ease-in", CLUTTER_EASE_IN }, - { "ease-out", CLUTTER_EASE_OUT }, - { "ease-in-out", CLUTTER_EASE_IN_OUT }, - { "expo-in", CLUTTER_EXPO_IN }, - { "expo-out", CLUTTER_EXPO_OUT }, - { "expo-in-out", CLUTTER_EXPO_IN_OUT }, - { "smooth-in-out", CLUTTER_SMOOTH_IN_OUT } + { "easeInQuad", CLUTTER_EASE_IN_QUAD }, + { "easeOutQuad", CLUTTER_EASE_OUT_QUAD }, + { "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD }, + { "easeInCubic", CLUTTER_EASE_IN_CUBIC }, + { "easeOutCubic", CLUTTER_EASE_OUT_CUBIC }, + { "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC }, + { "easeInQuart", CLUTTER_EASE_IN_QUART }, + { "easeOutQuart", CLUTTER_EASE_OUT_QUART }, + { "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART }, + { "easeInQuint", CLUTTER_EASE_IN_QUINT }, + { "easeOutQuint", CLUTTER_EASE_OUT_QUINT }, + { "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT }, + { "easeInSine", CLUTTER_EASE_IN_SINE }, + { "easeOutSine", CLUTTER_EASE_OUT_SINE }, + { "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE }, + { "easeInExpo", CLUTTER_EASE_IN_EXPO }, + { "easeOutExpo", CLUTTER_EASE_OUT_EXPO }, + { "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO }, + { "easeInCirc", CLUTTER_EASE_IN_CIRC }, + { "easeOutCirc", CLUTTER_EASE_OUT_CIRC }, + { "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC }, + { "easeInElastic", CLUTTER_EASE_IN_ELASTIC }, + { "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC }, + { "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC }, + { "easeInBack", CLUTTER_EASE_IN_BACK }, + { "easeOutBack", CLUTTER_EASE_OUT_BACK }, + { "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK }, + { "easeInBounce", CLUTTER_EASE_IN_BOUNCE }, + { "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE }, + { "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE }, }; static const gint n_easing_modes = G_N_ELEMENTS (easing_modes); @@ -30,36 +50,48 @@ on_button_press (ClutterActor *actor, ClutterButtonEvent *event, ClutterActor *rectangle) { - ClutterAnimation *animation; - ClutterAnimationMode cur_mode; - gchar *text; - guint stage_width, stage_height; - guint label_width, label_height; + if (event->button == 3) + { + gchar *text; + guint stage_width, stage_height; + guint label_width, label_height; - text = g_strdup_printf ("Easing mode: %s (%d of %d)\n", - easing_modes[current_mode].name, - current_mode + 1, - n_easing_modes); + current_mode = (current_mode + 1 < n_easing_modes) ? current_mode + 1 + : 0; - clutter_text_set_text (CLUTTER_TEXT (easing_mode_label), text); - g_free (text); + text = g_strdup_printf ("Easing mode: %s (%d of %d)\n" + "Right click to change the easing mode", + easing_modes[current_mode].name, + current_mode + 1, + n_easing_modes); - clutter_actor_get_size (main_stage, &stage_width, &stage_height); - clutter_actor_get_size (easing_mode_label, &label_width, &label_height); + clutter_text_set_text (CLUTTER_TEXT (easing_mode_label), text); + g_free (text); - clutter_actor_set_position (easing_mode_label, - stage_width - label_width - 10, - stage_height - label_height - 10); + clutter_actor_get_size (main_stage, + &stage_width, + &stage_height); + clutter_actor_get_size (easing_mode_label, + &label_width, + &label_height); - cur_mode = easing_modes[current_mode].mode; + clutter_actor_set_position (easing_mode_label, + stage_width - label_width - 10, + stage_height - label_height - 10); + } + else if (event->button == 1) + { + ClutterAnimation *animation; + ClutterAnimationMode cur_mode; - animation = - clutter_actor_animate (rectangle, cur_mode, 2000, - "x", event->x, - "y", event->y, - NULL); + cur_mode = easing_modes[current_mode].mode; - current_mode = (current_mode + 1 < n_easing_modes) ? current_mode + 1 : 0; + animation = + clutter_actor_animate (rectangle, cur_mode, 2000, + "x", event->x, + "y", event->y, + NULL); + } return TRUE; } @@ -92,7 +124,8 @@ test_easing_main (int argc, char *argv[]) "button-press-event", G_CALLBACK (on_button_press), rect); - text = g_strdup_printf ("Easing mode: %s (%d of %d)\n", + text = g_strdup_printf ("Easing mode: %s (%d of %d)\n" + "Right click to change the easing mode", easing_modes[current_mode].name, current_mode + 1, n_easing_modes); diff --git a/tests/interactive/test-layout.c b/tests/interactive/test-layout.c index f446779cc..4b70260a8 100644 --- a/tests/interactive/test-layout.c +++ b/tests/interactive/test-layout.c @@ -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); diff --git a/tests/interactive/test-paint-wrapper.c b/tests/interactive/test-paint-wrapper.c index 5bc60f018..79f4b4c01 100644 --- a/tests/interactive/test-paint-wrapper.c +++ b/tests/interactive/test-paint-wrapper.c @@ -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, diff --git a/tests/interactive/test-scale.c b/tests/interactive/test-scale.c index 0a466cb5d..7a2d86fdf 100644 --- a/tests/interactive/test-scale.c +++ b/tests/interactive/test-scale.c @@ -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, diff --git a/tests/interactive/test-script.c b/tests/interactive/test-script.c index 5e6464d4d..664e87361 100644 --- a/tests/interactive/test-script.c +++ b/tests/interactive/test-script.c @@ -43,7 +43,7 @@ static const gchar *test_behaviour = " \"path\" : \"M 50 50 L 100 100\"," " \"alpha\" : {" " \"timeline\" : \"main-timeline\"," -" \"function\" : \"ramp\"" +" \"mode\" : \"linear\"" " }" " }," " {" @@ -54,7 +54,7 @@ static const gchar *test_behaviour = " \"axis\" : \"y-axis\"," " \"alpha\" : {" " \"timeline\" : \"main-timeline\"," -" \"function\" : \"sine\"" +" \"mode\" : \"ease-in-sine\"" " }" " }," " {" @@ -64,7 +64,7 @@ static const gchar *test_behaviour = " \"opacity-end\" : 0," " \"alpha\" : {" " \"timeline\" : \"main-timeline\"," -" \"function\" : \"ramp-inc\"" +" \"mode\" : \"easeOutCubic\"" " }" " }" "]";