clutter/timeline: Add way to associate a timeline to an actor

The association is inactive, as in it doesn't do anything yet, but it
will later be used to determine what frame clock should be driving the
timeline by looking at what stage view the actor is currently on.

This also adapts sub types (ClutterPropertyTransition) to have
constuctors that takes an actor just as the new ClutterTimeline
constructor.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
This commit is contained in:
Jonas Ådahl 2020-04-17 09:00:18 +02:00
parent ff5f77f273
commit 203c20d7ad
4 changed files with 140 additions and 1 deletions

View File

@ -278,6 +278,26 @@ clutter_property_transition_init (ClutterPropertyTransition *self)
self->priv = clutter_property_transition_get_instance_private (self); self->priv = clutter_property_transition_get_instance_private (self);
} }
/**
* clutter_property_transition_new_for_actor:
* @actor: a #ClutterActor
* @property_name: (allow-none): a property of @animatable, or %NULL
*
* Creates a new #ClutterPropertyTransition.
*
* Return value: (transfer full): the newly created #ClutterPropertyTransition.
* Use g_object_unref() when done
*/
ClutterTransition *
clutter_property_transition_new_for_actor (ClutterActor *actor,
const char *property_name)
{
return g_object_new (CLUTTER_TYPE_PROPERTY_TRANSITION,
"actor", actor,
"property-name", property_name,
NULL);
}
/** /**
* clutter_property_transition_new: * clutter_property_transition_new:
* @property_name: (allow-none): a property of @animatable, or %NULL * @property_name: (allow-none): a property of @animatable, or %NULL

View File

@ -79,7 +79,11 @@ CLUTTER_EXPORT
GType clutter_property_transition_get_type (void) G_GNUC_CONST; GType clutter_property_transition_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterTransition * clutter_property_transition_new_for_actor (ClutterActor *actor,
const char *property_name);
ClutterTransition * clutter_property_transition_new (const char *property_name); ClutterTransition * clutter_property_transition_new (const char *property_name);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_property_transition_set_property_name (ClutterPropertyTransition *transition, void clutter_property_transition_set_property_name (ClutterPropertyTransition *transition,
const char *property_name); const char *property_name);

View File

@ -113,6 +113,9 @@ struct _ClutterTimelinePrivate
ClutterFrameClock *frame_clock; ClutterFrameClock *frame_clock;
ClutterActor *actor;
gulong actor_destroy_handler_id;
guint delay_id; guint delay_id;
/* The total length in milliseconds of this timeline */ /* The total length in milliseconds of this timeline */
@ -174,6 +177,7 @@ enum
{ {
PROP_0, PROP_0,
PROP_ACTOR,
PROP_DELAY, PROP_DELAY,
PROP_DURATION, PROP_DURATION,
PROP_DIRECTION, PROP_DIRECTION,
@ -292,6 +296,60 @@ clutter_timeline_add_marker_internal (ClutterTimeline *timeline,
g_hash_table_insert (priv->markers_by_name, marker->name, marker); g_hash_table_insert (priv->markers_by_name, marker->name, marker);
} }
static void
on_actor_destroyed (ClutterActor *actor,
ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
priv->actor = NULL;
}
/**
* clutter_timeline_get_actor:
* @timeline: a #ClutterTimeline
*
* Get the actor the timeline is associated with.
*
* Returns: (transfer none): the associated #ClutterActor
*/
ClutterActor *
clutter_timeline_get_actor (ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
return priv->actor;
}
/**
* clutter_timeline_set_actor:
* @timeline: a #ClutterTimeline
* @actor: (nullable): a #ClutterActor
*
* Set the actor the timeline is associated with.
*/
void
clutter_timeline_set_actor (ClutterTimeline *timeline,
ClutterActor *actor)
{
ClutterTimelinePrivate *priv = timeline->priv;
if (priv->actor)
{
g_clear_signal_handler (&priv->actor_destroy_handler_id, priv->actor);
}
priv->actor = actor;
if (priv->actor)
{
priv->actor_destroy_handler_id =
g_signal_connect (priv->actor, "destroy",
G_CALLBACK (on_actor_destroyed),
timeline);
}
}
/* Scriptable */ /* Scriptable */
typedef struct _ParseClosure { typedef struct _ParseClosure {
ClutterTimeline *timeline; ClutterTimeline *timeline;
@ -433,6 +491,10 @@ clutter_timeline_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_ACTOR:
clutter_timeline_set_actor (timeline, g_value_get_object (value));
break;
case PROP_DELAY: case PROP_DELAY:
clutter_timeline_set_delay (timeline, g_value_get_uint (value)); clutter_timeline_set_delay (timeline, g_value_get_uint (value));
break; break;
@ -478,6 +540,10 @@ clutter_timeline_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_ACTOR:
g_value_set_object (value, priv->actor);
break;
case PROP_DELAY: case PROP_DELAY:
g_value_set_uint (value, priv->delay); g_value_set_uint (value, priv->delay);
break; break;
@ -575,6 +641,12 @@ clutter_timeline_dispose (GObject *object)
clutter_timeline_cancel_delay (self); clutter_timeline_cancel_delay (self);
if (priv->actor)
{
g_clear_signal_handler (&priv->actor_destroy_handler_id, priv->actor);
priv->actor = NULL;
}
if (priv->progress_notify != NULL) if (priv->progress_notify != NULL)
{ {
priv->progress_notify (priv->progress_data); priv->progress_notify (priv->progress_data);
@ -591,6 +663,18 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
/**
* ClutterTimeline::actor:
*
* The actor the timeline is associated with. This will determine what frame
* clock will drive it.
*/
obj_props[PROP_ACTOR] =
g_param_spec_object ("actor",
P_("Actor"),
P_("Associated ClutterActor"),
CLUTTER_TYPE_ACTOR,
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE);
/** /**
* ClutterTimeline:delay: * ClutterTimeline:delay:
* *
@ -1398,12 +1482,32 @@ clutter_timeline_new (guint duration_ms)
NULL); NULL);
} }
/**
* clutter_timeline_new_for_actor:
* @actor: The #ClutterActor the timeline is associated with
* @duration_ms: Duration of the timeline in milliseconds
*
* Creates a new #ClutterTimeline with a duration of @duration milli seconds.
*
* Return value: the newly created #ClutterTimeline instance. Use
* g_object_unref() when done using it
*/
ClutterTimeline *
clutter_timeline_new_for_actor (ClutterActor *actor,
unsigned int duration_ms)
{
return g_object_new (CLUTTER_TYPE_TIMELINE,
"duration", duration_ms,
"actor", actor,
NULL);
}
/** /**
* clutter_timeline_new_for_frame_clock: * clutter_timeline_new_for_frame_clock:
* @frame_clock: The #ClutterFrameClock the timeline is driven by * @frame_clock: The #ClutterFrameClock the timeline is driven by
* @duration_ms: Duration of the timeline in milliseconds * @duration_ms: Duration of the timeline in milliseconds
* *
* Creates a new #ClutterTimeline with a duration of @duration milli seconds. * Creates a new #ClutterTimeline with a duration of @duration_ms milli seconds.
* *
* Return value: the newly created #ClutterTimeline instance. Use * Return value: the newly created #ClutterTimeline instance. Use
* g_object_unref() when done using it * g_object_unref() when done using it

View File

@ -121,10 +121,21 @@ GType clutter_timeline_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterTimeline * clutter_timeline_new (guint duration_ms); ClutterTimeline * clutter_timeline_new (guint duration_ms);
CLUTTER_EXPORT
ClutterTimeline * clutter_timeline_new_for_actor (ClutterActor *actor,
unsigned int duration_ms);
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterTimeline * clutter_timeline_new_for_frame_clock (ClutterFrameClock *frame_clock, ClutterTimeline * clutter_timeline_new_for_frame_clock (ClutterFrameClock *frame_clock,
unsigned int duration_ms); unsigned int duration_ms);
CLUTTER_EXPORT
ClutterActor * clutter_timeline_get_actor (ClutterTimeline *timeline);
CLUTTER_EXPORT
void clutter_timeline_set_actor (ClutterTimeline *timeline,
ClutterActor *actor);
CLUTTER_EXPORT CLUTTER_EXPORT
guint clutter_timeline_get_duration (ClutterTimeline *timeline); guint clutter_timeline_get_duration (ClutterTimeline *timeline);
CLUTTER_EXPORT CLUTTER_EXPORT