ChainedTweener class : ChainedTweener.as

 

package com.yahoo.motion
{   
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.events.TimerEvent;
import com.yahoo.motion.easing.Linear;
import flash.utils.Timer;
import flash.utils.ByteArray
import com.yahoo.motion.ChainedTweenerEvent

/**
 * @author mr.hichem aka halfrobot
 */


public class ChainedTweener extends BaseTweener{
     

     //Private Properties that are inherited from the BaseTweener class
     /*private var _ease:Function = Linear.easeIn;
     private var _duration:Number = 1; //in seconds
     private var _frameRate:Number = 35;
     
     private var _props:Array;
     private var _initValues:Array;
     private var _currentValues:Array;
     private var _endValues:Array;
     private var _propsLength:Number;   
     private var _targetsLength:Number;
     private var _tweenIntervalId:uint;
     private var _targets:Array;
     private var _timer:Timer;
     private var _frameIndex:Number;
     private var _totalFrames:Number;
     private var _keys:Array;
     private var _loop:Boolean;
     private var _yoyo:Boolean;
     private var _delay:Number = 0*/

   
     /**
      * static properties
      * */

     protected static var _chain:Boolean
    protected static var _stack:Array
    protected static var _stackIndex:Number = 0

    /**
     * Constructor
     * @param   targets :  the target display object
     * @param   props : the properties to tween
     * @param   duration : the duration , obvious , optional
     * @param   ease : the ease function , optional
     * @param   initValues : initial values, optional
     * @param   endValues : end values , optional
     */

     public function ChainedTweener(targets:Object, props:Object, duration:Number = 1, ease:Function = null,  initValues:Object = null, endValues:Object = null)
     {        
        super(targets, props, duration, ease, initValues, endValues)
       
        if (_stack == null) _stack =  new Array()
       
        if (_stack.length > 0) {
            ChainedTweener(_stack[0]).setInitValues()   
        }

     }
     
    /**
     * Public functions
     */

    public override function stop():void
    {
        if (!_chain){
            this._frameIndex = 0;
            this._disposeTimer();
           
        }else if (_chain) {
            for (var i:int = 0; i < _stack.length; i++) {
                ChainedTweener(_stack[i])._timer.stop()
                ChainedTweener(_stack[i])._frameIndex=0
                ChainedTweener(_stack[i])._disposeTimer()
               
            }
           
           
        }
        this.dispatchEvent(new TweenerEvent(TweenerEvent.MOTION_STOP))
    }
   
    public override function pause(key:String=null):void
    {      
        if (!_chain){
        this._keys.push(key);
        this._timer.stop();
        }else if (_chain) {
           
            for (var i:int = 0; i < _stack.length; i++) {
                ChainedTweener(_stack[i])._timer.stop();
                ChainedTweener(_stack[i])._keys.push(key);
            }
        }
    }
   
    public override function resume(key:String=null):void
    {
       
        if(key == null)
                this._keys = new Array();
        else
        {
            var i:Number = this._keys.indexOf(key);
            if(i >= 0 )
                this._keys.splice(i,1);
        }
        if (!_chain){
            if(this._keys.length == 0)
            {
                this._timer.start();
                this.dispatchEvent(new TweenerEvent(TweenerEvent.MOTION_RESUME));
            }
        }else if (_chain) {
            if(this._keys.length == 0){
                for (var j:int = 0; j < _stack.length ; j++) {
                   
                   
                    ChainedTweener(_stack[j])._timer.start()
                    this.dispatchEvent(new ChainedTweenerEvent(ChainedTweenerEvent.MOTION_RESUME));
                    trace(ChainedTweenerEvent.CHAINED_MOTION_FINISH)
                    this.dispatchEvent(new ChainedTweenerEvent(ChainedTweenerEvent.CHAINED_MOTION_RESUME));
                }
            }
        }
       
       
       
    }
   
    public function chainedTweenTo(endValues:Object, delay:Number = 0,  duration:Number = -1, ease:Function = null):ChainedTweener
    {
        if(this._initValues == null)
            this._initValues = new Array();
        if (_stack.length == 0 ){  
            for(var u:Number =0; u< this._propsLength;u++)
                for(var l:Number =0; l<this._targetsLength; l++)
                    this._initValues[u] = this._targets[l][this._props[u]];
        }
        this.delay += delay 
        this._endValues = this._getValuesArray(endValues, Number);
        if(duration >= 0) this._duration = duration;
        if(ease != null) this._ease = ease;
        this._frameIndex = 0;
       
        if (_stack.length > 0) {
                this.delay +=  (_stack[_stack.length-1].duration * 1000)
            }
           
           
        _stack.push(this)
        _chain = true
        //_stackIndex++
        addEventListener("chainedTween", _chainedTweenHandler)
        this.dispatchEvent(new Event("chainedTween"))
        var res:ChainedTweener = this._clone(this)
        res._initValues = arrayClone(this._endValues)
        return _clone(res)
    }
   
    public function chainedTweenFromTo(initValues:Object, endValues:Object, delay:Number = 0,  duration:Number = -1, ease:Function = null):ChainedTweener
    {
       
       
       
        this._initValues = this._getValuesArray(initValues, Number)
       
        this.delay += delay 
        this._endValues = this._getValuesArray(endValues, Number);
       
        if(duration >= 0) this._duration = duration;
        if(ease != null) this._ease = ease;
        this._frameIndex = 0;
       
        if (_stack.length > 0) {
                this.delay +=  (_stack[_stack.length-1].duration * 1000)
                //trace("delay = " + this._delay, "duration = " + this.duration)
                //trace(_stack.length)
            }
        _stack.push(this)
        _chain = true
        //_stackIndex++
        addEventListener("chainedTween", _chainedTweenHandler)
        this.dispatchEvent(new Event("chainedTween"))
        var res:ChainedTweener = this._clone(this)
        res._initValues = arrayClone(this._endValues)
        return _clone(res)
    }
   
   
     function arrayClone(source:Object):*
    {
        var copier:ByteArray = new ByteArray();
        copier.writeObject(source);
        copier.position = 0;
        return(copier.readObject());
    }
   
    public override function tweenTo(endValues:Object, duration:Number = -1, ease:Function = null):void {
       
        if (_stack.length > 0) {
            //_stackIndex++
            this.chainedTweenTo(endValues, 0,duration, ease)
        }
        else super.tweenTo(endValues, duration, ease);
       
    }
   
    public override function tweenFromTo(initValues:Object, endValues:Object, duration:Number = -1, ease:Function = null):void{
        if (_stack.length > 0) {
            //_stackIndex++
            chainedTweenFromTo(initValues, endValues, 0,duration, ease)
           
        }
        else super.tweenFromTo(initValues, endValues, duration, ease);
    }
   
    /**
     *
     * private functions
     */

    protected override function _onTweenFinished(event:TimerEvent):void
    {
        this._lastStepIt();
        this._frameIndex = 0;
        if(this._loop && !_chain )
        {          
            var temp:Array =  (new Array()).concat(this._initValues);
            this._initValues = (new Array()).concat(this._endValues);
            this._endValues = temp;
            this._tween();
            this.dispatchEvent(new TweenerEvent(TweenerEvent.MOTION_LOOP))
           
            return;
        }
        else if(this._yoyo && !_chain)
        {
            this._tween();
            this.dispatchEvent(new TweenerEvent(TweenerEvent.MOTION_LOOP));
            return;
        }
        if (_chain)
        {
            var tamp:Array
           
            this._disposeTimer();
           
            if (_stack.length > 0) {
                _stackIndex--
                if(_stack.length > 1)
                ChainedTweener(_stack[0]).dispatchEvent(new ChainedTweenerEvent(ChainedTweenerEvent.CHAINED_MOTION_FINISH));
               
                if (_stackIndex== 0){
                    ChainedTweener(_stack[0]).dispatchEvent(new ChainedTweenerEvent(ChainedTweenerEvent.MOTION_FINISH));
                    if (_yoyo) {
                       
                        _stackIndex = _stack.length
                        for (var i:int = 0; i < _stack.length; i++) {
                            ChainedTweener(_stack[i])._timer.reset()
                            _stack[i]._doDelay()
                            ChainedTweener(_stack[0]).dispatchEvent(new ChainedTweenerEvent(ChainedTweenerEvent.MOTION_LOOP))
                        }
                    }
                    else if (_loop) {
                   
                        _stackIndex = _stack.length
                        _reverseDelays()
                        var temp:Array ;
                        for (var j:int = 0; j < _stack.length; j++) {
                            temp = (new Array()).concat(ChainedTweener(_stack[j])._initValues);
                            ChainedTweener(_stack[j])._initValues = (new Array()).concat(ChainedTweener(_stack[j])._endValues);
                            ChainedTweener(_stack[j])._endValues = temp;
                            _stack[j]._doDelay()
                            ChainedTweener(_stack[0]).dispatchEvent(new ChainedTweenerEvent(ChainedTweenerEvent.MOTION_LOOP))
                        }
                       
                    }
                   
                       
                    }
                   
               
               
            }
            trace(_stackIndex)
            return
        }
       
        this._disposeTimer();
        //this.dispatchEvent(new TweenerEvent(TweenerEvent.MOTION_FINISH));
    }
   
    private function _reverseDelays()
    {
        var temp:Number
        for (var i:int = 0; i < Math.floor(_stack.length/2); i++) {
            temp = _stack[i].delay
            _stack[i].delay = _stack[_stack.length - 1 - i].delay
            _stack[_stack.length - 1 - i].delay = temp
        }
    }
   
    protected static function _chainedTweenHandler(e:Event)
    {
        _stack[0].setInitValues()
        _stack[_stack.length - 1]._doDelay()
        _stack[_stack.length - 1].removeEventListener("chainedTween", _chainedTweenHandler)
        _stackIndex++
       
    }
   
    protected  function setInitValues()
    {
       
        for(var u:Number =0; u< this._propsLength;u++)
            for(var l:Number =0; l<this._targetsLength; l++)
                this._targets[l][this._props[u]] =  this._initValues[u];
    }

    protected function _clone(obj:ChainedTweener):ChainedTweener
    {
        var res:ChainedTweener ;
        res =  new ChainedTweener(obj._targets, obj._props, obj.duration, obj.ease, obj._initValues, obj._endValues)
        res._delay = obj._delay
        res.yoyo = obj.yoyo
        res.loop = obj.loop
        return res
    }
   
   
}

}