[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:
parent
28b0f432b7
commit
068ba1caf0
2 changed files with 74 additions and 80 deletions
|
@ -27,12 +27,12 @@
|
|||
* @short_description: 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
|
||||
* to a #ClutterActor to a #ClutterInterval, and will then use a
|
||||
* #ClutterTimeline to interpolate the property between the initial
|
||||
* and final values of the interval.
|
||||
* to a #GObject to a #ClutterInterval, and will then use a #ClutterTimeline
|
||||
* to interpolate the property between the initial and final values of the
|
||||
* interval.
|
||||
*
|
||||
* For convenience, it is possible to use the clutter_actor_animate()
|
||||
* function call which will take care of setting up and tearing down
|
||||
|
@ -60,7 +60,7 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_ACTOR,
|
||||
PROP_OBJECT,
|
||||
PROP_MODE,
|
||||
PROP_DURATION,
|
||||
PROP_LOOP,
|
||||
|
@ -79,7 +79,7 @@ enum
|
|||
|
||||
struct _ClutterAnimationPrivate
|
||||
{
|
||||
ClutterActor *actor;
|
||||
GObject *object;
|
||||
|
||||
GHashTable *properties;
|
||||
|
||||
|
@ -96,7 +96,7 @@ struct _ClutterAnimationPrivate
|
|||
|
||||
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);
|
||||
|
||||
|
@ -118,16 +118,14 @@ clutter_animation_dispose (GObject *gobject)
|
|||
{
|
||||
ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
|
||||
|
||||
if (priv->actor)
|
||||
if (priv->object)
|
||||
{
|
||||
g_object_weak_unref (G_OBJECT (gobject),
|
||||
on_animation_weak_notify,
|
||||
priv->actor);
|
||||
g_object_set_qdata (G_OBJECT (priv->actor),
|
||||
quark_actor_animation,
|
||||
NULL);
|
||||
g_object_unref (priv->actor);
|
||||
priv->actor = NULL;
|
||||
priv->object);
|
||||
g_object_set_qdata (priv->object, quark_object_animation, NULL);
|
||||
g_object_unref (priv->object);
|
||||
priv->object = NULL;
|
||||
}
|
||||
|
||||
if (priv->timeline)
|
||||
|
@ -168,8 +166,8 @@ clutter_animation_set_property (GObject *gobject,
|
|||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTOR:
|
||||
clutter_animation_set_actor (animation, g_value_get_object (value));
|
||||
case PROP_OBJECT:
|
||||
clutter_animation_set_object (animation, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_MODE:
|
||||
|
@ -208,8 +206,8 @@ clutter_animation_get_property (GObject *gobject,
|
|||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTOR:
|
||||
g_value_set_object (value, priv->actor);
|
||||
case PROP_OBJECT:
|
||||
g_value_set_object (value, priv->object);
|
||||
break;
|
||||
|
||||
case PROP_MODE:
|
||||
|
@ -253,7 +251,7 @@ clutter_animation_class_init (ClutterAnimationClass *klass)
|
|||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
quark_actor_animation =
|
||||
quark_object_animation =
|
||||
g_quark_from_static_string ("clutter-actor-animation");
|
||||
|
||||
g_type_class_add_private (klass, sizeof (ClutterAnimationPrivate));
|
||||
|
@ -266,18 +264,18 @@ clutter_animation_class_init (ClutterAnimationClass *klass)
|
|||
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
|
||||
*/
|
||||
pspec = g_param_spec_object ("actor",
|
||||
"Actor",
|
||||
"Actor to which the animation applies",
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
pspec = g_param_spec_object ("object",
|
||||
"Object",
|
||||
"Object to which the animation applies",
|
||||
G_TYPE_OBJECT,
|
||||
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:
|
||||
|
@ -427,7 +425,7 @@ clutter_animation_update_property_internal (ClutterAnimation *animation,
|
|||
* @property_name: the property to control
|
||||
* @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
|
||||
* ownership of the passed #ClutterInterval.
|
||||
*
|
||||
|
@ -451,10 +449,10 @@ clutter_animation_bind_property (ClutterAnimation *animation,
|
|||
|
||||
priv = animation->priv;
|
||||
|
||||
if (G_UNLIKELY (!priv->actor))
|
||||
if (G_UNLIKELY (!priv->object))
|
||||
{
|
||||
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",
|
||||
property_name);
|
||||
return;
|
||||
|
@ -468,14 +466,14 @@ clutter_animation_bind_property (ClutterAnimation *animation,
|
|||
return;
|
||||
}
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (priv->actor);
|
||||
klass = G_OBJECT_GET_CLASS (priv->object);
|
||||
pspec = g_object_class_find_property (klass, property_name);
|
||||
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",
|
||||
property_name,
|
||||
g_type_name (G_OBJECT_TYPE (priv->actor)));
|
||||
g_type_name (G_OBJECT_TYPE (priv->object)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -592,14 +590,14 @@ clutter_animation_update_property (ClutterAnimation *animation,
|
|||
return;
|
||||
}
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (priv->actor);
|
||||
klass = G_OBJECT_GET_CLASS (priv->object);
|
||||
pspec = g_object_class_find_property (klass, property_name);
|
||||
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",
|
||||
property_name,
|
||||
g_type_name (G_OBJECT_TYPE (priv->actor)));
|
||||
g_type_name (G_OBJECT_TYPE (priv->object)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -667,7 +665,7 @@ on_alpha_notify (GObject *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);
|
||||
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;
|
||||
|
||||
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_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)),
|
||||
actor);
|
||||
|
||||
g_object_set_qdata (actor, quark_actor_animation, NULL);
|
||||
g_object_set_qdata (actor, quark_object_animation, NULL);
|
||||
}
|
||||
|
||||
ClutterAnimation *
|
||||
|
@ -719,66 +717,64 @@ clutter_animation_new (void)
|
|||
}
|
||||
|
||||
/**
|
||||
* clutter_animation_set_actor:
|
||||
* clutter_animation_set_object:
|
||||
* @animation: a #ClutterAnimation
|
||||
* @actor: a #ClutterActor
|
||||
* @object: a #GObject
|
||||
*
|
||||
* Attaches @animation to @actor. The #ClutterAnimation will take a
|
||||
* reference on @actor.
|
||||
* Attaches @animation to @object. The #ClutterAnimation will take a
|
||||
* reference on @object.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_animation_set_actor (ClutterAnimation *animation,
|
||||
ClutterActor *actor)
|
||||
clutter_animation_set_object (ClutterAnimation *animation,
|
||||
GObject *object)
|
||||
{
|
||||
ClutterAnimationPrivate *priv;
|
||||
|
||||
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;
|
||||
|
||||
g_object_ref (actor);
|
||||
g_object_ref (object);
|
||||
|
||||
if (priv->actor)
|
||||
if (priv->object)
|
||||
{
|
||||
g_object_weak_unref (G_OBJECT (animation),
|
||||
on_animation_weak_notify,
|
||||
priv->actor);
|
||||
g_object_set_qdata (G_OBJECT (priv->actor),
|
||||
quark_actor_animation,
|
||||
NULL);
|
||||
g_object_unref (priv->actor);
|
||||
priv->object);
|
||||
g_object_set_qdata (priv->object, quark_object_animation, NULL);
|
||||
g_object_unref (priv->object);
|
||||
}
|
||||
|
||||
priv->actor = actor;
|
||||
priv->object = object;
|
||||
g_object_weak_ref (G_OBJECT (animation),
|
||||
on_animation_weak_notify,
|
||||
priv->actor);
|
||||
g_object_set_qdata (G_OBJECT (priv->actor),
|
||||
quark_actor_animation,
|
||||
priv->object);
|
||||
g_object_set_qdata (G_OBJECT (priv->object),
|
||||
quark_object_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
|
||||
*
|
||||
* Retrieves the #ClutterActor attached to @animation.
|
||||
* Retrieves the #GObject attached to @animation.
|
||||
*
|
||||
* Return value: a #ClutterActor
|
||||
* Return value: a #GObject
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_animation_get_actor (ClutterAnimation *animation)
|
||||
GObject *
|
||||
clutter_animation_get_object (ClutterAnimation *animation)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
|
||||
|
||||
return animation->priv->actor;
|
||||
return animation->priv->object;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -1125,7 +1121,7 @@ clutter_animation_setup_valist (ClutterAnimation *animation,
|
|||
GObjectClass *klass;
|
||||
const gchar *property_name;
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (priv->actor);
|
||||
klass = G_OBJECT_GET_CLASS (priv->object);
|
||||
|
||||
property_name = first_property_name;
|
||||
while (property_name != NULL)
|
||||
|
@ -1145,10 +1141,10 @@ clutter_animation_setup_valist (ClutterAnimation *animation,
|
|||
pspec = g_object_class_find_property (klass, property_name);
|
||||
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",
|
||||
property_name,
|
||||
g_type_name (G_OBJECT_TYPE (priv->actor)));
|
||||
g_type_name (G_OBJECT_TYPE (priv->object)));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1178,9 +1174,7 @@ clutter_animation_setup_valist (ClutterAnimation *animation,
|
|||
GValue initial = { 0, };
|
||||
|
||||
g_value_init (&initial, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||
g_object_get_property (G_OBJECT (priv->actor),
|
||||
property_name,
|
||||
&initial);
|
||||
g_object_get_property (priv->object, property_name, &initial);
|
||||
|
||||
interval =
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
|
@ -1254,7 +1248,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
|
|||
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))
|
||||
{
|
||||
animation = clutter_animation_new ();
|
||||
|
@ -1265,7 +1259,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
|
|||
|
||||
clutter_animation_set_timeline (animation, timeline);
|
||||
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);
|
||||
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 (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))
|
||||
{
|
||||
animation = clutter_animation_new ();
|
||||
|
@ -1323,7 +1317,7 @@ clutter_actor_animate_with_timeline (ClutterActor *actor,
|
|||
clutter_animation_set_timeline (animation, timeline);
|
||||
clutter_animation_set_alpha (animation, NULL);
|
||||
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);
|
||||
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 (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 there is no animation already attached to the actor,
|
||||
|
@ -1416,7 +1410,7 @@ clutter_actor_animate (ClutterActor *actor,
|
|||
animation = clutter_animation_new ();
|
||||
clutter_animation_set_timeline (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);
|
||||
}
|
||||
|
|
|
@ -97,9 +97,9 @@ GType clutter_animation_get_type (void) G_GNUC_CONST;
|
|||
|
||||
ClutterAnimation * clutter_animation_new (void);
|
||||
|
||||
void clutter_animation_set_actor (ClutterAnimation *animation,
|
||||
ClutterActor *actor);
|
||||
ClutterActor * clutter_animation_get_actor (ClutterAnimation *animation);
|
||||
void clutter_animation_set_object (ClutterAnimation *animation,
|
||||
GObject *object);
|
||||
GObject * clutter_animation_get_object (ClutterAnimation *animation);
|
||||
void clutter_animation_set_mode (ClutterAnimation *animation,
|
||||
ClutterAnimationMode mode);
|
||||
ClutterAnimationMode clutter_animation_get_mode (ClutterAnimation *animation);
|
||||
|
|
Loading…
Reference in a new issue