From f98bb306337f8577f820b1c1e1e28f0e5bf4755d Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 10 Oct 2011 11:25:40 +0100 Subject: [PATCH] animation: Deprecate Alpha usage We can use ClutterTimeline and its progress mode inside ClutterAnimation; obviously, we have to maintain the invariants because of the ClutterAnimation:alpha property, but if all you set is the :mode property using one of the Clutter animation modes then we can skip the ClutterAlpha entirely. --- clutter/clutter-animation.c | 322 +++++++++++++++++++++--------------- clutter/clutter-animation.h | 30 ++-- 2 files changed, 208 insertions(+), 144 deletions(-) diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index e02dbb1e0..aaef03c2f 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -193,6 +193,7 @@ struct _ClutterAnimationPrivate GHashTable *properties; ClutterAlpha *alpha; + ClutterTimeline *timeline; guint timeline_started_id; guint timeline_completed_id; @@ -205,10 +206,35 @@ static GQuark quark_object_animation = 0; static void clutter_scriptable_init (ClutterScriptableIface *iface); +static void clutter_animation_set_alpha_internal (ClutterAnimation *animation, + ClutterAlpha *alpha); +static ClutterAlpha * clutter_animation_get_alpha_internal (ClutterAnimation *animation); +static ClutterTimeline * clutter_animation_get_timeline_internal (ClutterAnimation *animation); + G_DEFINE_TYPE_WITH_CODE (ClutterAnimation, clutter_animation, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, clutter_scriptable_init)); +static ClutterAlpha * +clutter_animation_get_alpha_internal (ClutterAnimation *animation) +{ + ClutterAnimationPrivate *priv = animation->priv; + + if (priv->alpha == NULL) + { + ClutterAlpha *alpha; + + alpha = clutter_alpha_new (); + clutter_alpha_set_mode (alpha, CLUTTER_LINEAR); + + priv->alpha = g_object_ref_sink (alpha); + + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_ALPHA]); + } + + return priv->alpha; +} + static void on_actor_destroy (ClutterActor *actor, ClutterAnimation *animation) @@ -310,7 +336,7 @@ clutter_animation_dispose (GObject *gobject) if (priv->alpha != NULL) timeline = clutter_alpha_get_timeline (priv->alpha); else - timeline = NULL; + timeline = priv->timeline; if (timeline != NULL && priv->timeline_started_id != 0) g_signal_handler_disconnect (timeline, priv->timeline_started_id); @@ -371,7 +397,7 @@ clutter_animation_set_property (GObject *gobject, break; case PROP_ALPHA: - clutter_animation_set_alpha (animation, g_value_get_object (value)); + clutter_animation_set_alpha_internal (animation, g_value_get_object (value)); break; default: @@ -412,7 +438,7 @@ clutter_animation_get_property (GObject *gobject, break; case PROP_ALPHA: - g_value_set_object (value, clutter_animation_get_alpha (animation)); + g_value_set_object (value, clutter_animation_get_alpha_internal (animation)); break; default: @@ -546,13 +572,16 @@ clutter_animation_class_init (ClutterAnimationClass *klass) * The #ClutterAlpha used by the animation. * * Since: 1.0 + * + * Deprecated: 1.10: Use the #ClutterAnimation:timeline property and + * the #ClutterTimeline:progress-mode property instead. */ obj_props[PROP_ALPHA] = g_param_spec_object ("alpha", P_("Alpha"), P_("The alpha used by the animation"), CLUTTER_TYPE_ALPHA, - CLUTTER_PARAM_READWRITE); + CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED); g_object_class_install_properties (gobject_class, PROP_LAST, @@ -1089,7 +1118,10 @@ on_timeline_frame (ClutterTimeline *timeline, priv = animation->priv; - alpha_value = clutter_alpha_get_alpha (priv->alpha); + if (priv->alpha != NULL) + alpha_value = clutter_alpha_get_alpha (priv->alpha); + else + alpha_value = clutter_timeline_get_progress (priv->timeline); if (CLUTTER_IS_ANIMATABLE (priv->object)) { @@ -1144,37 +1176,21 @@ on_timeline_frame (ClutterTimeline *timeline, g_object_unref (animation); } -static ClutterAlpha * -clutter_animation_get_alpha_internal (ClutterAnimation *animation) -{ - ClutterAnimationPrivate *priv = animation->priv; - - if (priv->alpha == NULL) - { - ClutterAlpha *alpha; - - alpha = clutter_alpha_new (); - clutter_alpha_set_mode (alpha, CLUTTER_LINEAR); - - priv->alpha = g_object_ref_sink (alpha); - - g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_ALPHA]); - } - - return priv->alpha; -} - static ClutterTimeline * clutter_animation_get_timeline_internal (ClutterAnimation *animation) { ClutterAnimationPrivate *priv = animation->priv; ClutterTimeline *timeline; - ClutterAlpha *alpha; - alpha = clutter_animation_get_alpha_internal (animation); - timeline = clutter_alpha_get_timeline (alpha); - if (timeline != NULL) - return timeline; + if (priv->timeline != NULL) + return priv->timeline; + + if (priv->alpha != NULL) + { + timeline = clutter_alpha_get_timeline (priv->alpha); + if (timeline != NULL) + return timeline; + } timeline = g_object_new (CLUTTER_TYPE_TIMELINE, NULL); @@ -1193,14 +1209,106 @@ clutter_animation_get_timeline_internal (ClutterAnimation *animation) G_CALLBACK (on_timeline_frame), animation); - clutter_alpha_set_timeline (alpha, timeline); + if (priv->alpha != NULL) + { + clutter_alpha_set_timeline (priv->alpha, timeline); - /* the alpha owns the timeline now */ - g_object_unref (timeline); + /* the alpha owns the timeline now */ + g_object_unref (timeline); + } + + priv->timeline = timeline; g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_TIMELINE]); - return timeline; + return priv->timeline; +} + +static void +clutter_animation_set_alpha_internal (ClutterAnimation *animation, + ClutterAlpha *alpha) +{ + ClutterAnimationPrivate *priv; + ClutterTimeline *timeline; + + priv = animation->priv; + + if (priv->alpha == alpha) + return; + + g_object_freeze_notify (G_OBJECT (animation)); + + if (priv->alpha != NULL) + timeline = clutter_alpha_get_timeline (priv->alpha); + else + timeline = NULL; + + /* disconnect the old timeline first */ + if (timeline != NULL && priv->timeline_started_id != 0) + { + g_signal_handler_disconnect (timeline, priv->timeline_started_id); + priv->timeline_started_id = 0; + } + + if (timeline != NULL && priv->timeline_completed_id != 0) + { + g_signal_handler_disconnect (timeline, priv->timeline_completed_id); + priv->timeline_completed_id = 0; + } + + /* then we need to disconnect the signal handler from the old alpha */ + if (timeline != NULL && priv->timeline_frame_id != 0) + { + g_signal_handler_disconnect (timeline, priv->timeline_frame_id); + priv->timeline_frame_id = 0; + } + + if (priv->alpha != NULL) + { + /* this will take care of any reference we hold on the timeline */ + g_object_unref (priv->alpha); + priv->alpha = NULL; + } + + if (alpha == NULL) + goto out; + + priv->alpha = g_object_ref_sink (alpha); + + /* if the alpha has a timeline then we use it, otherwise we create one */ + timeline = clutter_alpha_get_timeline (priv->alpha); + if (timeline != NULL) + { + priv->timeline_started_id = + g_signal_connect (timeline, "started", + G_CALLBACK (on_timeline_started), + animation); + priv->timeline_completed_id = + g_signal_connect (timeline, "completed", + G_CALLBACK (on_timeline_completed), + animation); + priv->timeline_frame_id = + g_signal_connect (timeline, "new-frame", + G_CALLBACK (on_timeline_frame), + animation); + } + else + { + /* FIXME - add a create_timeline_internal() because this does + * not look very good + */ + (void) clutter_animation_get_timeline_internal (animation); + } + +out: + /* emit all relevant notifications */ + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_MODE]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_DURATION]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_LOOP]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_ALPHA]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_TIMELINE]); + + g_object_thaw_notify (G_OBJECT (animation)); } /** @@ -1301,16 +1409,29 @@ void clutter_animation_set_mode (ClutterAnimation *animation, gulong mode) { - ClutterAlpha *alpha; - g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); g_object_freeze_notify (G_OBJECT (animation)); - alpha = clutter_animation_get_alpha_internal (animation); - g_assert (CLUTTER_IS_ALPHA (alpha)); + if (animation->priv->alpha != NULL || mode > CLUTTER_ANIMATION_LAST) + { + ClutterAlpha *alpha; - clutter_alpha_set_mode (alpha, mode); + if (animation->priv->alpha == NULL) + alpha = clutter_animation_get_alpha_internal (animation); + else + alpha = animation->priv->alpha; + + clutter_alpha_set_mode (alpha, mode); + } + else + { + ClutterTimeline *timeline; + + timeline = clutter_animation_get_timeline_internal (animation); + + clutter_timeline_set_progress_mode (timeline, mode); + } g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_MODE]); @@ -1331,13 +1452,16 @@ clutter_animation_set_mode (ClutterAnimation *animation, gulong clutter_animation_get_mode (ClutterAnimation *animation) { - ClutterAlpha *alpha; + ClutterTimeline *timeline; g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), CLUTTER_LINEAR); - alpha = clutter_animation_get_alpha_internal (animation); + if (animation->priv->alpha != NULL) + return clutter_alpha_get_mode (animation->priv->alpha); - return clutter_alpha_get_mode (alpha); + timeline = clutter_animation_get_timeline_internal (animation); + + return clutter_timeline_get_progress_mode (timeline); } /** @@ -1363,8 +1487,6 @@ clutter_animation_set_duration (ClutterAnimation *animation, g_object_freeze_notify (G_OBJECT (animation)); timeline = clutter_animation_get_timeline_internal (animation); - g_assert (CLUTTER_IS_TIMELINE (timeline)); - clutter_timeline_set_duration (timeline, msecs); clutter_timeline_rewind (timeline); @@ -1453,11 +1575,13 @@ clutter_animation_get_duration (ClutterAnimation *animation) /** * clutter_animation_set_timeline: * @animation: a #ClutterAnimation - * @timeline: a #ClutterTimeline, or %NULL to unset the + * @timeline: (allow-none): a #ClutterTimeline, or %NULL to unset the * current #ClutterTimeline * * Sets the #ClutterTimeline used by @animation. * + * This function will take a reference on the passed @timeline. + * * Since: 1.0 */ void @@ -1466,7 +1590,6 @@ clutter_animation_set_timeline (ClutterAnimation *animation, { ClutterAnimationPrivate *priv; ClutterTimeline *cur_timeline; - ClutterAlpha *alpha; g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); g_return_if_fail (timeline == NULL || CLUTTER_IS_TIMELINE (timeline)); @@ -1496,14 +1619,19 @@ clutter_animation_set_timeline (ClutterAnimation *animation, priv->timeline_completed_id = 0; priv->timeline_frame_id = 0; - alpha = clutter_animation_get_alpha_internal (animation); - clutter_alpha_set_timeline (alpha, timeline); + if (priv->alpha != NULL) + clutter_alpha_set_timeline (priv->alpha, timeline); + else + priv->timeline = timeline; + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_TIMELINE]); g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_DURATION]); g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_LOOP]); - if (timeline) + if (timeline != NULL) { + g_object_ref (timeline); + priv->timeline_started_id = g_signal_connect (timeline, "started", G_CALLBACK (on_timeline_started), @@ -1550,95 +1678,18 @@ clutter_animation_get_timeline (ClutterAnimation *animation) * of the #ClutterAlpha instance. * * Since: 1.0 + * + * Deprecated: 1.10: Use clutter_animation_get_timeline() and + * clutter_timeline_set_progress_mode() instead. */ void clutter_animation_set_alpha (ClutterAnimation *animation, ClutterAlpha *alpha) { - ClutterAnimationPrivate *priv; - ClutterTimeline *timeline; - g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); g_return_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha)); - priv = animation->priv; - - if (priv->alpha == alpha) - return; - - g_object_freeze_notify (G_OBJECT (animation)); - - if (priv->alpha != NULL) - timeline = clutter_alpha_get_timeline (priv->alpha); - else - timeline = NULL; - - /* disconnect the old timeline first */ - if (timeline != NULL && priv->timeline_started_id != 0) - { - g_signal_handler_disconnect (timeline, priv->timeline_started_id); - priv->timeline_started_id = 0; - } - - if (timeline != NULL && priv->timeline_completed_id != 0) - { - g_signal_handler_disconnect (timeline, priv->timeline_completed_id); - priv->timeline_completed_id = 0; - } - - /* then we need to disconnect the signal handler from the old alpha */ - if (timeline != NULL && priv->timeline_frame_id != 0) - { - g_signal_handler_disconnect (timeline, priv->timeline_frame_id); - priv->timeline_frame_id = 0; - } - - if (priv->alpha != NULL) - { - /* this will take care of any reference we hold on the timeline */ - g_object_unref (priv->alpha); - priv->alpha = NULL; - } - - if (alpha == NULL) - goto out; - - priv->alpha = g_object_ref_sink (alpha); - - /* if the alpha has a timeline then we use it, otherwise we create one */ - timeline = clutter_alpha_get_timeline (priv->alpha); - if (timeline != NULL) - { - priv->timeline_started_id = - g_signal_connect (timeline, "started", - G_CALLBACK (on_timeline_started), - animation); - priv->timeline_completed_id = - g_signal_connect (timeline, "completed", - G_CALLBACK (on_timeline_completed), - animation); - priv->timeline_frame_id = - g_signal_connect (timeline, "new-frame", - G_CALLBACK (on_timeline_frame), - animation); - } - else - { - /* FIXME - add a create_timeline_internal() because this does - * not look very good - */ - (void) clutter_animation_get_timeline_internal (animation); - } - -out: - /* emit all relevant notifications */ - g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_MODE]); - g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_DURATION]); - g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_LOOP]); - g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_ALPHA]); - g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_TIMELINE]); - - g_object_thaw_notify (G_OBJECT (animation)); + clutter_animation_set_alpha_internal (animation, alpha); } /** @@ -1650,6 +1701,9 @@ out: * Return value: (transfer none): the alpha object used by the animation * * Since: 1.0 + * + * Deprecated: 1.10: Use clutter_animation_get_timeline() and + * clutter_timeline_get_progress_mode() instead. */ ClutterAlpha * clutter_animation_get_alpha (ClutterAnimation *animation) @@ -2035,6 +2089,8 @@ animation_create_for_actor (ClutterActor *actor) * #ClutterActor and should not be unreferenced with g_object_unref() * * Since: 1.0 + * + * Deprecated: 1.10: Use clutter_actor_animate_with_timeline() instead */ ClutterAnimation * clutter_actor_animate_with_alpha (ClutterActor *actor, @@ -2059,7 +2115,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor, } animation = animation_create_for_actor (actor); - clutter_animation_set_alpha (animation, alpha); + clutter_animation_set_alpha_internal (animation, alpha); va_start (args, first_property_name); clutter_animation_setup_valist (animation, first_property_name, args); @@ -2444,6 +2500,8 @@ clutter_actor_animate_with_timelinev (ClutterActor *actor, * #ClutterActor and should not be unreferenced with g_object_unref() * * Since: 1.0 + * + * Deprecated: 1.10: Use clutter_actor_animate_with_timelinev() instead */ ClutterAnimation * clutter_actor_animate_with_alphav (ClutterActor *actor, @@ -2469,7 +2527,7 @@ clutter_actor_animate_with_alphav (ClutterActor *actor, } animation = animation_create_for_actor (actor); - clutter_animation_set_alpha (animation, alpha); + clutter_animation_set_alpha_internal (animation, alpha); clutter_animation_setupv (animation, n_properties, properties, values); clutter_animation_start (animation); diff --git a/clutter/clutter-animation.h b/clutter/clutter-animation.h index f572e4da4..ddc61d8d9 100644 --- a/clutter/clutter-animation.h +++ b/clutter/clutter-animation.h @@ -114,9 +114,6 @@ gboolean clutter_animation_get_loop (ClutterAnimation *an void clutter_animation_set_timeline (ClutterAnimation *animation, ClutterTimeline *timeline); ClutterTimeline * clutter_animation_get_timeline (ClutterAnimation *animation); -void clutter_animation_set_alpha (ClutterAnimation *animation, - ClutterAlpha *alpha); -ClutterAlpha * clutter_animation_get_alpha (ClutterAnimation *animation); ClutterAnimation * clutter_animation_bind (ClutterAnimation *animation, const gchar *property_name, @@ -138,6 +135,13 @@ ClutterInterval *clutter_animation_get_interval (ClutterAnimation *an const gchar *property_name); void clutter_animation_completed (ClutterAnimation *animation); +CLUTTER_DEPRECATED_FOR(clutter_timeline_set_progress_mode and clutter_animation_set_timeline) +void clutter_animation_set_alpha (ClutterAnimation *animation, + ClutterAlpha *alpha); + +CLUTTER_DEPRECATED_FOR(clutter_animation_get_timeline and clutter_timeline_get_progress_mode) +ClutterAlpha * clutter_animation_get_alpha (ClutterAnimation *animation); + ClutterAnimation * clutter_actor_animate (ClutterActor *actor, gulong mode, guint duration, @@ -148,11 +152,6 @@ ClutterAnimation * clutter_actor_animate_with_timeline (ClutterActor * ClutterTimeline *timeline, const gchar *first_property_name, ...) G_GNUC_NULL_TERMINATED; -ClutterAnimation * clutter_actor_animate_with_alpha (ClutterActor *actor, - ClutterAlpha *alpha, - const gchar *first_property_name, - ...) G_GNUC_NULL_TERMINATED; - ClutterAnimation * clutter_actor_animatev (ClutterActor *actor, gulong mode, guint duration, @@ -165,15 +164,22 @@ ClutterAnimation * clutter_actor_animate_with_timelinev (ClutterActor gint n_properties, const gchar * const properties[], const GValue *values); + +ClutterAnimation * clutter_actor_get_animation (ClutterActor *actor); +void clutter_actor_detach_animation (ClutterActor *actor); + +CLUTTER_DEPRECATED_FOR(clutter_actor_animate_with_timeline) +ClutterAnimation * clutter_actor_animate_with_alpha (ClutterActor *actor, + ClutterAlpha *alpha, + const gchar *first_property_name, + ...) G_GNUC_NULL_TERMINATED; + +CLUTTER_DEPRECATED_FOR(clutter_actor_animate_with_timelinev) ClutterAnimation * clutter_actor_animate_with_alphav (ClutterActor *actor, ClutterAlpha *alpha, gint n_properties, const gchar * const properties[], const GValue *values); - -ClutterAnimation * clutter_actor_get_animation (ClutterActor *actor); -void clutter_actor_detach_animation (ClutterActor *actor); - G_END_DECLS #endif /* __CLUTTER_ANIMATION_H__ */