/** * VERSION: 6.0 * DATE: 10/1/2009 * AS3 (AS2 is also available) * UPDATES AND DOCUMENTATION AT: http://blog.greensock.com/overwritemanager/ **/ package com.greensock { import com.greensock.core.*; import flash.errors.*; import flash.utils.*; /** * OverwriteManager resolves conflicts between tweens and controls if (and how) existing tweens of the same * target are overwritten. Think of it as a referee or traffic cop for tweens. For example, let's say you have * a button with ROLL_OVER and ROLL_OUT handlers that tween an object's alpha and the user rolls their mouse * over/out/over/out quickly. Most likely, you'd want each new tween to overwrite the other immediately so * that you don't end up with multiple tweens vying for control of the alpha property. That describes * the ALL_IMMEDIATE mode which is the default mode of TweenLite when it is not used in conjunction with * TweenMax, TimelineLite, or TimelineMax. This keeps things small and fast. However, it isn't ideal for * setting up sequences because as soon as you create subsequent tweens of the same target in the sequence, * the previous one gets overwritten. And what if you have a tween that is controling 3 properties and * then you create another tween that only controls one of those properties? You may want the first tween * to continue tweening the other 2 (non-overlapping) properties. This describes the AUTO mode which is * the default whenever TweenMax, TimelineLite, or TimelineMax is used in your swf. OverwriteManager * offers quite a few other modes to choose from in fact: * * * * With the exception of ALL_IMMEDIATE (which performs overwriting immediatly when the tween is created), * all overwriting occurs when a tween renders for the first time. So if your tween has a delay of 1 second, * it will not overwrite any tweens until that point.

* * You can define a default overwriting mode for all tweens using the OverwriteManager.init() method, like:

* * OverwriteManager.init(OverwriteManager.AUTO);

* * If you want to override the default mode in a particular tween, just use the overwrite special * property. You can use the static constant or the corresponding number. The following two lines produce * the same results:

* * TweenMax.to(mc, 1, {x:100, overwrite:OverwriteManager.PREXISTING});
* TweenMax.to(mc, 1, {x:100, overwrite:5});

* * OverwriteManager is a separate, optional class for TweenLite primarily because of file size concerns. * Without initting OverwriteManager, TweenLite can only recognize modes 0 and 1 (NONE and ALL_IMMEDIATE). * However, TweenMax, TimelineLite, and TimelineMax automatically init() OverwriteManager in AUTO mode * unless you have already initted OverwriteManager manually. You do not need to take any additional steps * to use AUTO mode if you're using any of those classes somewhere in your project. Keep in mind too that setting * the default OverwriteManager mode will affect TweenLite and TweenMax tweens.

* * * EXAMPLES:

* * To start OverwriteManager in AUTO mode (the default) and then do a simple TweenLite tween, simply do:

* * import com.greensock.OverwriteManager;
* import com.greensock.TweenLite;

* * OverwriteManager.init(OverwriteManager.AUTO);
* TweenLite.to(mc, 2, {x:300});

* * You can also define overwrite behavior in individual tweens, like so:

* * import com.greensock.OverwriteManager;
* import com.greensock.TweenLite;

* * OverwriteManager.init(2);
* TweenLite.to(mc, 2, {x:"300", y:"100"});
* TweenLite.to(mc, 1, {alpha:0.5, overwrite:1}); //or use the constant OverwriteManager.ALL_IMMEDIATE
* TweenLite.to(mc, 3, {x:200, rotation:30, overwrite:2}); //or use the constant OverwriteManager.AUTO

* * * OverwriteManager's mode can be changed anytime after init() is called, like.

* * OverwriteManager.mode = OverwriteManager.CONCURRENT;

* * Copyright 2010, GreenSock. All rights reserved. This work is subject to the terms in http://www.greensock.com/terms_of_use.html or for corporate Club GreenSock members, the software agreement that was issued with the corporate membership. * * @author Jack Doyle, jack@greensock.com */ public class OverwriteManager { /** @private **/ public static const version:Number = 6.0; /** Won't overwrite any other tweens **/ public static const NONE:int = 0; /** Overwrites all existing tweens of the same target immediately when the tween is created **/ public static const ALL_IMMEDIATE:int = 1; /** Only overwrites individual overlapping tweening properties in other tweens of the same target. TweenMax, TimelineLite, and TimelineMax automatically init() OverwriteManager in this mode if you haven't already called OverwriteManager.init(). **/ public static const AUTO:int = 2; /** Overwrites tweens of the same target that are active when the tween renders for the first time. **/ public static const CONCURRENT:int = 3; /** Overwrites all tweens of the same target (regardless of overlapping properties or timing) when the tween renders for the first time as opposed to ALL_IMMEDIATE which performs overwriting immediately when the tween is created. **/ public static const ALL_ONSTART:int = 4; /** Overwrites tweens of the same target that existed before this tween regardless of their start/end time or active state or overlapping properties. **/ public static const PREEXISTING:int = 5; /** The default overwrite mode for all TweenLite and TweenMax instances **/ public static var mode:int; /** @private **/ public static var enabled:Boolean; /** * Initializes OverwriteManager and sets the default management mode. Options include: * * * @param defaultMode The default mode that OverwriteManager should use. **/ public static function init(defaultMode:int=2):int { if (TweenLite.version < 11.099994) { throw new Error("Warning: Your TweenLite class needs to be updated to work with OverwriteManager (or you may need to clear your ASO files). Please download and install the latest version from http://www.tweenlite.com."); } TweenLite.overwriteManager = OverwriteManager; mode = defaultMode; enabled = true; return mode; } /** * @private * @return Boolean value indicating whether or not properties may have changed on the target when overwriting occurred. For example, when a motionBlur (plugin) is disabled, it swaps out a BitmapData for the target and may alter the alpha. We need to know this in order to determine whether or not the new tween should be re-initted() with the changed properties. **/ public static function manageOverwrites(tween:TweenLite, props:Object, targetTweens:Array, mode:uint):Boolean { var i:int, changed:Boolean, curTween:TweenLite; if (mode >= 4) { var l:uint = targetTweens.length; for (i = 0; i < l; i++) { curTween = targetTweens[i]; if (curTween != tween) { if (curTween.setEnabled(false, false)) { changed = true; } } else if (mode == 5) { break; } } return changed; } var startTime:Number = tween.startTime, overlaps:Array = [], cousins:Array = [], cCount:uint = 0, oCount:uint = 0; i = targetTweens.length; while (i--) { curTween = targetTweens[i]; if (curTween == tween || curTween.gc) { //ignore } else if (curTween.timeline != tween.timeline) { if (!getGlobalPaused(curTween)) { cousins[cCount++] = curTween; } } else if (curTween.startTime <= startTime && curTween.startTime + curTween.totalDuration > startTime && !getGlobalPaused(curTween)) { overlaps[oCount++] = curTween; } } if (cCount != 0) { //tweens that are nested in other timelines may have various offsets and timeScales so we need to translate them to a global/root one to see how they compare. var combinedTimeScale:Number = tween.cachedTimeScale, combinedStartTime:Number = startTime, cousin:TweenCore, cousinStartTime:Number, timeline:SimpleTimeline; timeline = tween.timeline; while (timeline) { combinedTimeScale *= timeline.cachedTimeScale; combinedStartTime += timeline.startTime; timeline = timeline.timeline; } startTime = combinedTimeScale * combinedStartTime; i = cCount; while (i--) { cousin = cousins[i]; combinedTimeScale = cousin.cachedTimeScale; combinedStartTime = cousin.startTime; timeline = cousin.timeline; while (timeline) { combinedTimeScale *= timeline.cachedTimeScale; combinedStartTime += timeline.startTime; timeline = timeline.timeline; } cousinStartTime = combinedTimeScale * combinedStartTime; if (cousinStartTime <= startTime && (cousinStartTime + (cousin.totalDuration * combinedTimeScale) > startTime || cousin.cachedDuration == 0)) { overlaps[oCount++] = cousin; } } } if (oCount == 0) { return changed; } i = oCount; if (mode == 2) { while (i--) { curTween = overlaps[i]; if (curTween.killVars(props)) { changed = true; } if (curTween.cachedPT1 == null && curTween.initted) { curTween.setEnabled(false, false); //if all property tweens have been overwritten, kill the tween. } } } else { while (i--) { if (TweenLite(overlaps[i]).setEnabled(false, false)) { //flags for garbage collection changed = true; } } } return changed; } /** @private **/ public static function getGlobalPaused(tween:TweenCore):Boolean { while (tween) { if (tween.cachedPaused) { return true; } tween = tween.timeline; } return false; } } }