From 18c86dd4b879378b3ec12d6959cee6723e39dd6a Mon Sep 17 00:00:00 2001 From: Jack Doyle Date: Mon, 2 Sep 2013 21:51:05 -0500 Subject: [PATCH] 12.0.15 - Improved handling of situations where a tween/timeline is added to a timeline that was already finished (it needs to resume playback intuitively). - Fixed an issue that could cause a timeline's rawTime() to be reported incorrectly in a very rare situation. --- bower.json | 2 +- src/com/greensock/TimelineLite.as | 46 +++++++++++++++++++++++++------ src/com/greensock/TimelineMax.as | 33 ++++++++++++++++++++-- src/com/greensock/TweenLite.as | 8 +++--- src/com/greensock/TweenMax.as | 6 ++-- 5 files changed, 75 insertions(+), 20 deletions(-) diff --git a/bower.json b/bower.json index cfb92ea..8e3830a 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "gsap", - "version": "12.0.14", + "version": "12.0.15", "description": "GreenSock Animation Platform (GSAP) is a suite of high-performance AS3 classes for scripted animation (also available in JavaScript and AS2), including TweenLite, TweenMax, TimelineLite, TimelineMax, various easing equations, and plugins for things like animating along Bezier paths, filters, etc. See http://www.greensock.com/ for details.", "author": { "name": "Jack Doyle", diff --git a/src/com/greensock/TimelineLite.as b/src/com/greensock/TimelineLite.as index 81346c0..c8d7636 100755 --- a/src/com/greensock/TimelineLite.as +++ b/src/com/greensock/TimelineLite.as @@ -1,6 +1,6 @@ /** - * VERSION: 12.0.14 - * DATE: 2013-07-27 + * VERSION: 12.0.15 + * DATE: 2013-09-02 * AS3 (AS2 version is also available) * UPDATES AND DOCS AT: http://www.greensock.com/timelinelite/ **/ @@ -268,6 +268,33 @@ var nested = new TimelineLite(); nested.to(mc2, 1, {x:200})); tl.add(nested); + * + * How do timelines work? What are the mechanics like? + *

Every animation (tween and timeline) is placed on a parent timeline (except the 2 root timelines - there's one for normal tweens and another for "useFrames" ones). + * In a sense, they all have their own playheads (that's what its "time" refers to, or "totalTime" which is identical except that it includes repeats and repeatDelays) + * but generally they're not independent because they're sitting on a timeline whose playhead moves. + * When the parent's playhead moves to a new position, it updates the childrens' too.

+ * + *

When a timeline renders at a particular time, it loops through its children and says "okay, you should render as if your playhead is at ____" and if that child + * is a timeline with children, it does the same to its children, right on down the line.

+ * + *

The only exception is when the tween/timeline is paused in which case its internal playhead acts like it's "locked". So in that case, + * it's possible (likely in fact) that the child's playhead would not be synced with the parent's. + * When you unpause it (resume()), it essentially picks it up and moves it so that its internal playhead + * is synchronized with wherever the parent's playhead is at that moment, thus things play perfectly smoothly. + * That is, unless the timeline's smoothChildTiming is to false in which case it won't move - + * its startTime will remain locked to where it was.

+ * + *

So basically, when smoothChildTiming is true, the engine will rearrange things on + * the fly to ensure the playheads line up so that playback is seamless and smooth. The same thing happens when you reverse() + * or alter the timeScale, etc. But sometimes you might not want that behavior - you prefer to have tight + * control over exactly where your tweens line up in the timeline - that's when smoothChildTiming:false is handy.

+ * + *

One more example: let's say you've got a 10-second tween that's just sitting on the root timeline and you're 2-seconds into the tween. + * Let's assume it started at exactly 0 on the root to make this easy, and then when it's at 2-seconds, you do tween.seek(5). + * The playhead of the root isn't affected - it keeps going exactly as it always did, but in order to make that tween jump to 5 seconds + * and play appropriately, the tween's startTime gets changed to -3. That way, the tween's playhead and the root + * playhead are perfectly aligned.

* *

