mirror of
https://github.com/brl/mutter.git
synced 2025-03-25 20:53:54 +00:00
[animation] Simplify the Animation code
After long deliberation, the Animation class handling of the :mode, :duration and :loop properties, as well as the conditions for creating the Alpha and Timeline instances, came out as far too complicated for their own good. This is a rework of the API/parameters matrix and behaviour: - :mode accessors will create an Alpha, if needed - :duration and :loop accessors will create an Alpha and a Timeline if needed - :alpha will set or unset the Alpha - :timeline will set or unset the Timeline Plus, more documentation on the Animation class itself. Many thanks to Jonas Bonn <jonas@southpole.se> for the feedback and the ideas.
This commit is contained in:
parent
6fff1bcdc6
commit
ccd3b4c886
@ -25,14 +25,43 @@
|
|||||||
/**
|
/**
|
||||||
* SECTION:clutter-animation
|
* SECTION:clutter-animation
|
||||||
* @short_description: Simple implicit animations
|
* @short_description: Simple implicit animations
|
||||||
|
* @See_Also: #ClutterAnimatable, #ClutterInterval, #ClutterAlpha,
|
||||||
|
* #ClutterTimeline
|
||||||
*
|
*
|
||||||
* #ClutterAnimation is an object providing simple, implicit animations
|
* #ClutterAnimation is an object providing simple, implicit animations
|
||||||
* for #GObject<!-- -->s.
|
* for #GObject<!-- -->s.
|
||||||
*
|
*
|
||||||
* #ClutterAnimation instances will bind a #GObject property belonging
|
* #ClutterAnimation instances will bind one or more #GObject properties
|
||||||
* to a #GObject to a #ClutterInterval, and will then use a #ClutterTimeline
|
* belonging to a #GObject to a #ClutterInterval, and will then use a
|
||||||
* to interpolate the property between the initial and final values of the
|
* #ClutterAlpha to interpolate the property between the initial and final
|
||||||
* interval.
|
* values of the interval.
|
||||||
|
*
|
||||||
|
* The duration of the animation is set using clutter_animation_set_duration().
|
||||||
|
* The easing mode of the animation is set using clutter_animation_set_mode().
|
||||||
|
*
|
||||||
|
* If you want to control the animation you should retrieve the
|
||||||
|
* #ClutterTimeline using clutter_animation_get_timeline() and then
|
||||||
|
* use #ClutterTimeline functions like clutter_timeline_start(),
|
||||||
|
* clutter_timeline_pause() or clutter_timeline_stop().
|
||||||
|
*
|
||||||
|
* A #ClutterAnimation will emit the #ClutterAnimation::completed signal
|
||||||
|
* when the #ClutterTimeline used by the animation is completed; unlike
|
||||||
|
* #ClutterTimeline, though, the #ClutterAnimation::completed will not be
|
||||||
|
* emitted if #ClutterAnimation:loop is set to %TRUE - that is, a looping
|
||||||
|
* animation never completes.
|
||||||
|
*
|
||||||
|
* If your animation depends on user control you can force its completion
|
||||||
|
* using clutter_animation_completed().
|
||||||
|
*
|
||||||
|
* If the #GObject instance bound to a #ClutterAnimation implements the
|
||||||
|
* #ClutterAnimatable interface it is possible for that instance to
|
||||||
|
* control the way the initial and final states are interpolated.
|
||||||
|
*
|
||||||
|
* #ClutterAnimation<!-- -->s are distinguished from #ClutterBehaviour<!-- -->s
|
||||||
|
* because the former can only control #GObject properties of a single
|
||||||
|
* #GObject instance, while the latter can control multiple properties
|
||||||
|
* using accessor functions inside the #ClutterBehaviour::alpha_notify
|
||||||
|
* virtual function, and can control multiple #ClutterActor<!-- -->s as well.
|
||||||
*
|
*
|
||||||
* For convenience, it is possible to use the clutter_actor_animate()
|
* For convenience, it is possible to use the clutter_actor_animate()
|
||||||
* function call which will take care of setting up and tearing down
|
* function call which will take care of setting up and tearing down
|
||||||
@ -87,11 +116,6 @@ struct _ClutterAnimationPrivate
|
|||||||
|
|
||||||
ClutterAlpha *alpha;
|
ClutterAlpha *alpha;
|
||||||
|
|
||||||
gulong mode;
|
|
||||||
|
|
||||||
guint loop : 1;
|
|
||||||
guint duration;
|
|
||||||
|
|
||||||
guint timeline_started_id;
|
guint timeline_started_id;
|
||||||
guint timeline_completed_id;
|
guint timeline_completed_id;
|
||||||
guint alpha_notify_id;
|
guint alpha_notify_id;
|
||||||
@ -123,34 +147,31 @@ clutter_animation_dispose (GObject *gobject)
|
|||||||
ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
|
ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
|
||||||
ClutterTimeline *timeline;
|
ClutterTimeline *timeline;
|
||||||
|
|
||||||
timeline = clutter_animation_get_timeline (CLUTTER_ANIMATION (gobject));
|
if (priv->alpha != NULL)
|
||||||
if (timeline != NULL)
|
timeline = clutter_alpha_get_timeline (priv->alpha);
|
||||||
{
|
else
|
||||||
if (priv->timeline_started_id)
|
timeline = NULL;
|
||||||
{
|
|
||||||
g_signal_handler_disconnect (timeline, priv->timeline_started_id);
|
|
||||||
priv->timeline_started_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->timeline_completed_id)
|
if (timeline != NULL && priv->timeline_started_id != 0)
|
||||||
{
|
g_signal_handler_disconnect (timeline, priv->timeline_started_id);
|
||||||
g_signal_handler_disconnect (timeline, priv->timeline_completed_id);
|
|
||||||
priv->timeline_completed_id = 0;
|
if (timeline != NULL && priv->timeline_completed_id != 0)
|
||||||
}
|
g_signal_handler_disconnect (timeline, priv->timeline_completed_id);
|
||||||
}
|
|
||||||
|
priv->timeline_started_id = 0;
|
||||||
|
priv->timeline_completed_id = 0;
|
||||||
|
|
||||||
if (priv->alpha != NULL)
|
if (priv->alpha != NULL)
|
||||||
{
|
{
|
||||||
if (priv->alpha_notify_id)
|
if (priv->alpha_notify_id != 0)
|
||||||
{
|
g_signal_handler_disconnect (priv->alpha, priv->alpha_notify_id);
|
||||||
g_signal_handler_disconnect (priv->alpha, priv->alpha_notify_id);
|
|
||||||
priv->alpha_notify_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (priv->alpha);
|
g_object_unref (priv->alpha);
|
||||||
priv->alpha = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->alpha_notify_id = 0;
|
||||||
|
priv->alpha = NULL;
|
||||||
|
|
||||||
if (priv->object != NULL)
|
if (priv->object != NULL)
|
||||||
{
|
{
|
||||||
g_object_weak_unref (G_OBJECT (gobject),
|
g_object_weak_unref (G_OBJECT (gobject),
|
||||||
@ -158,9 +179,10 @@ clutter_animation_dispose (GObject *gobject)
|
|||||||
priv->object);
|
priv->object);
|
||||||
g_object_set_qdata (priv->object, quark_object_animation, NULL);
|
g_object_set_qdata (priv->object, quark_object_animation, NULL);
|
||||||
g_object_unref (priv->object);
|
g_object_unref (priv->object);
|
||||||
priv->object = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->object = NULL;
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_animation_parent_class)->dispose (gobject);
|
G_OBJECT_CLASS (clutter_animation_parent_class)->dispose (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +415,6 @@ clutter_animation_init (ClutterAnimation *self)
|
|||||||
{
|
{
|
||||||
self->priv = CLUTTER_ANIMATION_GET_PRIVATE (self);
|
self->priv = CLUTTER_ANIMATION_GET_PRIVATE (self);
|
||||||
|
|
||||||
self->priv->mode = CLUTTER_LINEAR;
|
|
||||||
self->priv->properties =
|
self->priv->properties =
|
||||||
g_hash_table_new_full (g_str_hash, g_str_equal,
|
g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
(GDestroyNotify) g_free,
|
(GDestroyNotify) g_free,
|
||||||
@ -826,7 +847,7 @@ clutter_animation_get_alpha_internal (ClutterAnimation *animation)
|
|||||||
ClutterAlpha *alpha;
|
ClutterAlpha *alpha;
|
||||||
|
|
||||||
alpha = clutter_alpha_new ();
|
alpha = clutter_alpha_new ();
|
||||||
clutter_alpha_set_mode (alpha, priv->mode);
|
clutter_alpha_set_mode (alpha, CLUTTER_LINEAR);
|
||||||
|
|
||||||
priv->alpha_notify_id =
|
priv->alpha_notify_id =
|
||||||
g_signal_connect (alpha, "notify::alpha",
|
g_signal_connect (alpha, "notify::alpha",
|
||||||
@ -834,6 +855,8 @@ clutter_animation_get_alpha_internal (ClutterAnimation *animation)
|
|||||||
animation);
|
animation);
|
||||||
|
|
||||||
priv->alpha = g_object_ref_sink (alpha);
|
priv->alpha = g_object_ref_sink (alpha);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (animation), "alpha");
|
||||||
}
|
}
|
||||||
|
|
||||||
return priv->alpha;
|
return priv->alpha;
|
||||||
@ -841,28 +864,17 @@ clutter_animation_get_alpha_internal (ClutterAnimation *animation)
|
|||||||
|
|
||||||
static ClutterTimeline *
|
static ClutterTimeline *
|
||||||
clutter_animation_get_timeline_internal (ClutterAnimation *animation)
|
clutter_animation_get_timeline_internal (ClutterAnimation *animation)
|
||||||
{
|
|
||||||
ClutterAlpha *alpha;
|
|
||||||
|
|
||||||
alpha = clutter_animation_get_alpha_internal (animation);
|
|
||||||
|
|
||||||
return clutter_alpha_get_timeline (alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
clutter_animation_create_timeline (ClutterAnimation *animation)
|
|
||||||
{
|
{
|
||||||
ClutterAnimationPrivate *priv = animation->priv;
|
ClutterAnimationPrivate *priv = animation->priv;
|
||||||
ClutterTimeline *timeline;
|
ClutterTimeline *timeline;
|
||||||
ClutterAlpha *alpha;
|
ClutterAlpha *alpha;
|
||||||
|
|
||||||
alpha = clutter_animation_get_alpha_internal (animation);
|
alpha = clutter_animation_get_alpha_internal (animation);
|
||||||
|
timeline = clutter_alpha_get_timeline (alpha);
|
||||||
|
if (timeline != NULL)
|
||||||
|
return timeline;
|
||||||
|
|
||||||
timeline = g_object_new (CLUTTER_TYPE_TIMELINE,
|
timeline = g_object_new (CLUTTER_TYPE_TIMELINE, NULL);
|
||||||
"duration", priv->duration,
|
|
||||||
"loop", priv->loop,
|
|
||||||
NULL);
|
|
||||||
clutter_alpha_set_timeline (alpha, timeline);
|
|
||||||
|
|
||||||
priv->timeline_started_id =
|
priv->timeline_started_id =
|
||||||
g_signal_connect (timeline, "started",
|
g_signal_connect (timeline, "started",
|
||||||
@ -874,10 +886,14 @@ clutter_animation_create_timeline (ClutterAnimation *animation)
|
|||||||
G_CALLBACK (on_timeline_completed),
|
G_CALLBACK (on_timeline_completed),
|
||||||
animation);
|
animation);
|
||||||
|
|
||||||
/* since we are creating it ourselves, we can offload
|
clutter_alpha_set_timeline (alpha, timeline);
|
||||||
* the ownership of the timeline to the alpha itself
|
|
||||||
*/
|
/* the alpha owns the timeline now */
|
||||||
g_object_unref (timeline);
|
g_object_unref (timeline);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (animation), "timeline");
|
||||||
|
|
||||||
|
return timeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -985,21 +1001,6 @@ clutter_animation_get_object (ClutterAnimation *animation)
|
|||||||
return animation->priv->object;
|
return animation->priv->object;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
clutter_animation_set_mode_internal (ClutterAnimation *animation,
|
|
||||||
gulong mode)
|
|
||||||
{
|
|
||||||
ClutterAnimationPrivate *priv = animation->priv;
|
|
||||||
ClutterAlpha *alpha;
|
|
||||||
|
|
||||||
priv->mode = mode;
|
|
||||||
|
|
||||||
alpha = clutter_animation_get_alpha_internal (animation);
|
|
||||||
clutter_alpha_set_mode (alpha, priv->mode);
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (animation), "mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_animation_set_mode:
|
* clutter_animation_set_mode:
|
||||||
* @animation: a #ClutterAnimation
|
* @animation: a #ClutterAnimation
|
||||||
@ -1009,15 +1010,30 @@ clutter_animation_set_mode_internal (ClutterAnimation *animation,
|
|||||||
* a logical id, either coming from the #ClutterAnimationMode enumeration
|
* a logical id, either coming from the #ClutterAnimationMode enumeration
|
||||||
* or the return value of clutter_alpha_register_func().
|
* or the return value of clutter_alpha_register_func().
|
||||||
*
|
*
|
||||||
|
* This function will also set #ClutterAnimation:alpha if needed.
|
||||||
|
*
|
||||||
* Since: 1.0
|
* Since: 1.0
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_animation_set_mode (ClutterAnimation *animation,
|
clutter_animation_set_mode (ClutterAnimation *animation,
|
||||||
gulong mode)
|
gulong mode)
|
||||||
{
|
{
|
||||||
|
ClutterTimeline *timeline;
|
||||||
|
ClutterAlpha *alpha;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||||
|
|
||||||
clutter_animation_set_mode_internal (animation, mode);
|
g_object_freeze_notify (G_OBJECT (animation));
|
||||||
|
|
||||||
|
alpha = clutter_animation_get_alpha_internal (animation);
|
||||||
|
clutter_alpha_set_mode (alpha, mode);
|
||||||
|
|
||||||
|
timeline = clutter_animation_get_timeline_internal (animation);
|
||||||
|
clutter_alpha_set_timeline (alpha, timeline);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (animation), "mode");
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (animation));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1034,16 +1050,13 @@ clutter_animation_set_mode (ClutterAnimation *animation,
|
|||||||
gulong
|
gulong
|
||||||
clutter_animation_get_mode (ClutterAnimation *animation)
|
clutter_animation_get_mode (ClutterAnimation *animation)
|
||||||
{
|
{
|
||||||
ClutterAnimationPrivate *priv;
|
ClutterAlpha *alpha;
|
||||||
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), CLUTTER_LINEAR);
|
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), CLUTTER_LINEAR);
|
||||||
|
|
||||||
priv = animation->priv;
|
alpha = clutter_animation_get_alpha_internal (animation);
|
||||||
|
|
||||||
if (priv->alpha != NULL)
|
return clutter_alpha_get_mode (alpha);
|
||||||
return clutter_alpha_get_mode (priv->alpha);
|
|
||||||
|
|
||||||
return priv->mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1053,39 +1066,22 @@ clutter_animation_get_mode (ClutterAnimation *animation)
|
|||||||
*
|
*
|
||||||
* Sets the duration of @animation in milliseconds.
|
* Sets the duration of @animation in milliseconds.
|
||||||
*
|
*
|
||||||
|
* This function will set #ClutterAnimation:alpha and
|
||||||
|
* #ClutterAnimation:timeline if needed.
|
||||||
|
*
|
||||||
* Since: 1.0
|
* Since: 1.0
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_animation_set_duration (ClutterAnimation *animation,
|
clutter_animation_set_duration (ClutterAnimation *animation,
|
||||||
gint msecs)
|
gint msecs)
|
||||||
{
|
{
|
||||||
ClutterAnimationPrivate *priv;
|
|
||||||
ClutterTimeline *timeline;
|
ClutterTimeline *timeline;
|
||||||
ClutterAlpha *alpha;
|
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||||
|
|
||||||
priv = animation->priv;
|
timeline = clutter_animation_get_timeline_internal (animation);
|
||||||
|
clutter_timeline_set_duration (timeline, msecs);
|
||||||
priv->duration = msecs;
|
clutter_timeline_rewind (timeline);
|
||||||
|
|
||||||
alpha = clutter_animation_get_alpha_internal (animation);
|
|
||||||
timeline = clutter_alpha_get_timeline (alpha);
|
|
||||||
if (timeline == NULL)
|
|
||||||
clutter_animation_create_timeline (animation);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gboolean was_playing;
|
|
||||||
|
|
||||||
was_playing = clutter_timeline_is_playing (timeline);
|
|
||||||
if (was_playing)
|
|
||||||
clutter_timeline_stop (timeline);
|
|
||||||
|
|
||||||
clutter_timeline_set_duration (timeline, priv->duration);
|
|
||||||
|
|
||||||
if (was_playing)
|
|
||||||
clutter_timeline_start (timeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (animation), "duration");
|
g_object_notify (G_OBJECT (animation), "duration");
|
||||||
}
|
}
|
||||||
@ -1100,30 +1096,21 @@ clutter_animation_set_duration (ClutterAnimation *animation,
|
|||||||
* A looping #ClutterAnimation will not emit the #ClutterAnimation::completed
|
* A looping #ClutterAnimation will not emit the #ClutterAnimation::completed
|
||||||
* signal when finished.
|
* signal when finished.
|
||||||
*
|
*
|
||||||
|
* This function will set #ClutterAnimation:alpha and
|
||||||
|
* #ClutterAnimation:timeline if needed.
|
||||||
|
*
|
||||||
* Since: 1.0
|
* Since: 1.0
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_animation_set_loop (ClutterAnimation *animation,
|
clutter_animation_set_loop (ClutterAnimation *animation,
|
||||||
gboolean loop)
|
gboolean loop)
|
||||||
{
|
{
|
||||||
ClutterAnimationPrivate *priv;
|
|
||||||
ClutterTimeline *timeline;
|
ClutterTimeline *timeline;
|
||||||
ClutterAlpha *alpha;
|
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||||
|
|
||||||
priv = animation->priv;
|
timeline = clutter_animation_get_timeline_internal (animation);
|
||||||
|
clutter_timeline_set_loop (timeline, loop);
|
||||||
alpha = clutter_animation_get_alpha_internal (animation);
|
|
||||||
timeline = clutter_alpha_get_timeline (alpha);
|
|
||||||
if (timeline == NULL)
|
|
||||||
{
|
|
||||||
priv->loop = loop;
|
|
||||||
|
|
||||||
clutter_animation_create_timeline (animation);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
clutter_timeline_set_loop (timeline, loop);
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (animation), "loop");
|
g_object_notify (G_OBJECT (animation), "loop");
|
||||||
}
|
}
|
||||||
@ -1141,22 +1128,13 @@ clutter_animation_set_loop (ClutterAnimation *animation,
|
|||||||
gboolean
|
gboolean
|
||||||
clutter_animation_get_loop (ClutterAnimation *animation)
|
clutter_animation_get_loop (ClutterAnimation *animation)
|
||||||
{
|
{
|
||||||
ClutterAnimationPrivate *priv;
|
ClutterTimeline *timeline;
|
||||||
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE);
|
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE);
|
||||||
|
|
||||||
priv = animation->priv;
|
timeline = clutter_animation_get_timeline_internal (animation);
|
||||||
|
|
||||||
if (priv->alpha != NULL)
|
return clutter_timeline_get_loop (timeline);
|
||||||
{
|
|
||||||
ClutterTimeline *timeline;
|
|
||||||
|
|
||||||
timeline = clutter_alpha_get_timeline (priv->alpha);
|
|
||||||
if (timeline != NULL)
|
|
||||||
return clutter_timeline_get_loop (timeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
return priv->loop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1172,39 +1150,23 @@ clutter_animation_get_loop (ClutterAnimation *animation)
|
|||||||
guint
|
guint
|
||||||
clutter_animation_get_duration (ClutterAnimation *animation)
|
clutter_animation_get_duration (ClutterAnimation *animation)
|
||||||
{
|
{
|
||||||
ClutterAnimationPrivate *priv;
|
ClutterTimeline *timeline;
|
||||||
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), 0);
|
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), 0);
|
||||||
|
|
||||||
priv = animation->priv;
|
timeline = clutter_animation_get_timeline_internal (animation);
|
||||||
|
|
||||||
if (priv->alpha != NULL)
|
return clutter_timeline_get_duration (timeline);
|
||||||
{
|
|
||||||
ClutterTimeline *timeline;
|
|
||||||
|
|
||||||
timeline = clutter_alpha_get_timeline (priv->alpha);
|
|
||||||
if (timeline != NULL)
|
|
||||||
return clutter_timeline_get_duration (timeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
return priv->duration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_animation_set_timeline:
|
* clutter_animation_set_timeline:
|
||||||
* @animation: a #ClutterAnimation
|
* @animation: a #ClutterAnimation
|
||||||
* @timeline: a #ClutterTimeline or %NULL
|
* @timeline: a #ClutterTimeline, or %NULL to unset the
|
||||||
|
* current #ClutterTimeline
|
||||||
*
|
*
|
||||||
* Sets the #ClutterTimeline used by @animation.
|
* Sets the #ClutterTimeline used by @animation.
|
||||||
*
|
*
|
||||||
* The #ClutterAnimation:duration and #ClutterAnimation:loop properties
|
|
||||||
* will be set using the corresponding #ClutterTimeline properties as a
|
|
||||||
* side effect.
|
|
||||||
*
|
|
||||||
* If @timeline is %NULL a new #ClutterTimeline will be constructed
|
|
||||||
* using the current values of the #ClutterAnimation:duration and
|
|
||||||
* #ClutterAnimation:loop properties.
|
|
||||||
*
|
|
||||||
* Since: 1.0
|
* Since: 1.0
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -1220,49 +1182,42 @@ clutter_animation_set_timeline (ClutterAnimation *animation,
|
|||||||
|
|
||||||
priv = animation->priv;
|
priv = animation->priv;
|
||||||
|
|
||||||
cur_timeline = clutter_animation_get_timeline_internal (animation);
|
if (priv->alpha != NULL)
|
||||||
|
cur_timeline = clutter_alpha_get_timeline (priv->alpha);
|
||||||
|
else
|
||||||
|
cur_timeline = NULL;
|
||||||
|
|
||||||
if (cur_timeline == timeline)
|
if (cur_timeline == timeline)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_object_freeze_notify (G_OBJECT (animation));
|
g_object_freeze_notify (G_OBJECT (animation));
|
||||||
|
|
||||||
if (priv->timeline_started_id != 0)
|
if (cur_timeline != NULL && priv->timeline_started_id != 0)
|
||||||
g_signal_handler_disconnect (cur_timeline, priv->timeline_started_id);
|
g_signal_handler_disconnect (cur_timeline, priv->timeline_started_id);
|
||||||
|
|
||||||
if (priv->timeline_completed_id != 0)
|
if (cur_timeline != NULL && priv->timeline_completed_id != 0)
|
||||||
g_signal_handler_disconnect (cur_timeline, priv->timeline_completed_id);
|
g_signal_handler_disconnect (cur_timeline, priv->timeline_completed_id);
|
||||||
|
|
||||||
priv->timeline_started_id = 0;
|
priv->timeline_started_id = 0;
|
||||||
priv->timeline_completed_id = 0;
|
priv->timeline_completed_id = 0;
|
||||||
|
|
||||||
if (timeline == NULL)
|
|
||||||
{
|
|
||||||
timeline = g_object_new (CLUTTER_TYPE_TIMELINE,
|
|
||||||
"duration", priv->duration,
|
|
||||||
"loop", priv->loop,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
priv->duration = clutter_timeline_get_duration (timeline);
|
|
||||||
g_object_notify (G_OBJECT (animation), "duration");
|
|
||||||
|
|
||||||
priv->loop = clutter_timeline_get_loop (timeline);
|
|
||||||
g_object_notify (G_OBJECT (animation), "loop");
|
|
||||||
}
|
|
||||||
|
|
||||||
alpha = clutter_animation_get_alpha_internal (animation);
|
alpha = clutter_animation_get_alpha_internal (animation);
|
||||||
clutter_alpha_set_timeline (alpha, timeline);
|
clutter_alpha_set_timeline (alpha, timeline);
|
||||||
g_object_notify (G_OBJECT (animation), "timeline");
|
g_object_notify (G_OBJECT (animation), "timeline");
|
||||||
|
g_object_notify (G_OBJECT (animation), "duration");
|
||||||
|
g_object_notify (G_OBJECT (animation), "loop");
|
||||||
|
|
||||||
priv->timeline_started_id =
|
if (timeline)
|
||||||
g_signal_connect (timeline, "started",
|
{
|
||||||
G_CALLBACK (on_timeline_started),
|
priv->timeline_started_id =
|
||||||
animation);
|
g_signal_connect (timeline, "started",
|
||||||
priv->timeline_completed_id =
|
G_CALLBACK (on_timeline_started),
|
||||||
g_signal_connect (timeline, "completed",
|
animation);
|
||||||
G_CALLBACK (on_timeline_completed),
|
priv->timeline_completed_id =
|
||||||
animation);
|
g_signal_connect (timeline, "completed",
|
||||||
|
G_CALLBACK (on_timeline_completed),
|
||||||
|
animation);
|
||||||
|
}
|
||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (animation));
|
g_object_thaw_notify (G_OBJECT (animation));
|
||||||
}
|
}
|
||||||
@ -1288,14 +1243,10 @@ clutter_animation_get_timeline (ClutterAnimation *animation)
|
|||||||
/**
|
/**
|
||||||
* clutter_animation_set_alpha:
|
* clutter_animation_set_alpha:
|
||||||
* @animation: a #ClutterAnimation
|
* @animation: a #ClutterAnimation
|
||||||
* @alpha: a #ClutterAlpha, or %NULL
|
* @alpha: a #ClutterAlpha, or %NULL to unset the current #ClutterAlpha
|
||||||
*
|
*
|
||||||
* Sets @alpha as the #ClutterAlpha used by @animation.
|
* Sets @alpha as the #ClutterAlpha used by @animation.
|
||||||
*
|
*
|
||||||
* If @alpha is %NULL, a new #ClutterAlpha will be constructed from
|
|
||||||
* the current value of the #ClutterAnimation:mode and the current
|
|
||||||
* #ClutterAnimation:timeline.
|
|
||||||
*
|
|
||||||
* If @alpha is not %NULL, the #ClutterAnimation will take ownership
|
* If @alpha is not %NULL, the #ClutterAnimation will take ownership
|
||||||
* of the #ClutterAlpha instance.
|
* of the #ClutterAlpha instance.
|
||||||
*
|
*
|
||||||
@ -1316,85 +1267,62 @@ clutter_animation_set_alpha (ClutterAnimation *animation,
|
|||||||
if (priv->alpha == alpha)
|
if (priv->alpha == alpha)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* retrieve the old timeline, if any */
|
|
||||||
if (priv->alpha != NULL)
|
if (priv->alpha != NULL)
|
||||||
{
|
timeline = clutter_alpha_get_timeline (priv->alpha);
|
||||||
timeline = clutter_alpha_get_timeline (priv->alpha);
|
|
||||||
if (timeline != NULL)
|
|
||||||
g_object_ref (timeline);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
timeline = NULL;
|
timeline = NULL;
|
||||||
|
|
||||||
if (alpha == NULL)
|
/* disconnect the old timeline first */
|
||||||
|
if (timeline != NULL && priv->timeline_started_id != 0)
|
||||||
{
|
{
|
||||||
/* this will create a new alpha */
|
g_signal_handler_disconnect (timeline, priv->timeline_started_id);
|
||||||
alpha = clutter_animation_get_alpha_internal (animation);
|
priv->timeline_started_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* if we had a timeline before, we should have the same timeline now */
|
if (timeline != NULL && priv->timeline_completed_id != 0)
|
||||||
if (timeline != NULL)
|
{
|
||||||
{
|
g_signal_handler_disconnect (timeline, priv->timeline_completed_id);
|
||||||
clutter_alpha_set_timeline (alpha, timeline);
|
priv->timeline_completed_id = 0;
|
||||||
g_object_unref (timeline);
|
}
|
||||||
}
|
|
||||||
else
|
/* then we need to disconnect the signal handler from the old alpha */
|
||||||
clutter_animation_create_timeline (animation);
|
if (priv->alpha_notify_id != 0)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (priv->alpha, priv->alpha_notify_id);
|
||||||
|
priv->alpha_notify_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)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->alpha = g_object_ref_sink (alpha);
|
||||||
|
priv->alpha_notify_id =
|
||||||
|
g_signal_connect (priv->alpha, "notify::value",
|
||||||
|
G_CALLBACK (on_alpha_notify),
|
||||||
|
animation);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
timeline = clutter_animation_get_timeline_internal (animation);
|
||||||
if (timeline != NULL)
|
|
||||||
{
|
|
||||||
/* if we had a timeline before then we need to disconnect
|
|
||||||
* the signal handlers from it
|
|
||||||
*/
|
|
||||||
if (priv->timeline_started_id != 0)
|
|
||||||
g_signal_handler_disconnect (timeline, priv->timeline_started_id);
|
|
||||||
|
|
||||||
if (priv->timeline_completed_id != 0)
|
|
||||||
g_signal_handler_disconnect (timeline, priv->timeline_completed_id);
|
|
||||||
|
|
||||||
/* we don't need this timeline anymore */
|
|
||||||
g_object_unref (timeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* then we need to disconnect the signal handler from the old alpha */
|
|
||||||
if (priv->alpha_notify_id != 0)
|
|
||||||
{
|
|
||||||
g_signal_handler_disconnect (priv->alpha, priv->alpha_notify_id);
|
|
||||||
priv->alpha_notify_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->alpha != NULL)
|
|
||||||
{
|
|
||||||
g_object_unref (priv->alpha);
|
|
||||||
priv->alpha = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->alpha = g_object_ref_sink (alpha);
|
|
||||||
priv->alpha_notify_id =
|
|
||||||
g_signal_connect (priv->alpha, "notify::value",
|
|
||||||
G_CALLBACK (on_alpha_notify),
|
|
||||||
animation);
|
|
||||||
|
|
||||||
/* if the alpha has a timeline then we use it */
|
|
||||||
timeline = clutter_alpha_get_timeline (priv->alpha);
|
|
||||||
if (timeline != NULL)
|
|
||||||
{
|
|
||||||
priv->duration = clutter_timeline_get_duration (timeline);
|
|
||||||
priv->loop = clutter_timeline_get_loop (timeline);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
clutter_animation_create_timeline (animation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* emit all relevant notifications */
|
/* emit all relevant notifications */
|
||||||
g_object_notify (G_OBJECT (animation), "mode");
|
g_object_notify (G_OBJECT (animation), "mode");
|
||||||
@ -1419,7 +1347,7 @@ clutter_animation_get_alpha (ClutterAnimation *animation)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
|
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
|
||||||
|
|
||||||
return animation->priv->alpha;
|
return clutter_animation_get_alpha_internal (animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1722,6 +1650,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
|
|||||||
if (animation == NULL)
|
if (animation == NULL)
|
||||||
{
|
{
|
||||||
animation = clutter_animation_new ();
|
animation = clutter_animation_new ();
|
||||||
|
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||||
|
|
||||||
g_signal_connect (animation, "completed",
|
g_signal_connect (animation, "completed",
|
||||||
G_CALLBACK (on_animation_completed),
|
G_CALLBACK (on_animation_completed),
|
||||||
@ -1733,7 +1662,6 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
|
|||||||
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
||||||
|
|
||||||
clutter_animation_set_alpha (animation, alpha);
|
clutter_animation_set_alpha (animation, alpha);
|
||||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
|
||||||
|
|
||||||
va_start (args, first_property_name);
|
va_start (args, first_property_name);
|
||||||
clutter_animation_setup_valist (animation, first_property_name, args);
|
clutter_animation_setup_valist (animation, first_property_name, args);
|
||||||
@ -1786,6 +1714,7 @@ clutter_actor_animate_with_timeline (ClutterActor *actor,
|
|||||||
if (animation == NULL)
|
if (animation == NULL)
|
||||||
{
|
{
|
||||||
animation = clutter_animation_new ();
|
animation = clutter_animation_new ();
|
||||||
|
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||||
|
|
||||||
g_signal_connect (animation, "completed",
|
g_signal_connect (animation, "completed",
|
||||||
G_CALLBACK (on_animation_completed),
|
G_CALLBACK (on_animation_completed),
|
||||||
@ -1796,9 +1725,8 @@ clutter_actor_animate_with_timeline (ClutterActor *actor,
|
|||||||
else
|
else
|
||||||
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
||||||
|
|
||||||
clutter_animation_set_timeline (animation, timeline);
|
|
||||||
clutter_animation_set_mode (animation, mode);
|
clutter_animation_set_mode (animation, mode);
|
||||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
clutter_animation_set_timeline (animation, timeline);
|
||||||
|
|
||||||
va_start (args, first_property_name);
|
va_start (args, first_property_name);
|
||||||
clutter_animation_setup_valist (animation, first_property_name, args);
|
clutter_animation_setup_valist (animation, first_property_name, args);
|
||||||
@ -2130,6 +2058,7 @@ clutter_actor_animate_with_timelinev (ClutterActor *actor,
|
|||||||
if (animation == NULL)
|
if (animation == NULL)
|
||||||
{
|
{
|
||||||
animation = clutter_animation_new ();
|
animation = clutter_animation_new ();
|
||||||
|
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||||
|
|
||||||
g_signal_connect (animation, "completed",
|
g_signal_connect (animation, "completed",
|
||||||
G_CALLBACK (on_animation_completed),
|
G_CALLBACK (on_animation_completed),
|
||||||
@ -2140,9 +2069,8 @@ clutter_actor_animate_with_timelinev (ClutterActor *actor,
|
|||||||
else
|
else
|
||||||
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
||||||
|
|
||||||
clutter_animation_set_timeline (animation, timeline);
|
|
||||||
clutter_animation_set_mode (animation, mode);
|
clutter_animation_set_mode (animation, mode);
|
||||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
clutter_animation_set_timeline (animation, timeline);
|
||||||
clutter_animation_setupv (animation, n_properties, properties, values);
|
clutter_animation_setupv (animation, n_properties, properties, values);
|
||||||
clutter_animation_start (animation);
|
clutter_animation_start (animation);
|
||||||
|
|
||||||
@ -2206,6 +2134,7 @@ clutter_actor_animate_with_alphav (ClutterActor *actor,
|
|||||||
if (animation == NULL)
|
if (animation == NULL)
|
||||||
{
|
{
|
||||||
animation = clutter_animation_new ();
|
animation = clutter_animation_new ();
|
||||||
|
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||||
|
|
||||||
g_signal_connect (animation, "completed",
|
g_signal_connect (animation, "completed",
|
||||||
G_CALLBACK (on_animation_completed),
|
G_CALLBACK (on_animation_completed),
|
||||||
@ -2217,7 +2146,6 @@ clutter_actor_animate_with_alphav (ClutterActor *actor,
|
|||||||
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
||||||
|
|
||||||
clutter_animation_set_alpha (animation, alpha);
|
clutter_animation_set_alpha (animation, alpha);
|
||||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
|
||||||
clutter_animation_setupv (animation, n_properties, properties, values);
|
clutter_animation_setupv (animation, n_properties, properties, values);
|
||||||
clutter_animation_start (animation);
|
clutter_animation_start (animation);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user