[clutter/wip/master-next: 1/8] actor: Add ::transition-stopped



commit 5112a19751acb020827979d6ae50d46534101a5a
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Sat Jul 21 12:49:53 2012 -0400

    actor: Add ::transition-stopped
    
    The ::transition-stopped signal can be used to get notification of the
    end of a transition.

 clutter/clutter-actor.c      |   97 ++++++++++++++++++++++++++++++++++++------
 clutter/clutter-marshal.list |    1 +
 examples/basic-actor.c       |   27 ++++++------
 3 files changed, 99 insertions(+), 26 deletions(-)
---
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 4699340..e135304 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -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);
 }
 
 /**
@@ -8015,6 +8014,32 @@ clutter_actor_class_init (ClutterActorClass *klass)
                   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);
 
-      CLUTTER_NOTE (ANIMATION,
-                    "Created transition for %s:%s (len:%u, mode:%s, delay:%u)",
-                    _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);
+#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) "
+                      "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,
+                      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
-    res = clos->transition;
+    {
+      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);
 }
 
diff --git a/clutter/clutter-marshal.list b/clutter/clutter-marshal.list
index 557bf2a..efe8fb5 100644
--- a/clutter/clutter-marshal.list
+++ b/clutter/clutter-marshal.list
@@ -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
diff --git a/examples/basic-actor.c b/examples/basic-actor.c
index 0ce3967..1bfb427 100644
--- a/examples/basic-actor.c
+++ b/examples/basic-actor.c
@@ -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;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]