OverwriteManager.as 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /**
  2. * VERSION: 6.02
  3. * DATE: 2010-04-03
  4. * AS3 (AS2 is also available)
  5. * UPDATES AND DOCUMENTATION AT: http://www.greensock.com/overwritemanager/
  6. **/
  7. package com.greensock {
  8. import com.greensock.core.*;
  9. import flash.errors.*;
  10. import flash.utils.*;
  11. /**
  12. * OverwriteManager resolves conflicts between tweens and controls if (and how) existing tweens of the same
  13. * target are overwritten. Think of it as a referee or traffic cop for tweens. For example, let's say you have
  14. * a button with <code>ROLL_OVER</code> and <code>ROLL_OUT</code> handlers that tween an object's alpha and the user rolls their mouse
  15. * over/out/over/out quickly. Most likely, you'd want each new tween to overwrite the other immediately so
  16. * that you don't end up with multiple tweens vying for control of the alpha property. That describes
  17. * the <code>ALL_IMMEDIATE</code> mode which is the default mode of TweenLite when it is not used in conjunction with
  18. * TweenMax, TimelineLite, or TimelineMax. This keeps things small and fast. However, it isn't ideal for
  19. * setting up sequences because as soon as you create subsequent tweens of the same target in the sequence,
  20. * the previous one gets overwritten. And what if you have a tween that is controling 3 properties and
  21. * then you create another tween that only controls one of those properties? You may want the first tween
  22. * to continue tweening the other 2 (non-overlapping) properties. This describes the <code>AUTO</code> mode which is
  23. * the default whenever TweenMax, TimelineLite, or TimelineMax is used in your swf. OverwriteManager
  24. * offers quite a few other modes to choose from in fact:
  25. *
  26. * <ul>
  27. * <li><b> NONE (0):</b>
  28. * <ol>
  29. * <li><b>When:</b> Never</li>
  30. * <li><b>Finds:</b> Nothing</li>
  31. * <li><b>Kills:</b> Nothing</li>
  32. * <li><b>Performance:</b> Excellent</li>
  33. * <li><b>Good for:</b> When you know that your tweens won't conflict and you want maximum speed.</li>
  34. * </ol>
  35. * </li>
  36. *
  37. * <li><b> ALL_IMMEDIATE (1):</b>
  38. * <ol>
  39. * <li><b>When:</b> Immediately when the tween is created.</li>
  40. * <li><b>Finds:</b> All tweens of the same target (regardless of timing or overlapping properties).</li>
  41. * <li><b>Kills:</b> Every tween found</li>
  42. * <li><b>Performance:</b> Excellent</li>
  43. * <li><b>Good for:</b> When you want the tween to take priority over all other tweens of the
  44. * same target, like on button rollovers/rollouts. However, this mode is
  45. * bad for setting up sequences.</li>
  46. * </ol>
  47. * This is the default mode for TweenLite unless TweenMax, TimelineLite,
  48. * or TimelineMax are used in the SWF (in which case <code>AUTO</code> is the default mode).
  49. * </li>
  50. *
  51. * <li><b> AUTO (2):</b>
  52. * <ol>
  53. * <li><b>When:</b> The first time the tween renders (you can <code>invalidate()</code> a tween to force it
  54. * to re-init and run its overwriting routine again next time it renders)</li>
  55. * <li><b>Finds:</b> Only tweens of the same target that are active (running). Tweens that haven't started yet are immune.</li>
  56. * <li><b>Kills:</b> Only individual overlapping tweening properties. If all tweening properties
  57. * have been overwritten, the entire tween will be killed as well.</li>
  58. * <li><b>Performance:</b> Very good when there aren't many overlapping tweens; fair when there are.</li>
  59. * <li><b>Good for:</b> Virtually all situations. This mode does the best job overall of handling
  60. * overwriting in an intuitive way and is excellent for sequencing. </li>
  61. * </ol>
  62. * This is the default mode when TweenMax, TimelineLite, or TimelineMax is used in your swf (those classes
  63. * automatically init() OverwriteManager in <code>AUTO</code> mode unless you have already initted OverwriteManager manually).
  64. * </li>
  65. *
  66. * <li><b> CONCURRENT (3):</b>
  67. * <ol>
  68. * <li><b>When:</b> The first time the tween renders (you can <code>invalidate()</code> a tween to force it
  69. * to re-init and run its overwriting routine again next time it renders)</li>
  70. * <li><b>Finds:</b> Only tweens of the same target that are active (running). Tweens that haven't started yet are immune.</li>
  71. * <li><b>Kills:</b> Every tween found</li>
  72. * <li><b>Performance:</b> Very good</li>
  73. * <li><b>Good for:</b> When you want the target object to only be controled by one tween at a time. Good
  74. * for sequencing although AUTO mode is typically better because it will only kill
  75. * individual overlapping properties instead of entire tweens.</li>
  76. * </ol>
  77. * </li>
  78. *
  79. * <li><b> ALL_ONSTART (4):</b>
  80. * <ol>
  81. * <li><b>When:</b> The first time the tween renders (you can <code>invalidate()</code> a tween to force it
  82. * to re-init and run its overwriting routine again next time it renders)</li>
  83. * <li><b>Finds:</b> All tweens of the same target (regardless of timing or overlapping properties).</li>
  84. * <li><b>Kills:</b> Every tween found</li>
  85. * <li><b>Performance:</b> Very good</li>
  86. * <li><b>Good for:</b> When you want a tween to take priority and wipe out all other tweens of the
  87. * same target even if they start later. This mode is rarely used.</li>
  88. * </ol>
  89. * </li>
  90. *
  91. * <li><b> PREEXISTING (5):</b>
  92. * <ol>
  93. * <li><b>When:</b> The first time the tween renders (you can <code>invalidate()</code> a tween to force it
  94. * to re-init and run its overwriting routine again next time it renders)</li>
  95. * <li><b>Finds:</b> Only the tweens of the same target that were created before this tween was created
  96. * (regardless of timing or overlapping properties). Virtually identical to <code>ALL_IMMEDIATE</code>
  97. * except that <code>PREEXISTING</code> doesn't run its overwriting routines until it renders for the
  98. * first time, meaning that if it has a delay, other tweens won't be overwritten until the delay expires.</li>
  99. * <li><b>Kills:</b> Every tween found</li>
  100. * <li><b>Performance:</b> Very good</li>
  101. * <li><b>Good for:</b> When the order in which your code runs plays a critical role, like when tweens
  102. * that you create later should always take precidence over previously created ones
  103. * regardless of when they're scheduled to run. If <code>ALL_IMMEDIATE</code> is great except
  104. * that you want to wait on overwriting until the tween begins, <code>PREEXISTING</code> is perfect.</li>
  105. * </ol>
  106. * </li>
  107. * </ul>
  108. *
  109. * With the exception of <code>ALL_IMMEDIATE</code> (which performs overwriting immediatly when the tween is created),
  110. * all overwriting occurs when a tween renders for the first time. So if your tween has a delay of 1 second,
  111. * it will not overwrite any tweens until that point. <br /><br />
  112. *
  113. * You can define a default overwriting mode for all tweens using the <code>OverwriteManager.init()</code> method, like:<br /><br /><code>
  114. *
  115. * OverwriteManager.init(OverwriteManager.AUTO);<br /><br /></code>
  116. *
  117. * If you want to override the default mode in a particular tween, just use the <code>overwrite</code> special
  118. * property. You can use the static constant or the corresponding number. The following two lines produce
  119. * the same results:<br /><br /><code>
  120. *
  121. * TweenMax.to(mc, 1, {x:100, overwrite:OverwriteManager.PREXISTING});<br />
  122. * TweenMax.to(mc, 1, {x:100, overwrite:5});<br /><br /></code>
  123. *
  124. * OverwriteManager is a separate, optional class for TweenLite primarily because of file size concerns.
  125. * Without initting OverwriteManager, TweenLite can only recognize modes 0 and 1 (<code>NONE</code> and <code>ALL_IMMEDIATE</code>).
  126. * However, TweenMax, TimelineLite, and TimelineMax automatically init() OverwriteManager in <code>AUTO</code> mode
  127. * unless you have already initted OverwriteManager manually. You do not need to take any additional steps
  128. * to use AUTO mode if you're using any of those classes somewhere in your project. Keep in mind too that setting
  129. * the default OverwriteManager mode will affect TweenLite and TweenMax tweens.<br /><br />
  130. *
  131. *
  132. * <b>EXAMPLES:</b><br /><br />
  133. *
  134. * To start OverwriteManager in <code>AUTO</code> mode (the default) and then do a simple TweenLite tween, simply do:<br /><br /><code>
  135. *
  136. * import com.greensock.OverwriteManager;<br />
  137. * import com.greensock.TweenLite;<br /><br />
  138. *
  139. * OverwriteManager.init(OverwriteManager.AUTO);<br />
  140. * TweenLite.to(mc, 2, {x:300});<br /><br /></code>
  141. *
  142. * You can also define overwrite behavior in individual tweens, like so:<br /><br /><code>
  143. *
  144. * import com.greensock.OverwriteManager;<br />
  145. * import com.greensock.TweenLite;<br /><br />
  146. *
  147. * OverwriteManager.init(2);<br />
  148. * TweenLite.to(mc, 2, {x:"300", y:"100"});<br />
  149. * TweenLite.to(mc, 1, {alpha:0.5, overwrite:1}); //or use the constant OverwriteManager.ALL_IMMEDIATE<br />
  150. * TweenLite.to(mc, 3, {x:200, rotation:30, overwrite:2}); //or use the constant OverwriteManager.AUTO<br /><br /></code>
  151. *
  152. *
  153. * OverwriteManager's mode can be changed anytime after init() is called, like.<br /><br /><code>
  154. *
  155. * OverwriteManager.mode = OverwriteManager.CONCURRENT;<br /><br /></code>
  156. *
  157. * <b>Copyright 2010, GreenSock. All rights reserved.</b> This work is subject to the terms in <a href="http://www.greensock.com/terms_of_use.html">http://www.greensock.com/terms_of_use.html</a> or for corporate Club GreenSock members, the software agreement that was issued with the corporate membership.
  158. *
  159. * @author Jack Doyle, jack@greensock.com
  160. */
  161. public class OverwriteManager {
  162. /** @private **/
  163. public static const version:Number = 6.02;
  164. /** Won't overwrite any other tweens **/
  165. public static const NONE:int = 0;
  166. /** Overwrites all existing tweens of the same target immediately when the tween is created **/
  167. public static const ALL_IMMEDIATE:int = 1;
  168. /** 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(). **/
  169. public static const AUTO:int = 2;
  170. /** Overwrites tweens of the same target that are active when the tween renders for the first time. **/
  171. public static const CONCURRENT:int = 3;
  172. /** 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. **/
  173. public static const ALL_ONSTART:int = 4;
  174. /** Overwrites tweens of the same target that existed before this tween regardless of their start/end time or active state or overlapping properties. **/
  175. public static const PREEXISTING:int = 5;
  176. /** The default overwrite mode for all TweenLite and TweenMax instances **/
  177. public static var mode:int;
  178. /** @private **/
  179. public static var enabled:Boolean;
  180. /**
  181. * Initializes OverwriteManager and sets the default management mode. Options include:
  182. * <ul>
  183. * <li><b> NONE (0):</b>
  184. * <ol>
  185. * <li><b>When:</b> Never</li>
  186. * <li><b>Finds:</b> Nothing</li>
  187. * <li><b>Kills:</b> Nothing</li>
  188. * <li><b>Performance:</b> Excellent</li>
  189. * <li><b>Good for:</b> When you know that your tweens won't conflict and you want maximum speed.</li>
  190. * </ol>
  191. * </li>
  192. *
  193. * <li><b> ALL_IMMEDIATE (1):</b>
  194. * <ol>
  195. * <li><b>When:</b> Immediately when the tween is created.</li>
  196. * <li><b>Finds:</b> All tweens of the same target (regardless of timing or overlapping properties).</li>
  197. * <li><b>Kills:</b> Every tween found</li>
  198. * <li><b>Performance:</b> Excellent</li>
  199. * <li><b>Good for:</b> When you want the tween to take priority over all other tweens of the
  200. * same target, like on button rollovers/rollouts. However, this mode is
  201. * bad for setting up sequences.</li>
  202. * </ol>
  203. * This is the default mode for TweenLite unless TweenMax, TimelineLite,
  204. * or TimelineMax are used in the SWF (in which case <code>AUTO</code> is the default mode).
  205. * </li>
  206. *
  207. * <li><b> AUTO (2):</b>
  208. * <ol>
  209. * <li><b>When:</b> The first time the tween renders (you can <code>invalidate()</code> a tween to force it
  210. * to re-init and run its overwriting routine again next time it renders)</li>
  211. * <li><b>Finds:</b> Only tweens of the same target that are active (running). Tweens that haven't started yet are immune.</li>
  212. * <li><b>Kills:</b> Only individual overlapping tweening properties. If all tweening properties
  213. * have been overwritten, the entire tween will be killed as well.</li>
  214. * <li><b>Performance:</b> Very good when there aren't many overlapping tweens; fair when there are.</li>
  215. * <li><b>Good for:</b> Virtually all situations. This mode does the best job overall of handling
  216. * overwriting in an intuitive way and is excellent for sequencing. </li>
  217. * </ol>
  218. * This is the default mode when TweenMax, TimelineLite, or TimelineMax is used in your swf (those classes
  219. * automatically init() OverwriteManager in <code>AUTO</code> mode unless you have already initted OverwriteManager manually).
  220. * </li>
  221. *
  222. * <li><b> CONCURRENT (3):</b>
  223. * <ol>
  224. * <li><b>When:</b> The first time the tween renders (you can <code>invalidate()</code> a tween to force it
  225. * to re-init and run its overwriting routine again next time it renders)</li>
  226. * <li><b>Finds:</b> Only tweens of the same target that are active (running). Tweens that haven't started yet are immune.</li>
  227. * <li><b>Kills:</b> Every tween found</li>
  228. * <li><b>Performance:</b> Very good</li>
  229. * <li><b>Good for:</b> When you want the target object to only be controled by one tween at a time. Good
  230. * for sequencing although AUTO mode is typically better because it will only kill
  231. * individual overlapping properties instead of entire tweens.</li>
  232. * </ol>
  233. * </li>
  234. *
  235. * <li><b> ALL_ONSTART (4):</b>
  236. * <ol>
  237. * <li><b>When:</b> The first time the tween renders (you can <code>invalidate()</code> a tween to force it
  238. * to re-init and run its overwriting routine again next time it renders)</li>
  239. * <li><b>Finds:</b> All tweens of the same target (regardless of timing or overlapping properties).</li>
  240. * <li><b>Kills:</b> Every tween found</li>
  241. * <li><b>Performance:</b> Very good</li>
  242. * <li><b>Good for:</b> When you want a tween to take priority and wipe out all other tweens of the
  243. * same target even if they start later. This mode is rarely used.</li>
  244. * </ol>
  245. * </li>
  246. *
  247. * <li><b> PREEXISTING (5):</b>
  248. * <ol>
  249. * <li><b>When:</b> The first time the tween renders (you can <code>invalidate()</code> a tween to force it
  250. * to re-init and run its overwriting routine again next time it renders)</li>
  251. * <li><b>Finds:</b> Only the tweens of the same target that were created before this tween was created
  252. * (regardless of timing or overlapping properties). Virtually identical to <code>ALL_IMMEDIATE</code>
  253. * except that <code>PREEXISTING</code> doesn't run its overwriting routines until it renders for the
  254. * first time, meaning that if it has a delay, other tweens won't be overwritten until the delay expires.</li>
  255. * <li><b>Kills:</b> Every tween found</li>
  256. * <li><b>Performance:</b> Very good</li>
  257. * <li><b>Good for:</b> When the order in which your code runs plays a critical role, like when tweens
  258. * that you create later should always take precidence over previously created ones
  259. * regardless of when they're scheduled to run. If <code>ALL_IMMEDIATE</code> is great except
  260. * that you want to wait on overwriting until the tween begins, <code>PREEXISTING</code> is perfect.</li>
  261. * </ol>
  262. * </li>
  263. * </ul>
  264. *
  265. * @param defaultMode The default mode that OverwriteManager should use.
  266. **/
  267. public static function init(defaultMode:int=2):int {
  268. if (TweenLite.version < 11.1) {
  269. 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.");
  270. }
  271. TweenLite.overwriteManager = OverwriteManager;
  272. mode = defaultMode;
  273. enabled = true;
  274. return mode;
  275. }
  276. /**
  277. * @private
  278. * @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.
  279. **/
  280. public static function manageOverwrites(tween:TweenLite, props:Object, targetTweens:Array, mode:uint):Boolean {
  281. var i:int, changed:Boolean, curTween:TweenLite;
  282. if (mode >= 4) {
  283. var l:uint = targetTweens.length;
  284. for (i = 0; i < l; i++) {
  285. curTween = targetTweens[i];
  286. if (curTween != tween) {
  287. if (curTween.setEnabled(false, false)) {
  288. changed = true;
  289. }
  290. } else if (mode == 5) {
  291. break;
  292. }
  293. }
  294. return changed;
  295. }
  296. //NOTE: Add 0.0000000001 to overcome floating point errors that can cause the startTime to be VERY slightly off (when a tween's currentTime property is set for example)
  297. var startTime:Number = tween.cachedStartTime + 0.0000000001, overlaps:Array = [], cousins:Array = [], cCount:uint = 0, oCount:uint = 0;
  298. i = targetTweens.length;
  299. while (--i > -1) {
  300. curTween = targetTweens[i];
  301. if (curTween == tween || curTween.gc) {
  302. //ignore
  303. } else if (curTween.timeline != tween.timeline) {
  304. if (!getGlobalPaused(curTween)) {
  305. cousins[cCount++] = curTween;
  306. }
  307. } else if (curTween.cachedStartTime <= startTime && curTween.cachedStartTime + curTween.totalDuration + 0.0000000001 > startTime && !getGlobalPaused(curTween)) {
  308. overlaps[oCount++] = curTween;
  309. }
  310. }
  311. 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.
  312. var combinedTimeScale:Number = tween.cachedTimeScale, combinedStartTime:Number = startTime, cousin:TweenCore, cousinStartTime:Number, timeline:SimpleTimeline;
  313. timeline = tween.timeline;
  314. while (timeline) {
  315. combinedTimeScale *= timeline.cachedTimeScale;
  316. combinedStartTime += timeline.cachedStartTime;
  317. timeline = timeline.timeline;
  318. }
  319. startTime = combinedTimeScale * combinedStartTime;
  320. i = cCount;
  321. while (--i > -1) {
  322. cousin = cousins[i];
  323. combinedTimeScale = cousin.cachedTimeScale;
  324. combinedStartTime = cousin.cachedStartTime;
  325. timeline = cousin.timeline;
  326. while (timeline) {
  327. combinedTimeScale *= timeline.cachedTimeScale;
  328. combinedStartTime += timeline.cachedStartTime;
  329. timeline = timeline.timeline;
  330. }
  331. cousinStartTime = combinedTimeScale * combinedStartTime;
  332. if (cousinStartTime <= startTime && (cousinStartTime + (cousin.totalDuration * combinedTimeScale) + 0.0000000001 > startTime || cousin.cachedDuration == 0)) {
  333. overlaps[oCount++] = cousin;
  334. }
  335. }
  336. }
  337. if (oCount == 0) {
  338. return changed;
  339. }
  340. i = oCount;
  341. if (mode == 2) {
  342. while (--i > -1) {
  343. curTween = overlaps[i];
  344. if (curTween.killVars(props)) {
  345. changed = true;
  346. }
  347. if (curTween.cachedPT1 == null && curTween.initted) {
  348. curTween.setEnabled(false, false); //if all property tweens have been overwritten, kill the tween.
  349. }
  350. }
  351. } else {
  352. while (--i > -1) {
  353. if (TweenLite(overlaps[i]).setEnabled(false, false)) { //flags for garbage collection
  354. changed = true;
  355. }
  356. }
  357. }
  358. return changed;
  359. }
  360. /** @private **/
  361. public static function getGlobalPaused(tween:TweenCore):Boolean {
  362. while (tween) {
  363. if (tween.cachedPaused) {
  364. return true;
  365. }
  366. tween = tween.timeline;
  367. }
  368. return false;
  369. }
  370. }
  371. }