1
0
Fork 0

[animation] Extend ClutterAnimation support to all objects

Instead of limiting the use of ClutterAnimation to ClutterActor
instances, relax the constraint to include all GObject classes.

ClutterAnimation is not using actor-specific API, since it is
only using properties.

The only actor-based API is the clutter_actor_animate() family
of functions.
This commit is contained in:
Emmanuele Bassi 2009-01-08 13:13:39 +00:00
parent 28b0f432b7
commit 068ba1caf0
2 changed files with 74 additions and 80 deletions

View file

@ -27,12 +27,12 @@
* @short_description: Simple implicit animations * @short_description: Simple implicit animations
* *
* #ClutterAnimation is an object providing simple, implicit animations * #ClutterAnimation is an object providing simple, implicit animations
* for #ClutterActor<!-- -->s. * for #GObject<!-- -->s.
* *
* #ClutterAnimation instances will bind a #GObject property belonging * #ClutterAnimation instances will bind a #GObject property belonging
* to a #ClutterActor to a #ClutterInterval, and will then use a * to a #GObject to a #ClutterInterval, and will then use a #ClutterTimeline
* #ClutterTimeline to interpolate the property between the initial * to interpolate the property between the initial and final values of the
* and final values of the interval. * interval.
* *
* 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
@ -60,7 +60,7 @@ enum
{ {
PROP_0, PROP_0,
PROP_ACTOR, PROP_OBJECT,
PROP_MODE, PROP_MODE,
PROP_DURATION, PROP_DURATION,
PROP_LOOP, PROP_LOOP,
@ -79,7 +79,7 @@ enum
struct _ClutterAnimationPrivate struct _ClutterAnimationPrivate
{ {
ClutterActor *actor; GObject *object;
GHashTable *properties; GHashTable *properties;
@ -96,7 +96,7 @@ struct _ClutterAnimationPrivate
static guint animation_signals[LAST_SIGNAL] = { 0, }; static guint animation_signals[LAST_SIGNAL] = { 0, };
static GQuark quark_actor_animation = 0; static GQuark quark_object_animation = 0;
G_DEFINE_TYPE (ClutterAnimation, clutter_animation, G_TYPE_INITIALLY_UNOWNED); G_DEFINE_TYPE (ClutterAnimation, clutter_animation, G_TYPE_INITIALLY_UNOWNED);
@ -118,16 +118,14 @@ clutter_animation_dispose (GObject *gobject)
{ {
ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv; ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
if (priv->actor) if (priv->object)
{ {
g_object_weak_unref (G_OBJECT (gobject), g_object_weak_unref (G_OBJECT (gobject),
on_animation_weak_notify, on_animation_weak_notify,
priv->actor); priv->object);
g_object_set_qdata (G_OBJECT (priv->actor), g_object_set_qdata (priv->object, quark_object_animation, NULL);
quark_actor_animation, g_object_unref (priv->object);
NULL); priv->object = NULL;
g_object_unref (priv->actor);
priv->actor = NULL;
} }
if (priv->timeline) if (priv->timeline)
@ -168,8 +166,8 @@ clutter_animation_set_property (GObject *gobject,
switch (prop_id) switch (prop_id)
{ {
case PROP_ACTOR: case PROP_OBJECT:
clutter_animation_set_actor (animation, g_value_get_object (value)); clutter_animation_set_object (animation, g_value_get_object (value));
break; break;
case PROP_MODE: case PROP_MODE:
@ -208,8 +206,8 @@ clutter_animation_get_property (GObject *gobject,
switch (prop_id) switch (prop_id)
{ {
case PROP_ACTOR: case PROP_OBJECT:
g_value_set_object (value, priv->actor); g_value_set_object (value, priv->object);
break; break;
case PROP_MODE: case PROP_MODE:
@ -253,7 +251,7 @@ clutter_animation_class_init (ClutterAnimationClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec; GParamSpec *pspec;
quark_actor_animation = quark_object_animation =
g_quark_from_static_string ("clutter-actor-animation"); g_quark_from_static_string ("clutter-actor-animation");
g_type_class_add_private (klass, sizeof (ClutterAnimationPrivate)); g_type_class_add_private (klass, sizeof (ClutterAnimationPrivate));
@ -266,18 +264,18 @@ clutter_animation_class_init (ClutterAnimationClass *klass)
gobject_class->finalize = clutter_animation_finalize; gobject_class->finalize = clutter_animation_finalize;
/** /**
* ClutterAnimation:actor: * ClutterAnimation:objct:
* *
* The actor to which the animation applies. * The #GObject to which the animation applies.
* *
* Since: 1.0 * Since: 1.0
*/ */
pspec = g_param_spec_object ("actor", pspec = g_param_spec_object ("object",
"Actor", "Object",
"Actor to which the animation applies", "Object to which the animation applies",
CLUTTER_TYPE_ACTOR, G_TYPE_OBJECT,
CLUTTER_PARAM_READWRITE); CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_ACTOR, pspec); g_object_class_install_property (gobject_class, PROP_OBJECT, pspec);
/** /**
* ClutterAnimation:mode: * ClutterAnimation:mode:
@ -427,7 +425,7 @@ clutter_animation_update_property_internal (ClutterAnimation *animation,
* @property_name: the property to control * @property_name: the property to control
* @interval: a #ClutterInterval * @interval: a #ClutterInterval
* *
* Binds @interval to the @property_name of the #ClutterActor * Binds @interval to the @property_name of the #GObject
* attached to @animation. The #ClutterAnimation will take * attached to @animation. The #ClutterAnimation will take
* ownership of the passed #ClutterInterval. * ownership of the passed #ClutterInterval.
* *
@ -451,10 +449,10 @@ clutter_animation_bind_property (ClutterAnimation *animation,
priv = animation->priv; priv = animation->priv;
if (G_UNLIKELY (!priv->actor)) if (G_UNLIKELY (!priv->object))
{ {
g_warning ("Cannot bind property `%s': the animation has no " g_warning ("Cannot bind property `%s': the animation has no "
"actor set. You need to call clutter_animation_set_actor() " "object set. You need to call clutter_animation_set_object() "
"first to be able to bind a property", "first to be able to bind a property",
property_name); property_name);
return; return;
@ -468,14 +466,14 @@ clutter_animation_bind_property (ClutterAnimation *animation,
return; return;
} }
klass = G_OBJECT_GET_CLASS (priv->actor); klass = G_OBJECT_GET_CLASS (priv->object);
pspec = g_object_class_find_property (klass, property_name); pspec = g_object_class_find_property (klass, property_name);
if (!pspec) if (!pspec)
{ {
g_warning ("Cannot bind property `%s': actors of type `%s' have " g_warning ("Cannot bind property `%s': objects of type `%s' have "
"no such property", "no such property",
property_name, property_name,
g_type_name (G_OBJECT_TYPE (priv->actor))); g_type_name (G_OBJECT_TYPE (priv->object)));
return; return;
} }
@ -592,14 +590,14 @@ clutter_animation_update_property (ClutterAnimation *animation,
return; return;
} }
klass = G_OBJECT_GET_CLASS (priv->actor); klass = G_OBJECT_GET_CLASS (priv->object);
pspec = g_object_class_find_property (klass, property_name); pspec = g_object_class_find_property (klass, property_name);
if (!pspec) if (!pspec)
{ {
g_warning ("Cannot bind property `%s': actors of type `%s' have " g_warning ("Cannot bind property `%s': objects of type `%s' have "
"no such property", "no such property",
property_name, property_name,
g_type_name (G_OBJECT_TYPE (priv->actor))); g_type_name (G_OBJECT_TYPE (priv->object)));
return; return;
} }
@ -667,7 +665,7 @@ on_alpha_notify (GObject *gobject,
alpha_value = clutter_alpha_get_alpha (CLUTTER_ALPHA (gobject)); alpha_value = clutter_alpha_get_alpha (CLUTTER_ALPHA (gobject));
g_object_freeze_notify (G_OBJECT (priv->actor)); g_object_freeze_notify (priv->object);
properties = g_hash_table_get_keys (priv->properties); properties = g_hash_table_get_keys (priv->properties);
for (p = properties; p != NULL; p = p->next) for (p = properties; p != NULL; p = p->next)
@ -685,14 +683,14 @@ on_alpha_notify (GObject *gobject,
factor = (gdouble) alpha_value / CLUTTER_ALPHA_MAX_ALPHA; factor = (gdouble) alpha_value / CLUTTER_ALPHA_MAX_ALPHA;
if (clutter_interval_compute_value (interval, factor, &value)) if (clutter_interval_compute_value (interval, factor, &value))
g_object_set_property (G_OBJECT (priv->actor), p_name, &value); g_object_set_property (priv->object, p_name, &value);
g_value_unset (&value); g_value_unset (&value);
} }
g_list_free (properties); g_list_free (properties);
g_object_thaw_notify (G_OBJECT (priv->actor)); g_object_thaw_notify (priv->object);
} }
/* /*
@ -709,7 +707,7 @@ on_animation_weak_notify (gpointer data,
clutter_actor_get_gid (CLUTTER_ACTOR (actor)), clutter_actor_get_gid (CLUTTER_ACTOR (actor)),
actor); actor);
g_object_set_qdata (actor, quark_actor_animation, NULL); g_object_set_qdata (actor, quark_object_animation, NULL);
} }
ClutterAnimation * ClutterAnimation *
@ -719,66 +717,64 @@ clutter_animation_new (void)
} }
/** /**
* clutter_animation_set_actor: * clutter_animation_set_object:
* @animation: a #ClutterAnimation * @animation: a #ClutterAnimation
* @actor: a #ClutterActor * @object: a #GObject
* *
* Attaches @animation to @actor. The #ClutterAnimation will take a * Attaches @animation to @object. The #ClutterAnimation will take a
* reference on @actor. * reference on @object.
* *
* Since: 1.0 * Since: 1.0
*/ */
void void
clutter_animation_set_actor (ClutterAnimation *animation, clutter_animation_set_object (ClutterAnimation *animation,
ClutterActor *actor) GObject *object)
{ {
ClutterAnimationPrivate *priv; ClutterAnimationPrivate *priv;
g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
g_return_if_fail (CLUTTER_IS_ACTOR (actor)); g_return_if_fail (G_IS_OBJECT (object));
priv = animation->priv; priv = animation->priv;
g_object_ref (actor); g_object_ref (object);
if (priv->actor) if (priv->object)
{ {
g_object_weak_unref (G_OBJECT (animation), g_object_weak_unref (G_OBJECT (animation),
on_animation_weak_notify, on_animation_weak_notify,
priv->actor); priv->object);
g_object_set_qdata (G_OBJECT (priv->actor), g_object_set_qdata (priv->object, quark_object_animation, NULL);
quark_actor_animation, g_object_unref (priv->object);
NULL);
g_object_unref (priv->actor);
} }
priv->actor = actor; priv->object = object;
g_object_weak_ref (G_OBJECT (animation), g_object_weak_ref (G_OBJECT (animation),
on_animation_weak_notify, on_animation_weak_notify,
priv->actor); priv->object);
g_object_set_qdata (G_OBJECT (priv->actor), g_object_set_qdata (G_OBJECT (priv->object),
quark_actor_animation, quark_object_animation,
animation); animation);
g_object_notify (G_OBJECT (animation), "actor"); g_object_notify (G_OBJECT (animation), "object");
} }
/** /**
* clutter_animation_get_actor: * clutter_animation_get_object:
* @animation: a #ClutterAnimation * @animation: a #ClutterAnimation
* *
* Retrieves the #ClutterActor attached to @animation. * Retrieves the #GObject attached to @animation.
* *
* Return value: a #ClutterActor * Return value: a #GObject
* *
* Since: 1.0 * Since: 1.0
*/ */
ClutterActor * GObject *
clutter_animation_get_actor (ClutterAnimation *animation) clutter_animation_get_object (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->actor; return animation->priv->object;
} }
static inline void static inline void
@ -1125,7 +1121,7 @@ clutter_animation_setup_valist (ClutterAnimation *animation,
GObjectClass *klass; GObjectClass *klass;
const gchar *property_name; const gchar *property_name;
klass = G_OBJECT_GET_CLASS (priv->actor); klass = G_OBJECT_GET_CLASS (priv->object);
property_name = first_property_name; property_name = first_property_name;
while (property_name != NULL) while (property_name != NULL)
@ -1145,10 +1141,10 @@ clutter_animation_setup_valist (ClutterAnimation *animation,
pspec = g_object_class_find_property (klass, property_name); pspec = g_object_class_find_property (klass, property_name);
if (!pspec) if (!pspec)
{ {
g_warning ("Cannot bind property `%s': actors of type `%s' do " g_warning ("Cannot bind property `%s': objects of type `%s' do "
"not have this property", "not have this property",
property_name, property_name,
g_type_name (G_OBJECT_TYPE (priv->actor))); g_type_name (G_OBJECT_TYPE (priv->object)));
break; break;
} }
@ -1178,9 +1174,7 @@ clutter_animation_setup_valist (ClutterAnimation *animation,
GValue initial = { 0, }; GValue initial = { 0, };
g_value_init (&initial, G_PARAM_SPEC_VALUE_TYPE (pspec)); g_value_init (&initial, G_PARAM_SPEC_VALUE_TYPE (pspec));
g_object_get_property (G_OBJECT (priv->actor), g_object_get_property (priv->object, property_name, &initial);
property_name,
&initial);
interval = interval =
clutter_interval_new_with_values (G_PARAM_SPEC_VALUE_TYPE (pspec), clutter_interval_new_with_values (G_PARAM_SPEC_VALUE_TYPE (pspec),
@ -1199,7 +1193,7 @@ clutter_animation_setup_valist (ClutterAnimation *animation,
g_value_unset (&initial); g_value_unset (&initial);
} }
else else
g_object_set_property (G_OBJECT (priv->actor), property_name, &final); g_object_set_property (priv->object, property_name, &final);
g_value_unset (&final); g_value_unset (&final);
@ -1254,7 +1248,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
return NULL; return NULL;
} }
animation = g_object_get_qdata (G_OBJECT (actor), quark_actor_animation); animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
if (G_LIKELY (!animation)) if (G_LIKELY (!animation))
{ {
animation = clutter_animation_new (); animation = clutter_animation_new ();
@ -1265,7 +1259,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
clutter_animation_set_timeline (animation, timeline); clutter_animation_set_timeline (animation, timeline);
clutter_animation_set_alpha (animation, alpha); clutter_animation_set_alpha (animation, alpha);
clutter_animation_set_actor (animation, actor); 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);
@ -1311,7 +1305,7 @@ clutter_actor_animate_with_timeline (ClutterActor *actor,
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL);
g_return_val_if_fail (first_property_name != NULL, NULL); g_return_val_if_fail (first_property_name != NULL, NULL);
animation = g_object_get_qdata (G_OBJECT (actor), quark_actor_animation); animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
if (G_LIKELY (!animation)) if (G_LIKELY (!animation))
{ {
animation = clutter_animation_new (); animation = clutter_animation_new ();
@ -1323,7 +1317,7 @@ clutter_actor_animate_with_timeline (ClutterActor *actor,
clutter_animation_set_timeline (animation, timeline); clutter_animation_set_timeline (animation, timeline);
clutter_animation_set_alpha (animation, NULL); clutter_animation_set_alpha (animation, NULL);
clutter_animation_set_mode (animation, mode); clutter_animation_set_mode (animation, mode);
clutter_animation_set_actor (animation, actor); 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);
@ -1406,7 +1400,7 @@ clutter_actor_animate (ClutterActor *actor,
g_return_val_if_fail (duration > 0, NULL); g_return_val_if_fail (duration > 0, NULL);
g_return_val_if_fail (first_property_name != NULL, NULL); g_return_val_if_fail (first_property_name != NULL, NULL);
animation = g_object_get_qdata (G_OBJECT (actor), quark_actor_animation); animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
if (G_LIKELY (!animation)) if (G_LIKELY (!animation))
{ {
/* if there is no animation already attached to the actor, /* if there is no animation already attached to the actor,
@ -1416,7 +1410,7 @@ clutter_actor_animate (ClutterActor *actor,
animation = clutter_animation_new (); animation = clutter_animation_new ();
clutter_animation_set_timeline (animation, NULL); clutter_animation_set_timeline (animation, NULL);
clutter_animation_set_alpha (animation, NULL); clutter_animation_set_alpha (animation, NULL);
clutter_animation_set_actor (animation, actor); clutter_animation_set_object (animation, G_OBJECT (actor));
CLUTTER_NOTE (ANIMATION, "Created new Animation [%p]", animation); CLUTTER_NOTE (ANIMATION, "Created new Animation [%p]", animation);
} }

View file

@ -97,9 +97,9 @@ GType clutter_animation_get_type (void) G_GNUC_CONST;
ClutterAnimation * clutter_animation_new (void); ClutterAnimation * clutter_animation_new (void);
void clutter_animation_set_actor (ClutterAnimation *animation, void clutter_animation_set_object (ClutterAnimation *animation,
ClutterActor *actor); GObject *object);
ClutterActor * clutter_animation_get_actor (ClutterAnimation *animation); GObject * clutter_animation_get_object (ClutterAnimation *animation);
void clutter_animation_set_mode (ClutterAnimation *animation, void clutter_animation_set_mode (ClutterAnimation *animation,
ClutterAnimationMode mode); ClutterAnimationMode mode);
ClutterAnimationMode clutter_animation_get_mode (ClutterAnimation *animation); ClutterAnimationMode clutter_animation_get_mode (ClutterAnimation *animation);