diff --git a/ChangeLog b/ChangeLog index 88035ffdb..5c55c4f98 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-11-15 Emmanuele Bassi <ebassi@openedhand.com> + + * clutter/clutter-timeline.[ch]: Add ClutterTimeline:direction + property, defining the direction (forward or backward) of the + timeline. + + * tests/test-timeline.c: Test the direction property. + + * clutter.symbols: Update exported symbols + 2007-11-15 Emmanuele Bassi <ebassi@openedhand.com> * clutter/clutter-effect.h: diff --git a/clutter.symbols b/clutter.symbols index fa89f8a85..330295895 100644 --- a/clutter.symbols +++ b/clutter.symbols @@ -422,9 +422,12 @@ clutter_texture_has_generated_tiles clutter_texture_is_tiled clutter_timeline_get_type clutter_timeline_new +clutter_timeline_new_for_duration clutter_timeline_clone clutter_timeline_get_speed clutter_timeline_set_speed +clutter_timeline_get_direction +clutter_timeline_set_direction clutter_timeline_start clutter_timeline_pause clutter_timeline_stop @@ -439,6 +442,8 @@ clutter_timeline_get_n_frames clutter_timeline_is_playing clutter_timeline_set_delay clutter_timeline_get_delay +clutter_timeline_set_duration +clutter_timeline_get_duration clutter_timeout_pool_new clutter_timeout_pool_add clutter_timeout_pool_remove diff --git a/clutter/clutter-timeline.c b/clutter/clutter-timeline.c index 9fc6a1637..88dd49fda 100644 --- a/clutter/clutter-timeline.c +++ b/clutter/clutter-timeline.c @@ -49,6 +49,7 @@ #include "clutter-marshal.h" #include "clutter-private.h" #include "clutter-debug.h" +#include "clutter-enum-types.h" G_DEFINE_TYPE (ClutterTimeline, clutter_timeline, G_TYPE_OBJECT); @@ -57,12 +58,15 @@ G_DEFINE_TYPE (ClutterTimeline, clutter_timeline, G_TYPE_OBJECT); struct _ClutterTimelinePrivate { + ClutterTimelineDirection direction; + guint timeout_id; guint delay_id; + gint current_frame_num; + guint fps; guint n_frames; - guint current_frame_num; guint delay; guint duration; @@ -80,7 +84,8 @@ enum PROP_NUM_FRAMES, PROP_LOOP, PROP_DELAY, - PROP_DURATION + PROP_DURATION, + PROP_DIRECTION }; enum @@ -186,6 +191,9 @@ clutter_timeline_set_property (GObject *object, case PROP_DURATION: clutter_timeline_set_duration (timeline, g_value_get_uint (value)); break; + case PROP_DIRECTION: + clutter_timeline_set_direction (timeline, g_value_get_enum (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -221,6 +229,9 @@ clutter_timeline_get_property (GObject *object, case PROP_DURATION: g_value_set_uint (value, priv->duration); break; + case PROP_DIRECTION: + g_value_set_enum (value, priv->direction); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -341,6 +352,22 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) 0, G_MAXUINT, 1000, CLUTTER_PARAM_READWRITE)); + /** + * ClutterTimeline:direction: + * + * The direction of the timeline, either %CLUTTER_TIMELINE_FORWARD or + * %CLUTTER_TIMELINE_BACKWARD. + * + * Since: 0.6 + */ + g_object_class_install_property (object_class, + PROP_DIRECTION, + g_param_spec_enum ("direction", + "Direction", + "Direction of the timeline", + CLUTTER_TYPE_TIMELINE_DIRECTION, + CLUTTER_TIMELINE_FORWARD, + CLUTTER_PARAM_READWRITE)); /** * ClutterTimeline::new-frame: @@ -499,10 +526,16 @@ timeline_timeout_func (gpointer data) priv->last_frame_msecs = msecs; /* Advance frames */ - priv->current_frame_num += n_frames;; + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + priv->current_frame_num += n_frames; + else + priv->current_frame_num -= n_frames; /* Handle loop or stop */ - if (priv->current_frame_num > priv->n_frames) + if (((priv->direction == CLUTTER_TIMELINE_FORWARD) && + (priv->current_frame_num > priv->n_frames)) || + ((priv->direction == CLUTTER_TIMELINE_BACKWARD) && + (priv->current_frame_num < 0))) { guint frame_diff; @@ -513,8 +546,16 @@ timeline_timeout_func (gpointer data) priv->n_frames, n_frames - 1); - frame_diff = priv->current_frame_num - priv->n_frames; - priv->current_frame_num = priv->n_frames; + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + { + frame_diff = priv->current_frame_num - priv->n_frames; + priv->current_frame_num = priv->n_frames; + } + else + { + frame_diff = priv->n_frames - priv->current_frame_num; + priv->current_frame_num = 0; + } /* if we skipped some frame to get here let's see whether we still need * to emit the last new-frame signal with the last frame @@ -699,9 +740,16 @@ clutter_timeline_get_loop (ClutterTimeline *timeline) void clutter_timeline_rewind (ClutterTimeline *timeline) { + ClutterTimelinePrivate *priv; + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); - clutter_timeline_advance (timeline, 0); + priv = timeline->priv; + + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + clutter_timeline_advance (timeline, 0); + else if (priv->direction == CLUTTER_TIMELINE_BACKWARD) + clutter_timeline_advance (timeline, priv->n_frames); } /** @@ -723,8 +771,20 @@ clutter_timeline_skip (ClutterTimeline *timeline, priv->current_frame_num += n_frames; - if (priv->current_frame_num > priv->n_frames) - priv->current_frame_num = 1; + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + { + priv->current_frame_num += n_frames; + + if (priv->current_frame_num > priv->n_frames) + priv->current_frame_num = 1; + } + else if (priv->direction == CLUTTER_TIMELINE_BACKWARD) + { + priv->current_frame_num -= n_frames; + + if (priv->current_frame_num < 1) + priv->current_frame_num = priv->n_frames - 1; + } } /** @@ -744,8 +804,7 @@ clutter_timeline_advance (ClutterTimeline *timeline, priv = timeline->priv; - if (frame_num < priv->n_frames) - priv->current_frame_num = frame_num; + priv->current_frame_num = CLAMP (frame_num, 0, priv->n_frames); } /** @@ -800,12 +859,9 @@ clutter_timeline_set_n_frames (ClutterTimeline *timeline, if (priv->n_frames != n_frames) { - g_object_ref (timeline); - priv->n_frames = n_frames; g_object_notify (G_OBJECT (timeline), "num-frames"); - g_object_unref (timeline); } } @@ -905,6 +961,7 @@ clutter_timeline_clone (ClutterTimeline *timeline) "num-frames", clutter_timeline_get_n_frames (timeline), "loop", clutter_timeline_get_loop (timeline), "delay", clutter_timeline_get_delay (timeline), + "direction", clutter_timeline_get_direction (timeline), NULL); return copy; @@ -1091,6 +1148,60 @@ clutter_timeline_get_progressx (ClutterTimeline *timeline) priv = timeline->priv; - return CLUTTER_FIXED_DIV (CLUTTER_INT_TO_FIXED (priv->current_frame_num), - CLUTTER_INT_TO_FIXED (priv->n_frames)); + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + return CLUTTER_FIXED_DIV (CLUTTER_INT_TO_FIXED (priv->current_frame_num), + CLUTTER_INT_TO_FIXED (priv->n_frames)); + else + return CLUTTER_FIXED_DIV (CLUTTER_INT_TO_FIXED (priv->n_frames), + CLUTTER_INT_TO_FIXED (priv->current_frame_num)); +} + +/** + * clutter_timeline_get_direction: + * @timeline: a #ClutterTimeline + * + * Retrieves the direction of the timeline set with + * clutter_timeline_set_direction(). + * + * Return value: the direction of the timeline + * + * Since: 0.6 + */ +ClutterTimelineDirection +clutter_timeline_get_direction (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), CLUTTER_TIMELINE_FORWARD); + + return timeline->priv->direction; +} + +/** + * clutter_timeline_set_direction: + * @timeline: a #ClutterTimeline + * @direction: the direction of the timeline + * + * Sets the direction of @timeline, either %CLUTTER_TIMELINE_FORWARD or + * %CLUTTER_TIMELINE_BACKWARD. + * + * Since: 0.6 + */ +void +clutter_timeline_set_direction (ClutterTimeline *timeline, + ClutterTimelineDirection direction) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->direction != direction) + { + priv->direction = direction; + + if (priv->current_frame_num == 0) + priv->current_frame_num = priv->n_frames; + + g_object_notify (G_OBJECT (timeline), "direction"); + } } diff --git a/clutter/clutter-timeline.h b/clutter/clutter-timeline.h index 42fd6e000..0a28dc034 100644 --- a/clutter/clutter-timeline.h +++ b/clutter/clutter-timeline.h @@ -55,6 +55,20 @@ G_BEGIN_DECLS (G_TYPE_INSTANCE_GET_CLASS ((obj), \ CLUTTER_TYPE_TIMELINE, ClutterTimelineClass)) +/** + * ClutterTimelineDirection: + * @CLUTTER_TIMELINE_FORWARD: forward direction for a timeline + * @CLUTTER_TIMELINE_BACKWARD: backward direction for a timeline + * + * The direction of a #ClutterTimeline + * + * Since: 0.6 + */ +typedef enum { + CLUTTER_TIMELINE_FORWARD, + CLUTTER_TIMELINE_BACKWARD +} ClutterTimelineDirection; + typedef struct _ClutterTimeline ClutterTimeline; typedef struct _ClutterTimelineClass ClutterTimelineClass; typedef struct _ClutterTimelinePrivate ClutterTimelinePrivate; @@ -89,38 +103,41 @@ struct _ClutterTimelineClass GType clutter_timeline_get_type (void) G_GNUC_CONST; -ClutterTimeline *clutter_timeline_new (guint n_frames, - guint fps); -ClutterTimeline *clutter_timeline_new_for_duration (guint msecs); -ClutterTimeline *clutter_timeline_clone (ClutterTimeline *timeline); +ClutterTimeline *clutter_timeline_new (guint n_frames, + guint fps); +ClutterTimeline *clutter_timeline_new_for_duration (guint msecs); +ClutterTimeline *clutter_timeline_clone (ClutterTimeline *timeline); -guint clutter_timeline_get_duration (ClutterTimeline *timeline); -void clutter_timeline_set_duration (ClutterTimeline *timeline, - guint msecs); -guint clutter_timeline_get_speed (ClutterTimeline *timeline); -void clutter_timeline_set_speed (ClutterTimeline *timeline, - guint fps); -void clutter_timeline_start (ClutterTimeline *timeline); -void clutter_timeline_pause (ClutterTimeline *timeline); -void clutter_timeline_stop (ClutterTimeline *timeline); -void clutter_timeline_set_loop (ClutterTimeline *timeline, - gboolean loop); -gboolean clutter_timeline_get_loop (ClutterTimeline *timeline); -void clutter_timeline_rewind (ClutterTimeline *timeline); -void clutter_timeline_skip (ClutterTimeline *timeline, - guint n_frames); -void clutter_timeline_advance (ClutterTimeline *timeline, - guint frame_num); -gint clutter_timeline_get_current_frame (ClutterTimeline *timeline); -gdouble clutter_timeline_get_progress (ClutterTimeline *timeline); -ClutterFixed clutter_timeline_get_progressx (ClutterTimeline *timeline); -void clutter_timeline_set_n_frames (ClutterTimeline *timeline, - guint n_frames); -guint clutter_timeline_get_n_frames (ClutterTimeline *timeline); -gboolean clutter_timeline_is_playing (ClutterTimeline *timeline); -void clutter_timeline_set_delay (ClutterTimeline *timeline, - guint msecs); -guint clutter_timeline_get_delay (ClutterTimeline *timeline); +guint clutter_timeline_get_duration (ClutterTimeline *timeline); +void clutter_timeline_set_duration (ClutterTimeline *timeline, + guint msecs); +guint clutter_timeline_get_speed (ClutterTimeline *timeline); +void clutter_timeline_set_speed (ClutterTimeline *timeline, + guint fps); +ClutterTimelineDirection clutter_timeline_get_direction (ClutterTimeline *timeline); +void clutter_timeline_set_direction (ClutterTimeline *timeline, + ClutterTimelineDirection direction); +void clutter_timeline_start (ClutterTimeline *timeline); +void clutter_timeline_pause (ClutterTimeline *timeline); +void clutter_timeline_stop (ClutterTimeline *timeline); +void clutter_timeline_set_loop (ClutterTimeline *timeline, + gboolean loop); +gboolean clutter_timeline_get_loop (ClutterTimeline *timeline); +void clutter_timeline_rewind (ClutterTimeline *timeline); +void clutter_timeline_skip (ClutterTimeline *timeline, + guint n_frames); +void clutter_timeline_advance (ClutterTimeline *timeline, + guint frame_num); +gint clutter_timeline_get_current_frame (ClutterTimeline *timeline); +gdouble clutter_timeline_get_progress (ClutterTimeline *timeline); +ClutterFixed clutter_timeline_get_progressx (ClutterTimeline *timeline); +void clutter_timeline_set_n_frames (ClutterTimeline *timeline, + guint n_frames); +guint clutter_timeline_get_n_frames (ClutterTimeline *timeline); +gboolean clutter_timeline_is_playing (ClutterTimeline *timeline); +void clutter_timeline_set_delay (ClutterTimeline *timeline, + guint msecs); +guint clutter_timeline_get_delay (ClutterTimeline *timeline); G_END_DECLS diff --git a/doc/reference/ChangeLog b/doc/reference/ChangeLog index cc1d8d779..dfc687a56 100644 --- a/doc/reference/ChangeLog +++ b/doc/reference/ChangeLog @@ -1,3 +1,7 @@ +2007-11-15 Emmanuele Bassi <ebassi@openedhand.com> + + * clutter-sections.txt: Add new ClutterTimeline API + 2007-11-15 Emmanuele Bassi <ebassi@openedhand.com> * clutter-sections.txt: Add new ClutterEffectTemplate constructor. diff --git a/doc/reference/clutter-sections.txt b/doc/reference/clutter-sections.txt index 7d83700b7..dd9b9ce52 100644 --- a/doc/reference/clutter-sections.txt +++ b/doc/reference/clutter-sections.txt @@ -484,23 +484,36 @@ clutter_perspective_get_type ClutterTimeline ClutterTimelineClass clutter_timeline_new +clutter_timeline_new_for_duration clutter_timeline_clone + +<SUBSECTION> clutter_timeline_set_speed clutter_timeline_get_speed +clutter_timeline_set_duration +clutter_timeline_get_duration +clutter_timeline_set_loop +clutter_timeline_get_loop +clutter_timeline_set_n_frames +clutter_timeline_get_n_frames +clutter_timeline_set_delay +clutter_timeline_get_delay +ClutterTimelineDirection +clutter_timeline_set_direction +clutter_timeline_get_direction + +<SUBSECTION clutter_timeline_start clutter_timeline_pause clutter_timeline_stop -clutter_timeline_set_loop -clutter_timeline_get_loop clutter_timeline_rewind clutter_timeline_skip clutter_timeline_advance clutter_timeline_get_current_frame -clutter_timeline_set_n_frames -clutter_timeline_get_n_frames +clutter_timeline_get_progress +clutter_timeline_get_progressx clutter_timeline_is_playing -clutter_timeline_set_delay -clutter_timeline_get_delay + <SUBSECTION Standard> CLUTTER_TIMELINE CLUTTER_IS_TIMELINE diff --git a/tests/test-timeline.c b/tests/test-timeline.c index 9b2b74caa..506b23cb9 100644 --- a/tests/test-timeline.c +++ b/tests/test-timeline.c @@ -48,8 +48,11 @@ main (int argc, char **argv) clutter_init (&argc, &argv); timeline_1 = clutter_timeline_new (10, 120); + timeline_2 = clutter_timeline_clone (timeline_1); + timeline_3 = clutter_timeline_clone (timeline_1); + clutter_timeline_set_direction (timeline_3, CLUTTER_TIMELINE_BACKWARD); g_signal_connect (timeline_1, "new-frame", G_CALLBACK (timeline_1_new_frame_cb),