From 71a4db613569cd08572db517a045224161ba67d7 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 10 Sep 2010 11:18:53 +0100 Subject: [PATCH] animation: Allow detaching an animation from an actor When animating an actor through clutter_actor_animate() and friends we might want forcibly detach the animation instance from the actor in order to start a new one - for instance, in response to user interaction. Currently, there is no way to do that except in a very convoluted way, by emitting the ::completed signal and adding a special case in the signal handlers; this is due to the fact that clutter_actor_animate() adds more logic than the one added by clutter_animation_set_object(), so calling set_object(NULL) or unreferencing the animation instance itself won't be enough. The right way to approach this is to add a new method to Clutter.Actor that detaches any eventual Animation currently referencing it. http://bugzilla.clutter-project.org/show_bug.cgi?id=2051 --- clutter/clutter-animation.c | 53 ++++++++++++++++++++++ clutter/clutter-animation.h | 1 + doc/reference/clutter/clutter-sections.txt | 1 + 3 files changed, 55 insertions(+) diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index 0767d5176..f6c9ec33d 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -2461,3 +2461,56 @@ clutter_actor_get_animation (ClutterActor *actor) return g_object_get_qdata (G_OBJECT (actor), quark_object_animation); } + +/** + * clutter_actor_detach_animation: + * @actor: a #ClutterActor + * + * Detaches the #ClutterAnimation used by @actor, if clutter_actor_animate() + * has been called on @actor. + * + * Once the animation has been detached, it loses a reference. If it was + * the only reference then the #ClutterAnimation becomes invalid. + * + * The #ClutterAnimation::completed signal will not be emitted. + * + * Since: 1.4 + */ +void +clutter_actor_detach_animation (ClutterActor *actor) +{ + ClutterAnimation *animation; + ClutterAnimationPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation); + if (animation == NULL) + return; + + priv = animation->priv; + + g_assert (priv->object == G_OBJECT (actor)); + + /* we can't call get_timeline_internal() here because it would be + * pointless to create a timeline on an animation we want to detach + */ + if (priv->alpha != NULL) + { + ClutterTimeline *timeline; + + timeline = clutter_alpha_get_timeline (priv->alpha); + if (timeline != NULL) + clutter_timeline_stop (timeline); + } + + /* set_object(NULL) does no call weak_unref() because the weak reference + * is added by animation_create_for_actor() + */ + g_object_weak_unref (priv->object, on_actor_dispose, animation); + + clutter_animation_set_object (animation, NULL); + + /* drop the reference on the animation */ + g_object_unref (animation); +} diff --git a/clutter/clutter-animation.h b/clutter/clutter-animation.h index c2005ba7c..f572e4da4 100644 --- a/clutter/clutter-animation.h +++ b/clutter/clutter-animation.h @@ -172,6 +172,7 @@ ClutterAnimation * clutter_actor_animate_with_alphav (ClutterActor const GValue *values); ClutterAnimation * clutter_actor_get_animation (ClutterActor *actor); +void clutter_actor_detach_animation (ClutterActor *actor); G_END_DECLS diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 6121837e7..b3d911833 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1583,6 +1583,7 @@ clutter_actor_animatev clutter_actor_animate_with_timelinev clutter_actor_animate_with_alphav clutter_actor_get_animation +clutter_actor_detach_animation CLUTTER_TYPE_ANIMATION