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
This commit is contained in:
Emmanuele Bassi 2010-09-10 11:18:53 +01:00
parent 3aa2d00c3b
commit 71a4db6135
3 changed files with 55 additions and 0 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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
<SUBSECTION Standard>
CLUTTER_TYPE_ANIMATION