package flare.animate { import flare.util.Vectors; /** * Transition that runs multiple transitions simultaneously (in parallel). * The duration of this parallel transition is computed as the maximum * total duration (duration + delay) among the sub-transitions. If the * duration is explicitly set, the sub-transition lengths will be * uniformly scaled to fit within the new time span. */ public class Parallel extends Transition { // -- Properties ------------------------------------------------------ /** Array of parallel transitions */ protected var _trans:Vector. = new Vector.(); /** @private */ protected var _equidur:Boolean; /** @private */ protected var _dirty:Boolean = false; /** @private */ protected var _autodur:Boolean = true; /** * If true, the duration of this sequence is automatically determined * by the longest sub-transition. This is the default behavior. */ public function get autoDuration():Boolean { return _autodur; } public function set autoDuration(b:Boolean):void { _autodur = b; computeDuration(); } /** @inheritDoc */ public override function get duration():Number { if (_dirty) computeDuration(); return super.duration; } public override function set duration(dur:Number):void { _autodur = false; super.duration = dur; _dirty = true; } // -- Methods --------------------------------------------------------- /** * Creates a new Parallel transition. * @param transitions a list of sub-transitions */ public function Parallel(...transitions) { easing = Easing.none; for each (var t:Transition in transitions) { _trans.push(t); } _dirty = true; } /** * Adds a new sub-transition to this parallel transition. * @param t the transition to add */ public function add(t:Transition):void { if (running) throw new Error("Transition is running!"); _trans.push(t); _dirty = true; } /** * Removes a sub-transition from this parallel transition. * @param t the transition to remove * @return true if the transition was found and removed, false * otherwise */ public function remove(t:Transition):Boolean { if (running) throw new Error("Transition is running!"); var rem:Boolean = Vectors.remove(_trans, t) >= 0; if (rem) _dirty = true; return rem; } /** * Staggers the start of each sub-transition by a given interval. This * method will overwrite the delay settings for each sub-transition. * @param delay the delay between the start of each sub-transition. * @param reverse if true, staggering will be applied in the reverse * order in which sub-transitions were added. * @return returns this parallel transition */ public function stagger(delay:Number=0.05, reverse:Boolean=false):Parallel { var d:Number = 0, i:uint = 0; if (reverse) { for (i=_trans.length; --i>=0;) { _trans[i].delay = d; d += delay; } } else { for each (var t:Transition in _trans) { t.delay = d; d += delay; } } _dirty = true; return this; } /** * Computes the duration of this parallel transition. */ protected function computeDuration():void { var d:Number=0, td:Number; if (_trans.length > 0) d = _trans[0].totalDuration; _equidur = true; for each (var t:Transition in _trans) { td = t.totalDuration; if (_equidur && td != d) _equidur = false; d = Math.max(d, t.totalDuration); } if (_autodur) super.duration = d; _dirty = false; } /** @inheritDoc */ public override function dispose():void { while (_trans.length > 0) { _trans.pop().dispose(); } } // -- Transition Handlers --------------------------------------------- /** @inheritDoc */ public override function play(reverse:Boolean=false):void { if (_dirty) computeDuration(); super.play(reverse); } /** * Sets up each sub-transition. */ protected override function setup():void { for each (var t:Transition in _trans) { t.doSetup(); } } /** * Starts each sub-transition. */ protected override function start():void { for each (var t:Transition in _trans) { t.doStart(_reverse); } } /** * Steps each sub-transition. * @param ef the current progress fraction. */ internal override function step(ef:Number):void { var t:Transition; if (_equidur) { // if all durations are the same, we can skip some calculations for each (t in _trans) { t.doStep(ef); } } else { // otherwise, make sure we respect the different lengths var d:Number = duration; for each (t in _trans) { var td:Number = t.totalDuration; var f:Number = d==0 || td==d ? 1 : td/d; t.doStep(ef>f ? 1 : f==1 ? ef : ef/f); } } } /** * Ends each sub-transition. */ protected override function end():void { for each (var t:Transition in _trans) { t.doEnd(); } } } // end of class Parallel }