diff --git a/ChangeLog b/ChangeLog index 7986be529..31bcd1b36 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,19 @@ +2007-10-16 Emmanuele Bassi + + * clutter/clutter-timeline.[ch]: Added ClutterTimeline:duration, + a property for setting the duration of a timeline in milliseconds. + The property comes with accessors and a new constructor. The + frame rate used is the default value. + + * clutter/clutter-private.h: + * clutter/clutter-main.[ch]: Add clutter_get_default_frame_rate() + and clutter_set_default_frame_rate(); these two functions control + the default frame rate to be used when creating timelines. Currently + is set to 60 frames-per-second. + 2007-10-16 Tomas Frydrych - * build/msvc_2k5 + * build/msvc_2k5: Added MSVC project files. 2007-10-16 Emmanuele bassi diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 47c69ac20..0ce8dbe8b 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -650,7 +650,7 @@ clutter_get_debug_enabled (void) #endif } -ClutterMainContext* +ClutterMainContext * clutter_context_get_default (void) { if (G_UNLIKELY(!ClutterCntx)) @@ -760,6 +760,8 @@ pre_parse_hook (GOptionContext *context, clutter_context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ()); pango_ft2_font_map_set_resolution (clutter_context->font_map, 96.0, 96.0); + clutter_context->frame_rate = 60; + clutter_context->actor_hash = g_hash_table_new (NULL, NULL); backend = clutter_context->backend; @@ -777,7 +779,6 @@ pre_parse_hook (GOptionContext *context, } #endif /* CLUTTER_ENABLE_DEBUG */ - env_string = g_getenv ("CLUTTER_SHOW_FPS"); if (env_string) clutter_show_fps = TRUE; @@ -1133,8 +1134,9 @@ event_click_count_generate (ClutterEvent *event) } } -static void -deliver_event (ClutterEvent *event, ClutterActor *source) +static inline void +deliver_event (ClutterEvent *event, + ClutterActor *source) { #define MAX_EVENT_DEPTH 512 @@ -1150,8 +1152,8 @@ deliver_event (ClutterEvent *event, ClutterActor *source) lock = TRUE; /* Guard against reentrancy */ /* Sorry Mr Bassi. */ - if (event_tree == NULL) - event_tree = g_new0(ClutterActor*, MAX_EVENT_DEPTH); + if (G_UNLIKELY (event_tree == NULL)) + event_tree = g_new0 (ClutterActor *, MAX_EVENT_DEPTH); actor = source; @@ -1166,21 +1168,23 @@ deliver_event (ClutterEvent *event, ClutterActor *source) } /* Capture */ - for (i=n_tree_events-1; i >= 0; i--) - if (clutter_actor_event (event_tree[i], event, TRUE)) - goto done; + for (i = n_tree_events-1; i >= 0; i--) + if (clutter_actor_event (event_tree[i], event, TRUE)) + goto done; /* Bubble */ - for (i=0; i < n_tree_events; i++) + for (i = 0; i < n_tree_events; i++) if (clutter_actor_event (event_tree[i], event, FALSE)) goto done; - done: +done: - for (i=0; i < n_tree_events; i++) + for (i = 0; i < n_tree_events; i++) g_object_unref (event_tree[i]); lock = FALSE; + +#undef MAX_EVENT_DEPTH } /** @@ -1239,7 +1243,7 @@ clutter_do_event (ClutterEvent *event) { ClutterActor *actor = NULL; - actor = clutter_stage_get_key_focus (CLUTTER_STAGE(stage)); + actor = clutter_stage_get_key_focus (CLUTTER_STAGE (stage)); g_return_if_fail (actor != NULL); @@ -1276,6 +1280,8 @@ clutter_do_event (ClutterEvent *event) actor = _clutter_do_pick (CLUTTER_STAGE (stage), x, y, CLUTTER_PICK_REACTIVE); + if (!actor) + break; /* FIXME: for an optimisation should check if there are * actually any reactive actors and avoid the pick all togeather @@ -1285,8 +1291,6 @@ clutter_do_event (ClutterEvent *event) CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p", x, y, actor); - g_return_if_fail (actor != NULL); - if (event->type == CLUTTER_SCROLL) event->scroll.source = actor; else @@ -1382,3 +1386,23 @@ clutter_base_init (void) } } +guint +clutter_get_default_frame_rate (void) +{ + ClutterMainContext *context; + + context = clutter_context_get_default (); + + return context->frame_rate; +} + +void +clutter_set_default_frame_rate (guint frames_per_sec) +{ + ClutterMainContext *context; + + context = clutter_context_get_default (); + + if (context->frame_rate != frames_per_sec) + context->frame_rate = frames_per_sec; +} diff --git a/clutter/clutter-main.h b/clutter/clutter-main.h index d4e985e40..0ebe6490a 100644 --- a/clutter/clutter-main.h +++ b/clutter/clutter-main.h @@ -100,10 +100,11 @@ guint clutter_threads_add_timeout_full (gint priority, gpointer data, GDestroyNotify notify); -void clutter_enable_motion_events (gboolean enable); - -gboolean clutter_get_motion_events_enabled (void); +void clutter_enable_motion_events (gboolean enable); +gboolean clutter_get_motion_events_enabled (void); +guint clutter_get_default_frame_rate (void); +void clutter_set_default_frame_rate (guint frames_per_sec); G_END_DECLS diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index f2fda45ff..2de3a87cc 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -83,6 +83,8 @@ struct _ClutterMainContext gint num_reactives; /* Num of reactive actors */ GHashTable *actor_hash; /* Hash of all actors mapped to id */ + + guint frame_rate; /* Default FPS */ }; #define CLUTTER_CONTEXT() (clutter_context_get_default ()) diff --git a/clutter/clutter-timeline.c b/clutter/clutter-timeline.c index adc9ed265..51a25d2e7 100644 --- a/clutter/clutter-timeline.c +++ b/clutter/clutter-timeline.c @@ -64,6 +64,7 @@ struct _ClutterTimelinePrivate guint n_frames; guint current_frame_num; guint delay; + guint duration; gulong last_frame_msecs; gulong start_frame_secs; @@ -78,7 +79,8 @@ enum PROP_FPS, PROP_NUM_FRAMES, PROP_LOOP, - PROP_DELAY + PROP_DELAY, + PROP_DURATION }; enum @@ -124,7 +126,7 @@ timeout_add (guint interval, { guint res; - if (timeline_use_pool) + if (G_LIKELY (timeline_use_pool)) { g_assert (timeline_pool != NULL); res = clutter_timeout_pool_add (timeline_pool, @@ -144,7 +146,7 @@ timeout_add (guint interval, static void timeout_remove (guint tag) { - if (timeline_use_pool) + if (G_LIKELY (timeline_use_pool)) { g_assert (timeline_pool != NULL); clutter_timeout_pool_remove (timeline_pool, tag); @@ -181,6 +183,9 @@ clutter_timeline_set_property (GObject *object, case PROP_DELAY: priv->delay = g_value_get_uint (value); break; + case PROP_DURATION: + clutter_timeline_set_duration (timeline, g_value_get_uint (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -213,6 +218,9 @@ clutter_timeline_get_property (GObject *object, case PROP_DELAY: g_value_set_uint (value, priv->delay); break; + case PROP_DURATION: + g_value_set_uint (value, priv->duration); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -274,8 +282,8 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) "Frames Per Second", "Timeline frames per second", 1, 1000, - 50, - G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE)); + 60, + CLUTTER_PARAM_READWRITE)); /** * ClutterTimeline:num-frames: * @@ -288,7 +296,7 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) "Timelines total number of frames", 1, G_MAXUINT, 1, - G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE)); + CLUTTER_PARAM_READWRITE)); /** * ClutterTimeline:loop: * @@ -300,7 +308,7 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) "Loop", "Should the timeline automatically restart", FALSE, - G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE)); + CLUTTER_PARAM_READWRITE)); /** * ClutterTimeline:delay: * @@ -316,7 +324,23 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) "Delay before start", 0, G_MAXUINT, 0, - G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE)); + CLUTTER_PARAM_READWRITE)); + /** + * ClutterTimeline:duration: + * + * Duration of the timeline in milliseconds, depending on the + * ClutterTimeline:fps value. + * + * Since: 0.6 + */ + g_object_class_install_property (object_class, + PROP_DURATION, + g_param_spec_uint ("duration", + "Duration", + "Duration of the timeline in milliseconds", + 0, G_MAXUINT, + 1000, + CLUTTER_PARAM_READWRITE)); /** * ClutterTimeline::new-frame: @@ -389,6 +413,9 @@ clutter_timeline_init (ClutterTimeline *self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_TIMELINE, ClutterTimelinePrivate); + + self->priv->fps = clutter_get_default_frame_rate (); + self->priv->n_frames = 0; } static gboolean @@ -562,6 +589,9 @@ clutter_timeline_start (ClutterTimeline *timeline) if (priv->delay_id || priv->timeout_id) return; + if (priv->n_frames == 0) + return; + if (priv->delay) { priv->delay_id = timeout_add (priv->delay, @@ -880,6 +910,26 @@ clutter_timeline_clone (ClutterTimeline *timeline) return copy; } +/** + * clutter_timeline_new_for_duration: + * @msecs: Duration of the timeline in milliseconds + * + * Creates a new #ClutterTimeline with a duration of @msecs using + * the value of the ClutterTimeline:fps property to compute the + * equivalent number of frames. + * + * Return value: the newly created #ClutterTimeline + * + * Since: 0.6 + */ +ClutterTimeline * +clutter_timeline_new_for_duration (guint msecs) +{ + return g_object_new (CLUTTER_TYPE_TIMELINE, + "duration", msecs, + NULL); +} + /** * clutter_timeline_new: * @n_frames: the number of frames @@ -946,3 +996,102 @@ clutter_timeline_set_delay (ClutterTimeline *timeline, g_object_notify (G_OBJECT (timeline), "delay"); } } + +/** + * clutter_timeline_get_duration: + * @timeline: a #ClutterTimeline + * + * Retrieves the duration of a #ClutterTimeline in milliseconds. + * See clutter_timeline_set_duration(). + * + * Return value: the duration of the timeline, in milliseconds. + * + * Since: 0.6 + */ +guint +clutter_timeline_get_duration (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + return timeline->priv->duration; +} + +/** + * clutter_timeline_set_duration: + * @timeline: a #ClutterTimeline + * @msecs: duration of the timeline in milliseconds + * + * Sets the duration of the timeline, in milliseconds. The speed + * of the timeline depends on the ClutterTimeline:fps setting. + * + * Since: 0.6 + */ +void +clutter_timeline_set_duration (ClutterTimeline *timeline, + guint msecs) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->duration != msecs) + { + g_object_ref (timeline); + + g_object_freeze_notify (G_OBJECT (timeline)); + + priv->duration = msecs; + + priv->n_frames = priv->duration / 1000 + * priv->fps; + + g_object_notify (G_OBJECT (timeline), "num-frames"); + g_object_notify (G_OBJECT (timeline), "duration"); + + g_object_thaw_notify (G_OBJECT (timeline)); + g_object_unref (timeline); + } +} + +/** + * clutter_timeline_get_progress: + * @timeline: a #ClutterTimeline + * + * The position of the timeline in a [0, 1] interval. + * + * Return value: the position of the timeline. + * + * Since: 0.6 + */ +gdouble +clutter_timeline_get_progress (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0.); + + return CLUTTER_FIXED_TO_DOUBLE (clutter_timeline_get_progressx (timeline)); +} + +/** + * clutter_timeline_get_progressx: + * @timeline: a #ClutterTimeline + * + * Fixed point version of clutter_timeline_get_progress(). + * + * Return value: the position of the timeline as a fixed point value + * + * Since: 0.6 + */ +ClutterFixed +clutter_timeline_get_progressx (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + priv = timeline->priv; + + return CLUTTER_FIXED_DIV (CLUTTER_INT_TO_FIXED (priv->current_frame_num), + CLUTTER_INT_TO_FIXED (priv->n_frames)); +} diff --git a/clutter/clutter-timeline.h b/clutter/clutter-timeline.h index 2932a9d70..42fd6e000 100644 --- a/clutter/clutter-timeline.h +++ b/clutter/clutter-timeline.h @@ -29,6 +29,7 @@ /* clutter-timeline.h */ #include +#include G_BEGIN_DECLS @@ -90,8 +91,12 @@ 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); +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); @@ -107,6 +112,8 @@ void clutter_timeline_skip (ClutterTimeline *timeline, 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);