[clutter/wip/apocalypses/apocalypse-6: 15/17] actor: Add generic transition support



commit 4bd3583dbf59d1882d2b7704d6a1416176df80d6
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Thu Mar 15 16:40:41 2012 +0000

    actor: Add generic transition support
    
    ClutterActor should be able to hold all transitions, even the ones that
    have been explicitly created.
    
    This will allow to add new transitions types in the future, like the
    keyframe-based one, or the transition group.

 clutter/clutter-actor.c                    |  187 +++++++++++++++++++++++-----
 clutter/clutter-actor.h                    |   18 +++
 clutter/clutter.symbols                    |    3 +
 doc/reference/clutter/clutter-sections.txt |    3 +
 4 files changed, 179 insertions(+), 32 deletions(-)
---
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 753def0..3310caf 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -16614,11 +16614,25 @@ typedef struct _TransitionClosure
 {
   ClutterActor *actor;
   ClutterTransition *transition;
-  GParamSpec *property;
+  gchar *name;
   gulong completed_id;
 } TransitionClosure;
 
 static void
+transition_closure_free (gpointer data)
+{
+  if (G_LIKELY (data != NULL))
+    {
+      TransitionClosure *clos = data;
+
+      g_signal_handler_disconnect (clos->transition, clos->completed_id);
+      g_free (clos->name);
+
+      g_slice_free (TransitionClosure, clos);
+    }
+}
+
+static void
 on_transition_completed (ClutterTransition *transition,
                          TransitionClosure *clos)
 {
@@ -16626,11 +16640,8 @@ on_transition_completed (ClutterTransition *transition,
 
   info = _clutter_actor_get_animation_info (clos->actor);
 
-  g_hash_table_remove (info->transitions, clos->property->name);
-
-  g_signal_handler_disconnect (transition, clos->completed_id);
-
-  g_slice_free (TransitionClosure, clos);
+  /* this will take care of cleaning clos for us */
+  g_hash_table_remove (info->transitions, clos->name);
 }
 
 void
@@ -16638,7 +16649,7 @@ _clutter_actor_update_transition (ClutterActor *actor,
                                   GParamSpec   *pspec,
                                   ...)
 {
-  ClutterTransition *transition;
+  TransitionClosure *clos;
   ClutterInterval *interval;
   const ClutterAnimationInfo *info;
   va_list var_args;
@@ -16652,8 +16663,8 @@ _clutter_actor_update_transition (ClutterActor *actor,
   if (info->transitions == NULL)
     return;
 
-  transition = g_hash_table_lookup (info->transitions, pspec->name);
-  if (transition == NULL)
+  clos = g_hash_table_lookup (info->transitions, pspec->name);
+  if (clos == NULL)
     return;
 
   va_start (var_args, pspec);
@@ -16673,11 +16684,11 @@ _clutter_actor_update_transition (ClutterActor *actor,
       goto out;
     }
 
-  interval = clutter_transition_get_interval (transition);
+  interval = clutter_transition_get_interval (clos->transition);
   clutter_interval_set_initial_value (interval, &initial);
   clutter_interval_set_final_value (interval, &final);
 
-  clutter_timeline_rewind (CLUTTER_TIMELINE (transition));
+  clutter_timeline_rewind (CLUTTER_TIMELINE (clos->transition));
 
 out:
   g_value_unset (&initial);
@@ -16704,6 +16715,7 @@ _clutter_actor_create_transition (ClutterActor *actor,
   ClutterAnimationInfo *info;
   ClutterTransition *res = NULL;
   gboolean call_restore = FALSE;
+  TransitionClosure *clos;
   va_list var_args;
 
   info = _clutter_actor_get_animation_info (actor);
@@ -16715,19 +16727,20 @@ _clutter_actor_create_transition (ClutterActor *actor,
     }
 
   if (info->transitions == NULL)
-    info->transitions = g_hash_table_new (g_str_hash, g_str_equal);
+    info->transitions = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                               NULL,
+                                               transition_closure_free);
 
   va_start (var_args, pspec);
 
-  res = g_hash_table_lookup (info->transitions, pspec->name);
-  if (res == NULL)
+  clos = g_hash_table_lookup (info->transitions, pspec->name);
+  if (clos == NULL)
     {
       ClutterInterval *interval;
       GValue initial = G_VALUE_INIT;
       GValue final = G_VALUE_INIT;
       GType ptype;
       char *error;
-      TransitionClosure *clos;
 
       ptype = G_PARAM_SPEC_VALUE_TYPE (pspec);
 
@@ -16764,24 +16777,10 @@ _clutter_actor_create_transition (ClutterActor *actor,
       clutter_transition_set_interval (res, interval);
       clutter_transition_set_remove_on_complete (res, TRUE);
 
-      clutter_timeline_set_delay (CLUTTER_TIMELINE (res),
-                                  info->cur_state->easing_delay);
-      clutter_timeline_set_duration (CLUTTER_TIMELINE (res),
-                                     info->cur_state->easing_duration);
-      clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (res),
-                                          info->cur_state->easing_mode);
-
-      clos = g_slice_new (TransitionClosure);
-      clos->actor = actor;
-      clos->transition = res;
-      clos->property = pspec;
-      clos->completed_id =
-        g_signal_connect (res, "completed",
-                          G_CALLBACK (on_transition_completed),
-                          clos);
-
-      g_hash_table_insert (info->transitions, (gpointer) pspec->name, res);
+      clutter_actor_add_transition (actor, pspec->name, res);
     }
+  else
+    res = clos->transition;
 
 out:
   if (call_restore)
@@ -16793,6 +16792,130 @@ out:
 }
 
 /**
+ * clutter_actor_add_transition:
+ * @self: a #ClutterActor
+ * @name: the name of the transition to add
+ * @transition: the #ClutterTransition to add
+ *
+ * Adds a @transition to the #ClutterActor's list of animations.
+ *
+ * The @name string is a per-actor unique identifier of the @transition: only
+ * one #ClutterTransition can be associated to the specified @name.
+ *
+ * The @transition will be given the easing duration, mode, and delay
+ * associated to the actor's current easing state; it is possible to modify
+ * these values after calling clutter_actor_add_transition().
+ *
+ * This function is usually called implicitly when modifying an animatable
+ * property.
+ *
+ * Since: 1.10
+ */
+void
+clutter_actor_add_transition (ClutterActor      *self,
+                              const char        *name,
+                              ClutterTransition *transition)
+{
+  ClutterTimeline *timeline;
+  TransitionClosure *clos;
+  ClutterAnimationInfo *info;
+
+  g_return_if_fail (CLUTTER_IS_ACTOR (self));
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
+
+  info = _clutter_actor_get_animation_info (self);
+
+  if (info->cur_state == NULL)
+    {
+      g_warning ("No easing state is defined for the actor '%s'; you "
+                 "must call clutter_actor_save_easing_state() before "
+                 "calling clutter_actor_add_transition().",
+                 _clutter_actor_get_debug_name (self));
+      return;
+    }
+
+  if (info->transitions == NULL)
+    info->transitions = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                               NULL,
+                                               transition_closure_free);
+
+  if (g_hash_table_lookup (info->transitions, name) != NULL)
+    {
+      g_warning ("A transition with name '%s' already exists for "
+                 "the actor '%s'",
+                 name,
+                 _clutter_actor_get_debug_name (self));
+      return;
+    }
+
+  timeline = CLUTTER_TIMELINE (transition);
+
+  clutter_timeline_set_delay (timeline, info->cur_state->easing_delay);
+  clutter_timeline_set_duration (timeline, info->cur_state->easing_duration);
+  clutter_timeline_set_progress_mode (timeline, info->cur_state->easing_mode);
+
+  clos = g_slice_new (TransitionClosure);
+  clos->actor = self;
+  clos->transition = transition;
+  clos->name = g_strdup (name);
+  clos->completed_id = g_signal_connect (timeline, "completed",
+                                         G_CALLBACK (on_transition_completed),
+                                         clos);
+
+  g_hash_table_insert (info->transitions, clos->name, clos);
+}
+
+/**
+ * clutter_actor_remove_transition:
+ * @self: a #ClutterActor
+ * @name: the name of the transition to remove
+ *
+ * Removes the transition stored inside a #ClutterActor using @name
+ * identifier.
+ *
+ * Since: 1.10
+ */
+void
+clutter_actor_remove_transition (ClutterActor *self,
+                                 const char   *name)
+{
+  const ClutterAnimationInfo *info;
+
+  g_return_if_fail (CLUTTER_IS_ACTOR (self));
+  g_return_if_fail (name != NULL);
+
+  info = _clutter_actor_get_animation_info_or_defaults (self);
+
+  if (info->transitions == NULL)
+    return;
+
+  g_hash_table_remove (info->transitions, name);
+}
+
+/**
+ * clutter_actor_remove_all_transitions:
+ * @self: a #ClutterActor
+ *
+ * Removes all transitions associated to @self.
+ *
+ * Since: 1.10
+ */
+void
+clutter_actor_remove_all_transitions (ClutterActor *self)
+{
+  const ClutterAnimationInfo *info;
+
+  g_return_if_fail (CLUTTER_IS_ACTOR (self));
+
+  info = _clutter_actor_get_animation_info_or_defaults (self);
+  if (info->transitions == NULL)
+    return;
+
+  g_hash_table_remove_all (info->transitions);
+}
+
+/**
  * clutter_actor_set_easing_duration:
  * @self: a #ClutterActor
  * @msecs: the duration of the easing, or %NULL
diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h
index 2e4bd18..af832d2 100644
--- a/clutter/clutter-actor.h
+++ b/clutter/clutter-actor.h
@@ -643,19 +643,37 @@ void                            clutter_actor_get_transformation_matrix
                                                                                  CoglMatrix                 *matrix);
 
 /* Implicit animations */
+CLUTTER_AVAILABLE_IN_1_10
 void                            clutter_actor_save_easing_state                 (ClutterActor               *self);
+CLUTTER_AVAILABLE_IN_1_10
 void                            clutter_actor_restore_easing_state              (ClutterActor               *self);
+CLUTTER_AVAILABLE_IN_1_10
 void                            clutter_actor_set_easing_mode                   (ClutterActor               *self,
                                                                                  ClutterAnimationMode        mode);
+CLUTTER_AVAILABLE_IN_1_10
 ClutterAnimationMode            clutter_actor_get_easing_mode                   (ClutterActor               *self);
+CLUTTER_AVAILABLE_IN_1_10
 void                            clutter_actor_set_easing_duration               (ClutterActor               *self,
                                                                                  guint                       msecs);
+CLUTTER_AVAILABLE_IN_1_10
 guint                           clutter_actor_get_easing_duration               (ClutterActor               *self);
+CLUTTER_AVAILABLE_IN_1_10
 void                            clutter_actor_set_easing_delay                  (ClutterActor               *self,
                                                                                  guint                       msecs);
+CLUTTER_AVAILABLE_IN_1_10
 guint                           clutter_actor_get_easing_delay                  (ClutterActor               *self);
+CLUTTER_AVAILABLE_IN_1_10
 ClutterTransition *             clutter_actor_get_transition                    (ClutterActor               *self,
                                                                                  const char                 *name);
+CLUTTER_AVAILABLE_IN_1_10
+void                            clutter_actor_add_transition                    (ClutterActor               *self,
+                                                                                 const char                 *name,
+                                                                                 ClutterTransition          *transition);
+CLUTTER_AVAILABLE_IN_1_10
+void                            clutter_actor_remove_transition                 (ClutterActor               *self,
+                                                                                 const char                 *name);
+CLUTTER_AVAILABLE_IN_1_10
+void                            clutter_actor_remove_all_transitions            (ClutterActor               *self);
 
 G_END_DECLS
 
diff --git a/clutter/clutter.symbols b/clutter/clutter.symbols
index b0bb3cf..fe583a1 100644
--- a/clutter/clutter.symbols
+++ b/clutter/clutter.symbols
@@ -30,6 +30,7 @@ clutter_actor_add_constraint
 clutter_actor_add_constraint_with_name
 clutter_actor_add_effect
 clutter_actor_add_effect_with_name
+clutter_actor_add_transition
 clutter_actor_align_get_type
 clutter_actor_allocate
 clutter_actor_allocate_align_fill
@@ -194,12 +195,14 @@ clutter_actor_realize
 clutter_actor_remove_action
 clutter_actor_remove_action_by_name
 clutter_actor_remove_all_children
+clutter_actor_remove_all_transitions
 clutter_actor_remove_constraint
 clutter_actor_remove_constraint_by_name
 clutter_actor_remove_child
 clutter_actor_remove_clip
 clutter_actor_remove_effect
 clutter_actor_remove_effect_by_name
+clutter_actor_remove_transition
 clutter_actor_reparent
 clutter_actor_replace_child
 clutter_actor_restore_easing_state
diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt
index df3cd7e..a24926e 100644
--- a/doc/reference/clutter/clutter-sections.txt
+++ b/doc/reference/clutter/clutter-sections.txt
@@ -464,6 +464,9 @@ clutter_actor_get_easing_mode
 clutter_actor_set_easing_delay
 clutter_actor_get_easing_delay
 clutter_actor_get_transition
+clutter_actor_add_transition
+clutter_actor_remove_transition
+clutter_actor_remove_all_transitions
 
 <SUBSECTION>
 clutter_actor_set_reactive



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