Copyright 2008-2013, GreenSock. All rights reserved. This work is subject to the terms in http://www.greensock.com/terms_of_use.html or for Club GreenSock members, the software agreement that was issued with the membership.

* @@ -276,7 +303,7 @@ tl.add(nested); **/ public class TimelineLite extends SimpleTimeline { /** @private **/ - public static const version:String = "12.0.14"; + public static const version:String = "12.0.15"; /** @private **/ protected var _labels:Object; @@ -1211,7 +1238,7 @@ tl.add([tween1, tween2, tween3], "+=2", "sequence", 0.5); } else if (typeof(value) === "function") { value = TweenLite.delayedCall(0, value); } else { - trace("Cannot add " + value + " into the TimelineLite/Max: it is neither a tween, timeline, function, nor a String."); + trace("Cannot add " + value + " into the TimelineLite/Max: it is not a tween, timeline, function, or string."); return this; } } @@ -1219,12 +1246,13 @@ tl.add([tween1, tween2, tween3], "+=2", "sequence", 0.5); super.add(value, position); //if the timeline has already ended but the inserted tween/timeline extends the duration, we should enable this timeline again so that it renders properly. - if (_gc) if (!_paused) if (_time === _duration) if (_time < duration()) { + if (_gc) if (!_paused) if (_duration < duration()) { //in case any of the anscestors had completed but should now be enabled... - var tl:SimpleTimeline = this; + var tl:SimpleTimeline = this, + beforeRawTime:Boolean = (tl.rawTime() > value._startTime); //if the tween is placed on the timeline so that it starts BEFORE the current rawTime, we should align the playhead (move the timeline). This is because sometimes users will create a timeline, let it finish, and much later append a tween and expect it to run instead of jumping to its end state. While technically one could argue that it should jump to its end state, that's not what users intuitively expect. while (tl._gc && tl._timeline) { - if (tl._timeline.smoothChildTiming) { - tl.totalTime(tl._totalTime, true); //also enables them + if (tl._timeline.smoothChildTiming && beforeRawTime) { + tl.totalTime(tl._totalTime, true); //moves the timeline (shifts its startTime) if necessary, and also enables it. } else { tl._enabled(true, false); } @@ -1957,7 +1985,7 @@ myAnimation.totalDuration( 20 ); //adjusts the timeScale so that myAnimation fit * @return The totalTime of the timeline without capping the number at the totalDuration (max) and zero (minimum) */ override public function rawTime():Number { - return (_paused || (_totalTime !== 0 && _totalTime !== _totalDuration)) ? _totalTime : (_timeline.rawTime() - _startTime) * _timeScale; + return _paused ? _totalTime : (_timeline.rawTime() - _startTime) * _timeScale; } diff --git a/src/com/greensock/TimelineMax.as b/src/com/greensock/TimelineMax.as index 8d88960..5370a41 100755 --- a/src/com/greensock/TimelineMax.as +++ b/src/com/greensock/TimelineMax.as @@ -1,6 +1,6 @@ /** - * VERSION: 12.0.14 - * DATE: 2013-07-27 + * VERSION: 12.0.15 + * DATE: 2013-09-02 * AS3 (AS2 version is also available) * UPDATES AND DOCS AT: http://www.greensock.com/timelinemax/ **/ @@ -353,6 +353,33 @@ var nested = new TimelineMax(); nested.to(mc2, 1, {x:200})); tl.add(nested); + * + * How do timelines work? What are the mechanics like? + *

Every animation (tween and timeline) is placed on a parent timeline (except the 2 root timelines - there's one for normal tweens and another for "useFrames" ones). + * In a sense, they all have their own playheads (that's what its "time" refers to, or "totalTime" which is identical except that it includes repeats and repeatDelays) + * but generally they're not independent because they're sitting on a timeline whose playhead moves. + * When the parent's playhead moves to a new position, it updates the childrens' too.

+ * + *

When a timeline renders at a particular time, it loops through its children and says "okay, you should render as if your playhead is at ____" and if that child + * is a timeline with children, it does the same to its children, right on down the line.

+ * + *

