diff --git a/clutter/Makefile.am b/clutter/Makefile.am index fff949bec..c47681625 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -123,6 +123,7 @@ source_h = \ $(srcdir)/clutter-text.h \ $(srcdir)/clutter-text-buffer.h \ $(srcdir)/clutter-timeline.h \ + $(srcdir)/clutter-transition-group.h \ $(srcdir)/clutter-transition.h \ $(srcdir)/clutter-types.h \ $(srcdir)/clutter-units.h \ @@ -203,6 +204,7 @@ source_c = \ $(srcdir)/clutter-texture.c \ $(srcdir)/clutter-text.c \ $(srcdir)/clutter-text-buffer.c \ + $(srcdir)/clutter-transition-group.c \ $(srcdir)/clutter-transition.c \ $(srcdir)/clutter-timeline.c \ $(srcdir)/clutter-units.c \ diff --git a/clutter/clutter-transition-group.c b/clutter/clutter-transition-group.c new file mode 100644 index 000000000..1b8e664bb --- /dev/null +++ b/clutter/clutter-transition-group.c @@ -0,0 +1,257 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Emmanuele Bassi + */ + +/** + * SECTION:clutter-transition-group + * @Title: ClutterTransitionGroup + * @Short_Description: Group transitions together + * + * The #ClutterTransitionGroup allows running multiple #ClutterTransition + * instances concurrently. + * + * The transitions inside a group will run within the boundaries of the + * group; for instance, if a transition has a duration of 10 seconds, and + * the group that contains it has a duration of 5 seconds, only the first + * 5 seconds of the transition will be played. + * + * #ClutterTransitionGroup is available since Clutter 1.12 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-transition-group.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +struct _ClutterTransitionGroupPrivate +{ + GHashTable *transitions; +}; + +G_DEFINE_TYPE (ClutterTransitionGroup, clutter_transition_group, CLUTTER_TYPE_TRANSITION) + +static void +clutter_transition_group_new_frame (ClutterTimeline *timeline, + gint elapsed) +{ + ClutterTransitionGroupPrivate *priv; + GHashTableIter iter; + gpointer element; + gint64 msecs; + + priv = CLUTTER_TRANSITION_GROUP (timeline)->priv; + + /* get the time elapsed since the last ::new-frame... */ + msecs = clutter_timeline_get_delta (timeline); + + g_hash_table_iter_init (&iter, priv->transitions); + while (g_hash_table_iter_next (&iter, &element, NULL)) + { + ClutterTimeline *t = element; + + /* ... and advance every timeline */ + clutter_timeline_set_direction (t, clutter_timeline_get_direction (timeline)); + clutter_timeline_set_duration (t, clutter_timeline_get_duration (timeline)); + + _clutter_timeline_advance (t, msecs); + } +} + +static void +clutter_transition_group_attached (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + ClutterTransitionGroupPrivate *priv; + GHashTableIter iter; + gpointer element; + + priv = CLUTTER_TRANSITION_GROUP (transition)->priv; + + g_hash_table_iter_init (&iter, priv->transitions); + while (g_hash_table_iter_next (&iter, &element, NULL)) + { + ClutterTransition *t = element; + + clutter_transition_set_animatable (t, animatable); + } +} + +static void +clutter_transition_group_detached (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + ClutterTransitionGroupPrivate *priv; + GHashTableIter iter; + gpointer element; + + priv = CLUTTER_TRANSITION_GROUP (transition)->priv; + + g_hash_table_iter_init (&iter, priv->transitions); + while (g_hash_table_iter_next (&iter, &element, NULL)) + { + ClutterTransition *t = element; + + clutter_transition_set_animatable (t, NULL); + } +} + +static void +clutter_transition_group_started (ClutterTimeline *timeline) +{ + ClutterTransitionGroupPrivate *priv; + GHashTableIter iter; + gpointer element; + + priv = CLUTTER_TRANSITION_GROUP (timeline)->priv; + + g_hash_table_iter_init (&iter, priv->transitions); + while (g_hash_table_iter_next (&iter, &element, NULL)) + { + ClutterTransition *t = element; + + g_signal_emit_by_name (t, "started"); + } +} + +static void +clutter_transition_group_finalize (GObject *gobject) +{ + ClutterTransitionGroupPrivate *priv; + + priv = CLUTTER_TRANSITION_GROUP (gobject)->priv; + + g_hash_table_unref (priv->transitions); + + G_OBJECT_CLASS (clutter_transition_group_parent_class)->finalize (gobject); +} + +static void +clutter_transition_group_class_init (ClutterTransitionGroupClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterTimelineClass *timeline_class = CLUTTER_TIMELINE_CLASS (klass); + ClutterTransitionClass *transition_class = CLUTTER_TRANSITION_CLASS (klass); + + g_type_class_add_private (klass, sizeof (ClutterTransitionGroupPrivate)); + + gobject_class->finalize = clutter_transition_group_finalize; + + timeline_class->started = clutter_transition_group_started; + timeline_class->new_frame = clutter_transition_group_new_frame; + + transition_class->attached = clutter_transition_group_attached; + transition_class->detached = clutter_transition_group_detached; +} + +static void +clutter_transition_group_init (ClutterTransitionGroup *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + CLUTTER_TYPE_TRANSITION_GROUP, + ClutterTransitionGroupPrivate); + + self->priv->transitions = + g_hash_table_new_full (NULL, NULL, (GDestroyNotify) g_object_unref, NULL); +} + +/** + * clutter_transition_group_new: + * + * Creates a new #ClutterTransitionGroup instance. + * + * Return value: the newly created #ClutterTransitionGroup. Use + * g_object_unref() when done to deallocate the resources it + * uses + * + * Since: 1.12 + */ +ClutterTransition * +clutter_transition_group_new (void) +{ + return g_object_new (CLUTTER_TYPE_TRANSITION_GROUP, NULL); +} + +/** + * clutter_transition_group_add_transition: + * @group: a #ClutterTransitionGroup + * @transition: a #ClutterTransition + * + * Adds @transition to @group. + * + * This function acquires a reference on @transition that will be released + * when calling clutter_transition_group_remove_transition(). + * + * Since: 1.12 + */ +void +clutter_transition_group_add_transition (ClutterTransitionGroup *group, + ClutterTransition *transition) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group)); + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + + g_hash_table_add (group->priv->transitions, g_object_ref (transition)); +} + +/** + * clutter_transition_group_remove_transition: + * @group: a #ClutterTransitionGroup + * @transition: a #ClutterTransition + * + * Removes @transition from @group. + * + * This function releases the reference acquired on @transition when + * calling clutter_transition_group_add_transition(). + * + * Since: 1.12 + */ +void +clutter_transition_group_remove_transition (ClutterTransitionGroup *group, + ClutterTransition *transition) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group)); + + g_hash_table_remove (group->priv->transitions, transition); +} + +/** + * clutter_transition_group_remove_all: + * @group: a #ClutterTransitionGroup + * + * Removes all transitions from @group. + * + * This function releases the reference acquired when calling + * clutter_transition_group_add_transition(). + * + * Since: 1.12 + */ +void +clutter_transition_group_remove_all (ClutterTransitionGroup *group) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group)); + + g_hash_table_remove_all (group->priv->transitions); +} diff --git a/clutter/clutter-transition-group.h b/clutter/clutter-transition-group.h new file mode 100644 index 000000000..efa9ddb22 --- /dev/null +++ b/clutter/clutter-transition-group.h @@ -0,0 +1,91 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_TRANSITION_GROUP_H__ +#define __CLUTTER_TRANSITION_GROUP_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TRANSITION_GROUP (clutter_transition_group_get_type ()) +#define CLUTTER_TRANSITION_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSITION_GROUP, ClutterTransitionGroup)) +#define CLUTTER_IS_TRANSITION_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TRANSITION_GROUP)) +#define CLUTTER_TRANSITION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TRANSITION_GROUP, ClutterTransitionGroupClass)) +#define CLUTTER_IS_TRANSITION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TRANSITION_GROUP)) +#define CLUTTER_TRANSITION_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TRANSITION_GROUP, ClutterTransitionGroup)) + +typedef struct _ClutterTransitionGroupPrivate ClutterTransitionGroupPrivate; +typedef struct _ClutterTransitionGroupClass ClutterTransitionGroupClass; + +/** + * ClutterTransitionGroup: + * + * The ClutterTransitionGroup structure contains + * private data and should only be accessed using the provided API. + * + * Since: 1.12 + */ +struct _ClutterTransitionGroup +{ + /*< private >*/ + ClutterTransition parent_instance; + + ClutterTransitionGroupPrivate *priv; +}; + +/** + * ClutterTransitionGroupClass: + * + * The ClutterTransitionGroupClass structure + * contains only private data. + * + * Since: 1.12 + */ +struct _ClutterTransitionGroupClass +{ + /*< private >*/ + ClutterTransitionClass parent_class; + + gpointer _padding[8]; +}; + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_transition_group_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterTransition * clutter_transition_group_new (void); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_group_add_transition (ClutterTransitionGroup *group, + ClutterTransition *transition); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_group_remove_transition (ClutterTransitionGroup *group, + ClutterTransition *transition); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_group_remove_all (ClutterTransitionGroup *group); + +G_END_DECLS + +#endif /* __CLUTTER_TRANSITION_GROUP_H__ */ diff --git a/clutter/clutter-types.h b/clutter/clutter-types.h index fdfaafdaf..00c89d920 100644 --- a/clutter/clutter-types.h +++ b/clutter/clutter-types.h @@ -59,15 +59,16 @@ typedef struct _ClutterActorIter ClutterActorIter; typedef struct _ClutterPaintNode ClutterPaintNode; typedef struct _ClutterContent ClutterContent; /* dummy */ -typedef struct _ClutterAlpha ClutterAlpha; -typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy */ -typedef struct _ClutterAnimator ClutterAnimator; -typedef struct _ClutterInterval ClutterInterval; -typedef struct _ClutterState ClutterState; -typedef struct _ClutterTimeline ClutterTimeline; -typedef struct _ClutterTransition ClutterTransition; +typedef struct _ClutterAlpha ClutterAlpha; +typedef struct _ClutterAnimator ClutterAnimator; +typedef struct _ClutterState ClutterState; +typedef struct _ClutterInterval ClutterInterval; +typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy */ +typedef struct _ClutterTimeline ClutterTimeline; +typedef struct _ClutterTransition ClutterTransition; typedef struct _ClutterPropertyTransition ClutterPropertyTransition; typedef struct _ClutterKeyframeTransition ClutterKeyframeTransition; +typedef struct _ClutterTransitionGroup ClutterTransitionGroup; typedef struct _ClutterAction ClutterAction; typedef struct _ClutterConstraint ClutterConstraint; diff --git a/clutter/clutter.h b/clutter/clutter.h index a42d656fc..9e494949e 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -102,6 +102,7 @@ #include "clutter-texture.h" #include "clutter-text.h" #include "clutter-timeline.h" +#include "clutter-transition-group.h" #include "clutter-transition.h" #include "clutter-units.h" #include "clutter-version.h" diff --git a/clutter/clutter.symbols b/clutter/clutter.symbols index 1c671ea5f..fc1e63194 100644 --- a/clutter/clutter.symbols +++ b/clutter/clutter.symbols @@ -1415,6 +1415,11 @@ clutter_timeline_stop clutter_timeout_pool_add clutter_timeout_pool_new clutter_timeout_pool_remove +clutter_transition_group_add_transition +clutter_transition_group_get_type +clutter_transition_group_new +clutter_transition_group_remove_transition +clutter_transition_group_remove_all clutter_transition_get_animatable clutter_transition_get_interval clutter_transition_get_type diff --git a/doc/reference/clutter/clutter-docs.xml.in b/doc/reference/clutter/clutter-docs.xml.in index 556edce81..ee00b76ae 100644 --- a/doc/reference/clutter/clutter-docs.xml.in +++ b/doc/reference/clutter/clutter-docs.xml.in @@ -155,6 +155,7 @@ + diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 226844b92..915b5b4aa 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -3243,3 +3243,23 @@ CLUTTER_KEYFRAME_TRANSITION_GET_CLASS ClutterKeyframeTransitionPrivate clutter_keyframe_transition_get_type + +
+clutter-transition-group +ClutterTransitionGroup +ClutterTransitionGroupClass +clutter_transition_group_new +clutter_transition_group_add_transition +clutter_transition_group_remove_transition +clutter_transition_group_remove_all + +CLUTTER_TYPE_TRANSITION_GROUP +CLUTTER_TRANSITION_GROUP +CLUTTER_TRANSITION_GROUP_CLASS +CLUTTER_IS_TRANSITION_GROUP +CLUTTER_IS_TRANSITION_GROUP_CLASS +CLUTTER_TRANSITION_GROUP_GET_CLASS + +ClutterTransitionGroupPrivate +clutter_transition_group_get_type +
diff --git a/doc/reference/clutter/clutter.types b/doc/reference/clutter/clutter.types index f94fc394c..cae6764ca 100644 --- a/doc/reference/clutter/clutter.types +++ b/doc/reference/clutter/clutter.types @@ -73,3 +73,4 @@ clutter_text_get_type clutter_texture_get_type clutter_timeline_get_type clutter_transition_get_type +clutter_transition_group_get_type diff --git a/tests/interactive/test-keyframe-transition.c b/tests/interactive/test-keyframe-transition.c index aeef54885..07b628d00 100644 --- a/tests/interactive/test-keyframe-transition.c +++ b/tests/interactive/test-keyframe-transition.c @@ -32,15 +32,16 @@ test_keyframe_transition_main (int argc, char *argv[]) for (i = 0; i < 3; i++) { - ClutterTransition *transition; + ClutterTransition *transition, *group; ClutterActor *rect; float cur_x, cur_y; - float new_x; + float new_x, new_y; cur_x = PADDING; cur_y = PADDING + ((SIZE + PADDING) * i); new_x = clutter_actor_get_width (stage) - PADDING - SIZE; + new_y = g_random_double_range (PADDING, clutter_actor_get_height (stage) - PADDING - SIZE); rect = clutter_actor_new (); @@ -53,6 +54,10 @@ test_keyframe_transition_main (int argc, char *argv[]) clutter_actor_set_easing_duration (rect, 2000); clutter_actor_set_easing_mode (rect, CLUTTER_LINEAR); + group = clutter_transition_group_new (); + clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (group), 1); + clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (group), TRUE); + transition = clutter_keyframe_transition_new ("x"); clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_x); clutter_transition_set_to (transition, G_TYPE_FLOAT, new_x); @@ -60,11 +65,21 @@ test_keyframe_transition_main (int argc, char *argv[]) clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition), G_TYPE_FLOAT, 1, 0.5, new_x / 2.0f, CLUTTER_EASE_OUT_EXPO); + clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition); + g_object_unref (transition); - clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), 1); - clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); + transition = clutter_keyframe_transition_new ("y"); + clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_y); + clutter_transition_set_to (transition, G_TYPE_FLOAT, cur_y); - clutter_actor_add_transition (rect, "horizAnimation", transition); + clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition), + G_TYPE_FLOAT, 1, + 0.5, new_y, CLUTTER_EASE_OUT_EXPO); + clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition); + g_object_unref (transition); + + clutter_actor_add_transition (rect, "rectAnimation", group); + g_object_unref (group); clutter_actor_restore_easing_state (rect); }