actor: Add ::transition-stopped

The ::transition-stopped signal can be used to get notification of the
end of a transition.
This commit is contained in:
Emmanuele Bassi 2012-07-21 12:49:53 -04:00
parent e0e5ab9dd4
commit 28c2eeef95
3 changed files with 99 additions and 26 deletions

View File

@ -964,6 +964,7 @@ enum
ALLOCATION_CHANGED,
TRANSITIONS_COMPLETED,
TOUCH_EVENT,
TRANSITION_STOPPED,
LAST_SIGNAL
};
@ -4449,8 +4450,6 @@ clutter_actor_set_rotation_angle (ClutterActor *self,
_clutter_actor_create_transition (self, pspec, *cur_angle_p, angle);
else
_clutter_actor_update_transition (self, pspec, angle);
clutter_actor_queue_redraw (self);
}
/**
@ -8014,6 +8013,32 @@ clutter_actor_class_init (ClutterActorClass *klass)
_clutter_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* ClutterActor::transition-stopped:
* @actor: a #ClutterActor
* @name: the name of the transition
* @is_finished: whether the transition was finished, or stopped
*
* The ::transition-stopped signal is emitted once a transition
* is stopped; a transition is stopped once it reached its total
* duration (including eventual repeats), it has been stopped
* using clutter_timeline_stop(), or it has been removed from the
* transitions applied on @actor, using clutter_actor_remove_transition().
*
* Since: 1.12
*/
actor_signals[TRANSITION_STOPPED] =
g_signal_new (I_("transition-stopped"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED,
0,
NULL, NULL,
_clutter_marshal_VOID__STRING_BOOLEAN,
G_TYPE_NONE, 2,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
/**
* ClutterActor::touch-event:
* @actor: a #ClutterActor
@ -18350,6 +18375,11 @@ on_transition_stopped (ClutterTransition *transition,
{
ClutterActor *actor = clos->actor;
ClutterAnimationInfo *info;
GQuark t_quark;
gchar *t_name;
if (clos->name == NULL)
return;
/* reset the caches used by animations */
clutter_actor_store_content_box (actor, NULL);
@ -18359,6 +18389,9 @@ on_transition_stopped (ClutterTransition *transition,
info = _clutter_actor_get_animation_info (actor);
t_quark = g_quark_from_string (clos->name);
t_name = g_strdup (clos->name);
/* we take a reference here because removing the closure
* will release the reference on the transition, and we
* want the transition to survive the signal emission;
@ -18368,6 +18401,16 @@ on_transition_stopped (ClutterTransition *transition,
g_object_ref (transition);
g_hash_table_remove (info->transitions, clos->name);
/* we emit the ::transition-stopped after removing the
* transition, so that we can chain up new transitions
* without interfering with the one that just finished
*/
g_signal_emit (actor, actor_signals[TRANSITION_STOPPED], t_quark,
t_name,
TRUE);
g_free (t_name);
/* if it's the last transition then we clean up */
if (g_hash_table_size (info->transitions) == 0)
{
@ -18481,6 +18524,9 @@ _clutter_actor_create_transition (ClutterActor *actor,
TransitionClosure *clos;
va_list var_args;
g_assert (pspec != NULL);
g_assert ((pspec->flags & CLUTTER_PARAM_ANIMATABLE) != 0);
info = _clutter_actor_get_animation_info (actor);
/* XXX - this will go away in 2.0
@ -18559,9 +18605,6 @@ _clutter_actor_create_transition (ClutterActor *actor,
interval = clutter_interval_new_with_values (ptype, &initial, &final);
g_value_unset (&initial);
g_value_unset (&final);
res = clutter_property_transition_new (pspec->name);
clutter_transition_set_interval (res, interval);
@ -18572,22 +18615,45 @@ _clutter_actor_create_transition (ClutterActor *actor,
clutter_timeline_set_duration (timeline, info->cur_state->easing_duration);
clutter_timeline_set_progress_mode (timeline, info->cur_state->easing_mode);
#ifdef CLUTTER_ENABLE_DEBUG
{
gchar *initial_v, *final_v;
initial_v = g_strdup_value_contents (&initial);
final_v = g_strdup_value_contents (&final);
CLUTTER_NOTE (ANIMATION,
"Created transition for %s:%s (len:%u, mode:%s, delay:%u)",
"Created transition for %s:%s "
"(len:%u, mode:%s, delay:%u) "
"initial:%s, final:%s",
_clutter_actor_get_debug_name (actor),
pspec->name,
info->cur_state->easing_duration,
clutter_get_easing_name_for_mode (info->cur_state->easing_mode),
info->cur_state->easing_delay);
info->cur_state->easing_delay,
initial_v, final_v);
g_free (initial_v);
g_free (final_v);
}
#endif /* CLUTTER_ENABLE_DEBUG */
/* this will start the transition as well */
clutter_actor_add_transition (actor, pspec->name, res);
/* the actor now owns the transition */
g_object_unref (res);
g_value_unset (&initial);
g_value_unset (&final);
}
else
{
CLUTTER_NOTE (ANIMATION, "Existing transition for %s:%s",
_clutter_actor_get_debug_name (actor),
pspec->name);
res = clos->transition;
}
out:
if (call_restore)
@ -18698,6 +18764,11 @@ clutter_actor_remove_transition (ClutterActor *self,
if (info->transitions == NULL)
return;
g_signal_emit (self, actor_signals[TRANSITION_STOPPED],
g_quark_from_string (name),
name,
FALSE);
g_hash_table_remove (info->transitions, name);
}

View File

@ -24,6 +24,7 @@ VOID:OBJECT,PARAM
VOID:OBJECT,POINTER
VOID:OBJECT,UINT
VOID:POINTER
VOID:STRING,BOOLEAN
VOID:STRING,BOOLEAN,BOOLEAN
VOID:STRING,INT
VOID:UINT

View File

@ -49,36 +49,37 @@ on_crossing (ClutterActor *actor,
}
static void
on_transition_stopped (ClutterTransition *transition,
gboolean is_finished,
ClutterActor *actor)
on_transition_stopped (ClutterActor *actor,
const gchar *transition_name,
gboolean is_finished)
{
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_duration (actor, 250);
clutter_actor_set_rotation_angle (actor, CLUTTER_Y_AXIS, 0.0f);
clutter_actor_restore_easing_state (actor);
/* disconnect so we don't get multiple notifications */
g_signal_handlers_disconnect_by_func (actor,
on_transition_stopped,
NULL);
}
static gboolean
animate_rotation (ClutterActor *actor,
ClutterEvent *event)
{
ClutterTransition *transition;
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_duration (actor, 1000);
clutter_actor_set_rotation_angle (actor, CLUTTER_Y_AXIS, 360.0);
transition = clutter_actor_get_transition (actor, "rotation-angle-y");
g_signal_connect (transition, "stopped",
G_CALLBACK (on_transition_stopped),
actor);
clutter_actor_restore_easing_state (actor);
/* get a notification when the rotation-angle-y transition ends */
g_signal_connect (actor,
"transition-stopped::rotation-angle-y",
G_CALLBACK (on_transition_stopped),
NULL);
return CLUTTER_EVENT_STOP;
}