The only exception is when the tween/timeline is paused in which case its internal playhead acts like it's "locked". So in that case, + * it's possible (likely in fact) that the child's playhead would not be synced with the parent's. + * When you unpause it (resume()), it essentially picks it up and moves it so that its internal playhead + * is synchronized with wherever the parent's playhead is at that moment, thus things play perfectly smoothly. + * That is, unless the timeline's smoothChildTiming is to false in which case it won't move - + * its startTime will remain locked to where it was.

+ * + *

So basically, when smoothChildTiming is true, the engine will rearrange things on + * the fly to ensure the playheads line up so that playback is seamless and smooth. The same thing happens when you reverse() + * or alter the timeScale, etc. But sometimes you might not want that behavior - you prefer to have tight + * control over exactly where your tweens line up in the timeline - that's when smoothChildTiming:false is handy.

+ * + *

One more example: let's say you've got a 10-second tween that's just sitting on the root timeline and you're 2-seconds into the tween. + * Let's assume it started at exactly 0 on the root to make this easy, and then when it's at 2-seconds, you do tween.seek(5). + * The playhead of the root isn't affected - it keeps going exactly as it always did, but in order to make that tween jump to 5 seconds + * and play appropriately, the tween's startTime gets changed to -3. That way, the tween's playhead and the root + * playhead are perfectly aligned.

* *

Copyright 2008-2013, GreenSock. All rights reserved. This work is subject to the terms in http://www.greensock.com/terms_of_use.html or for Club GreenSock members, the software agreement that was issued with the membership.

* @@ -361,7 +388,7 @@ tl.add(nested); **/ public class TimelineMax extends TimelineLite implements IEventDispatcher { /** @private **/ - public static const version:String = "12.0.14"; + public static const version:String = "12.0.15"; /** @private **/ protected static var _listenerLookup:Object = {onCompleteListener:TweenEvent.COMPLETE, onUpdateListener:TweenEvent.UPDATE, onStartListener:TweenEvent.START, onRepeatListener:TweenEvent.REPEAT, onReverseCompleteListener:TweenEvent.REVERSE_COMPLETE}; /** @private **/ diff --git a/src/com/greensock/TweenLite.as b/src/com/greensock/TweenLite.as index 75aeb08..a704b09 100755 --- a/src/com/greensock/TweenLite.as +++ b/src/com/greensock/TweenLite.as @@ -1,6 +1,6 @@ /** - * VERSION: 12.0.14 - * DATE: 2013-07-27 + * VERSION: 12.0.15 + * DATE: 2013-09-02 * AS3 (AS2 version is also available) * UPDATES AND DOCS AT: http://www.greensock.com **/ @@ -304,7 +304,7 @@ package com.greensock { public class TweenLite extends Animation { /** @private **/ - public static const version:String = "12.0.14"; + public static const version:String = "12.0.15"; /** Provides An easy way to change the default easing equation. Choose from any of the GreenSock eases in the com.greensock.easing package. @default Power1.easeOut **/ public static var defaultEase:Ease = new Ease(null, null, 1, 1); @@ -570,7 +570,7 @@ package com.greensock { /** @private Loops through the vars properties, captures starting values, triggers overwriting if necessary, etc. **/ protected function _initProps(target:Object, propLookup:Object, siblings:Array, overwrittenProps:Object):Boolean { - var vars = this.vars, + var vars:Object = this.vars, p:String, i:int, initPlugins:Boolean, plugin:Object, val:Object; if (target == null) { return false; diff --git a/src/com/greensock/TweenMax.as b/src/com/greensock/TweenMax.as index 144ffd1..ab6e2a3 100755 --- a/src/com/greensock/TweenMax.as +++ b/src/com/greensock/TweenMax.as @@ -1,6 +1,6 @@ /** - * VERSION: 12.0.14 - * DATE: 2013-07-29 + * VERSION: 12.0.15 + * DATE: 2013-09-02 * AS3 (AS2 version is also available) * UPDATES AND DOCS AT: http://www.greensock.com **/ @@ -530,7 +530,7 @@ package com.greensock { */ public class TweenMax extends TweenLite implements IEventDispatcher { /** @private **/ - public static const version:String = "12.0.14"; + public static const version:String = "12.0.15"; TweenPlugin.activate([