summaryrefslogtreecommitdiff
path: root/clutter/clutter-timeline.c
diff options
context:
space:
mode:
authorNeil Roberts <neil@linux.intel.com>2009-06-11 10:55:52 +0100
committerNeil Roberts <neil@linux.intel.com>2009-06-11 11:46:41 +0100
commit9021aa2909189becd9809d29ebf8c9a3c362ce5f (patch)
tree8f45f19579a853ba2c80c6c09eafedc0daf544a4 /clutter/clutter-timeline.c
parent6bb5b3a13e6dfe1934c9d2476f00ac2be86d33cd (diff)
downloadclutter-9021aa2909189becd9809d29ebf8c9a3c362ce5f.tar.gz
Revert "[timeline] Don't clamp the elapsed time when a looping tl reaches the end"
This reverts commit 9c5663d6717722d6d77162060f284355b5081174. The patch was causing problems for applications that expect the elapsed_time to be at either end of the timeline when the completed signal is fired. For example test-behave swaps the direction of the timeline in the completed handler but if the time has overflowed the end then the timeline would only take a short time to get back the beginning. This caused the animation to just vibrate around the beginning.
Diffstat (limited to 'clutter/clutter-timeline.c')
-rw-r--r--clutter/clutter-timeline.c142
1 files changed, 49 insertions, 93 deletions
diff --git a/clutter/clutter-timeline.c b/clutter/clutter-timeline.c
index d10e9ec6e..2d68bc5d1 100644
--- a/clutter/clutter-timeline.c
+++ b/clutter/clutter-timeline.c
@@ -430,76 +430,22 @@ clutter_timeline_init (ClutterTimeline *self)
priv->elapsed_time = 0;
}
-static gboolean
-have_passed_time (ClutterTimeline *timeline,
- gint new_time,
- gint msecs)
-{
- ClutterTimelinePrivate *priv = timeline->priv;
-
- /* Ignore markers that are outside the duration of the timeline */
- if (msecs < 0 || msecs > priv->duration)
- return FALSE;
-
- if (priv->direction == CLUTTER_TIMELINE_FORWARD)
- {
- /* We need to special case when a marker is added at the
- beginning of the timeline */
- if (msecs == 0 &&
- priv->msecs_delta > 0 &&
- new_time - priv->msecs_delta <= 0)
- return TRUE;
-
- /* If the timeline is looping then we need to check for wrap
- around */
- if (priv->loop && new_time >= priv->duration)
- return (msecs > new_time - priv->msecs_delta ||
- msecs <= new_time % priv->duration);
-
- /* Otherwise it's just a simple test if the time is in range of
- the previous time and the new time */
- return (msecs > new_time - priv->msecs_delta
- && msecs <= new_time);
- }
- else
- {
- /* We need to special case when a marker is added at the
- end of the timeline */
- if (msecs == priv->duration &&
- priv->msecs_delta > 0 &&
- new_time + priv->msecs_delta >= priv->duration)
- return TRUE;
-
- /* If the timeline is looping then we need to check for wrap
- around */
- if (priv->loop && new_time <= 0)
- return (msecs < new_time + priv->msecs_delta ||
- msecs >= (priv->duration -
- (-new_time % priv->duration)));
-
- /* Otherwise it's just a simple test if the time is in range of
- the previous time and the new time */
- return (msecs >= new_time
- && msecs < new_time + priv->msecs_delta);
- }
-}
-
-struct CheckIfMarkerHitClosure
-{
- ClutterTimeline *timeline;
- gint new_time;
-};
-
static void
check_if_marker_hit (const gchar *name,
TimelineMarker *marker,
- struct CheckIfMarkerHitClosure *data)
+ ClutterTimeline *timeline)
{
- if (have_passed_time (data->timeline, data->new_time, marker->msecs))
+ ClutterTimelinePrivate *priv = timeline->priv;
+
+ if (priv->direction == CLUTTER_TIMELINE_FORWARD
+ ? (marker->msecs > priv->elapsed_time - priv->msecs_delta
+ && marker->msecs <= priv->elapsed_time)
+ : (marker->msecs >= priv->elapsed_time
+ && marker->msecs < priv->elapsed_time + priv->msecs_delta))
{
CLUTTER_NOTE (SCHEDULER, "Marker '%s' reached", name);
- g_signal_emit (data->timeline, timeline_signals[MARKER_REACHED],
+ g_signal_emit (timeline, timeline_signals[MARKER_REACHED],
marker->quark,
name,
marker->msecs);
@@ -507,12 +453,10 @@ check_if_marker_hit (const gchar *name,
}
static void
-emit_frame_signal (ClutterTimeline *timeline, gint new_time)
+emit_frame_signal (ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
- struct CheckIfMarkerHitClosure data;
- /* Emit the signal */
g_signal_emit (timeline, timeline_signals[NEW_FRAME], 0,
priv->elapsed_time);
@@ -520,12 +464,9 @@ emit_frame_signal (ClutterTimeline *timeline, gint new_time)
if (priv->markers_by_name == NULL)
return;
- data.timeline = timeline;
- data.new_time = new_time;
-
g_hash_table_foreach (priv->markers_by_name,
(GHFunc) check_if_marker_hit,
- &data);
+ timeline);
}
static gboolean
@@ -586,7 +527,7 @@ clutter_timeline_do_frame (ClutterTimeline *timeline)
if (!is_complete (timeline))
{
/* Emit the signal */
- emit_frame_signal (timeline, priv->elapsed_time);
+ emit_frame_signal (timeline);
/* Signal pauses timeline ? */
if (!priv->is_playing)
@@ -601,31 +542,29 @@ clutter_timeline_do_frame (ClutterTimeline *timeline)
else
{
/* Handle loop or stop */
+ ClutterTimelineDirection saved_direction = priv->direction;
+ guint overflow_msecs = priv->elapsed_time;
gint end_msecs;
- gint overflow_msecs = priv->elapsed_time;
/* Update the current elapsed time in case the signal handlers
- * want to take a peek */
- if (priv->loop)
- {
- /* We try and interpolate smoothly around a loop */
- if (priv->direction == CLUTTER_TIMELINE_FORWARD)
- priv->elapsed_time = priv->elapsed_time % priv->duration;
- else
- priv->elapsed_time = (priv->duration -
- (-priv->elapsed_time % priv->duration));
- }
- else if (priv->direction == CLUTTER_TIMELINE_FORWARD)
- priv->elapsed_time = priv->duration;
+ * want to take a peek. If we clamp elapsed time, then we need
+ * to correpondingly reduce msecs_delta to reflect the correct
+ * range of times */
+ if (priv->direction == CLUTTER_TIMELINE_FORWARD)
+ {
+ priv->msecs_delta -= (priv->elapsed_time - priv->duration);
+ priv->elapsed_time = priv->duration;
+ }
else if (priv->direction == CLUTTER_TIMELINE_BACKWARD)
- priv->elapsed_time = 0;
+ {
+ priv->msecs_delta -= - priv->elapsed_time;
+ priv->elapsed_time = 0;
+ }
end_msecs = priv->elapsed_time;
- /* Check if the markers have been hit using the old value of
- elapsed time so it will use the right value for the previous
- elapsed time */
- emit_frame_signal (timeline, overflow_msecs);
+ /* Emit the signal */
+ emit_frame_signal (timeline);
/* Did the signal handler modify the elapsed time? */
if (priv->elapsed_time != end_msecs)
@@ -670,11 +609,28 @@ clutter_timeline_do_frame (ClutterTimeline *timeline)
return TRUE;
}
- if (!priv->loop)
- clutter_timeline_rewind (timeline);
+ if (priv->loop)
+ {
+ /* We try and interpolate smoothly around a loop */
+ if (saved_direction == CLUTTER_TIMELINE_FORWARD)
+ priv->elapsed_time = overflow_msecs - priv->duration;
+ else
+ priv->elapsed_time = priv->duration + overflow_msecs;
+
+ /* Or if the direction changed, we try and bounce */
+ if (priv->direction != saved_direction)
+ priv->elapsed_time = priv->duration - priv->elapsed_time;
- g_object_unref (timeline);
- return priv->loop;
+ g_object_unref (timeline);
+ return TRUE;
+ }
+ else
+ {
+ clutter_timeline_rewind (timeline);
+
+ g_object_unref (timeline);
+ return FALSE;
+ }
}
}