
//
// JavaScript class for A_Jumping
//
// To use this class on web pages:
//  - include the global support routines in BWT_SUPPORT.JS
//  - include this file
//  - Make sure that the file __BWT_SPACER.GIF is accessible (i.e. same directory)
//  - call
//      new A_Jumping();
//    to create a sprite instance
//

//
// A_Jumping resources
//
function A_Jumping( xScr, yScr, name, scale, depth )
{
	this.m_anim = ++BWT_numAnim;
	BWT_arrAnim.push(this);

	if( typeof(name)=='undefined' )
		name = A_Jumping;
    this.m_name = name;

    this.m_numView = 1;
    // view direction in polar coordinates
    this.m_arrViewTheta = new Array( 1.571, 0.000 );
    this.m_arrViewPhi = new Array( -0.095, 0.000 );

    this.m_numRotStep = 1;


    // eye lid control
    this.m_numEyeLidStep = 1;
    this.m_idxEyeLid = 0;

    // the "multiple" abilities
    this.m_numMultiple = 0;




    this.m_exprNeutral = 7;


    this.m_pmotRhino_Jumping0 = 2;

    this.m_pmotRhino_Jumping1 = 3;

    this.m_pmotRhino_Jumping2 = 4;

    this.m_pmotRhino_Jumping3 = 5;

    this.m_pmotRhino_Jumping4 = 6;



    //
    this.m_numCoreFrame = 23;

    // these arrays describe the core output
    this.m_nCoreListSize = 5;
    this.m_arrPLike = new Array( 2, 3, 4, 5, 6 );
    this.m_arrELike = new Array( 7, 7, 7, 7, 7 );
    this.m_arrStartFrame = new Array( 1, 7, 11, 15, 18 );
    this.m_arrFrameCount = new Array( 6, 4, 4, 3, 6 );
    this.m_arrMotionDuration = new Array( 655, 450, 430, 330, 630 );


    this.m_arrPNG = new Array( 23 );
    this.m_framePNG = -1;
	this.m_imgPNG = 0;

    this.m_curStartFrame;
    this.m_curFrameCount;
    this.m_curMotionDuration;

	if( typeof(depth)=='undefined' )
		depth = 0;
    this.m_depth = depth;

	if( typeof(scale)=='undefined' )
		scale = 1;
    this.m_scale = scale;

    this.m_scaleStart;
    this.m_scaleTarget;
    this.m_scaleDelta;

    this.m_rot;

    this.m_idxView = 0;
    this.m_idxRot = 0;

    this.m_xStart;
    this.m_yStart;
    this.m_xTarget;
    this.m_yTarget;
    this.m_xDelta;
    this.m_yDelta;

    this.m_timeMotionStart = 0;
    this.m_timeMotionDuration = 0;

    this.m_frame = 1;
    this.m_frameCore = 1;

    this.m_run = false;
    this.m_hasLerping = false;
    this.m_reverse = false;

	this.m_preloaded = false;
	this.m_complete = false;

	this.m_x = 0;
	this.m_y = 0;

	if( typeof(xScr)!='undefined' )
	    this.setX( xScr );
	if( typeof(yScr)!='undefined' )
	    this.setY( yScr );

    this.m_onStop = 0;

    this.stopMotion();


}


A_Jumping.prototype.show = function()
{
    this.ShowPNG( this.m_frame );
};

A_Jumping.prototype.hide = function()
{
    if( this.m_imgPNG )
        this.m_imgPNG.style.visibility="hidden";
};


//
// if multiple views are available, tries to find the best one,
//  sets m_idxView
//
A_Jumping.prototype.setView = function( theta, phi )
{
    var idx = 0;

    if( this.m_numView > 1 )
    {
        // linear search for the minimal error
        var curError = Number.POSITIVE_INFINITY;
        var candView = -1;
        var tempError;
        var n;

        for( n = 0; n < this.m_numView; n++ )
        {
            tempError = Math.abs( this.m_arrViewTheta[n] - theta ) +
                        Math.abs( this.m_arrViewPhi[n] - phi );
            if( tempError < curError )
            {
                curError = tempError;
                candView = n;
            }
        }

        if( candView != -1 )
            idx = candView;

    }

    this.setViewIdx( idx );
};


//
// selects a view by index
//
A_Jumping.prototype.setViewIdx = function( idx )
{
    if( (idx >= 0) && (idx < this.m_numView) )
    {
        this.m_idxView = idx;
        this.refreshVisuals();
    }
};








//
// a static pose + expression
//
A_Jumping.prototype.setStill = function( pLike, eLike )
{
    this.stopMotion();

    var off = this.findOffset(pLike, eLike);
    this.m_frameCore = this.m_arrStartFrame[off];
    this.refreshVisuals();
};


//
// finds the correct offset in frame arrays
//
A_Jumping.prototype.findOffset = function( pLike, eLike )
{
    var n;

    for( n = 0; n < 5; n++ )
    {
        if( (this.m_arrPLike[n] == pLike) && (this.m_arrELike[n] == eLike) )
            return n;
    }


    // actually an error condition...
    return 0;
};



A_Jumping.prototype.setStartTime = function( startTime )
{
    if(typeof( startTime ) != 'number')
        startTime = BWT_getTime();

    this.m_timeMotionStart = startTime;
}


//
// stop animation
//
A_Jumping.prototype.stopMotion = function()
{
    if( this.m_run )
    {
      this.m_run = false;

      this.onMotionStopped();
    }
};

A_Jumping.prototype.onMotionStopped = function()
{
    if( this.m_onStop )
    {
        eval(this.m_onStop);
    }
};

A_Jumping.prototype.preloadImgages = function()
{
    if( !this.m_preloaded )
    {
        var n;
        for( n = 0; n < 23; n++ )
        {
            this.getImgPNG(n);
        }
        this.m_preloaded = true;
    }
};

A_Jumping.prototype.complete = function()
{
    if( !this.m_complete )
    {
        this.preloadImgages();

        var n = 23;
        while( --n >= 0)
        {
            if( !this.m_arrPNG[n].complete )
                return false;
        }
        this.complete = true;
    }
    return true;
};

A_Jumping.prototype.getImgPNG = function( n )
{
    var imgPNG, srcPNG;

    imgPNG = this.m_arrPNG[n];
    if( typeof(imgPNG)=='undefined' )
    {
        srcPNG = 'A_Jumping_'+BWT_PadLeft(n.toString(), 4, '0')+'.PNG';
        imgPNG = new Image(300/** this.m_scale*/, 234/** this.m_scale*/);
        imgPNG.style.visibility="hidden";
        imgPNG.src = srcPNG;

        if ( BWT_FixPNG )
        {
            imgPNG.src = '__BWT_SPACER.GIF';
            imgPNG.runtimeStyle.filter = "progid:DXImageTransform.Microsoft." + "AlphaImageLoader(src='" + srcPNG + "',sizingMethod='scale')";
        }
        document.body.appendChild(imgPNG);
        imgPNG.style.position="absolute";

        this.m_arrPNG[n] = imgPNG;
    }
    return imgPNG;
};


A_Jumping.prototype.gotoAndStop = function( frame )
{
    this.m_run = false;
    this.m_frame = frame;
    this.ShowPNG( frame );
};

A_Jumping.prototype.ShowPNG = function( frame )
{
    var imgPNG;

    if(this.m_framePNG == --frame)
    {
        imgPNG = this.m_imgPNG;	// this.m_arrPNG[frame];

    } else
    {
        if( this.m_framePNG >= 0)
            this.m_arrPNG[this.m_framePNG].style.visibility="hidden";

        this.m_framePNG = frame;

        imgPNG = this.getImgPNG(frame);
        this.m_imgPNG = imgPNG;
    }

    imgPNG.width=300* this.m_scale;
    imgPNG.height=234* this.m_scale;

    imgPNG.style.zIndex = this.m_depth;

    imgPNG.style.left = this.getX();
    imgPNG.style.top  = this.getY();

    imgPNG.style.visibility="visible";
};


//
// start an animation
//
A_Jumping.prototype.runMotion = function( pLike, eLike, startTime, onStop )
{
    var off = this.findOffset(pLike, eLike);
    this.m_curStartFrame = this.m_arrStartFrame[off];
    this.m_curFrameCount = this.m_arrFrameCount[off];
    this.m_curMotionDuration = this.m_arrMotionDuration[off];

    this.m_timeMotionDuration = Number.POSITIVE_INFINITY;

    this.m_run = true;
    this.m_hasLerping = false;
    this.setStartTime( startTime );
    
    this.m_onStop = (typeof(onStop)!='undefined') ? onStop : 0;
    this.animate();
    
    
};


//
// let a motion run for a fixed time in miliseconds
//
A_Jumping.prototype.runMotionTimed = function( pLike, eLike, duration, startTime, onStop )
{
    var off = this.findOffset(pLike, eLike);
    this.m_curStartFrame = this.m_arrStartFrame[off];
    this.m_curFrameCount = this.m_arrFrameCount[off];
    this.m_curMotionDuration = this.m_arrMotionDuration[off];

    this.m_timeMotionDuration = duration;

    this.m_run = true;
    this.m_hasLerping = false;
    this.setStartTime( startTime );
    
    this.m_onStop = (typeof(onStop)!='undefined') ? onStop : 0;
    this.animate();
        
    
};


//
// let a motion run until a screen position is reached
//  either a duration in miliseconds or speed in pixels/second must be specified
//

A_Jumping.prototype.runMotionPos = function(  pLike, eLike,
                        xTarget, yTarget,
                        scaleTarget,
                        speed,
                        duration,
                        startTime,
                        onStop )
{

    var off = this.findOffset(pLike, eLike);
    this.m_curStartFrame = this.m_arrStartFrame[off];
    this.m_curFrameCount = this.m_arrFrameCount[off];
    this.m_curMotionDuration = this.m_arrMotionDuration[off];

    this.m_xStart = this.getX();
    this.m_yStart = this.getY();
    this.m_scaleStart = this.getScale();

    this.m_xTarget = (typeof(xTarget)!='undefined') ? xTarget : this.m_xStart;
    this.m_yTarget = (typeof(yTarget)!='undefined') ? yTarget : this.m_yStart;
    this.m_scaleTarget = (typeof(scaleTarget)!='undefined') ? scaleTarget : this.m_scaleStart;

    this.m_xDelta = this.m_xTarget - this.m_xStart;
    this.m_yDelta = this.m_yTarget - this.m_yStart;
    this.m_scaleDelta = this.m_scaleTarget - this.m_scaleStart;

    if( duration <= 0 )
    {
        var dist;
        dist = Math.sqrt( this.m_xDelta * this.m_xDelta + this.m_yDelta * this.m_yDelta );
        if( dist > 0 )
            this.m_timeMotionDuration = dist / speed * 1000;
        else
            this.m_timeMotionDuration = 1000;    // this should never happen
    }
    else
    {
        this.m_timeMotionDuration = duration;
    }

    this.m_onStop = (typeof(onStop)!='undefined') ? onStop : 0;

    this.m_run = true;
    this.m_hasLerping = true;
    this.setStartTime( startTime );

    this.animate();


};


A_Jumping.prototype.getReverse = function()
{
    return this.m_reverse;
};
A_Jumping.prototype.setReverse = function(r)
{
    this.m_reverse = r;
};

A_Jumping.prototype.getX = function()
{
    return (this.m_x + (300 / 2) * this.m_scale);
};

A_Jumping.prototype.getY = function()
{
    return (this.m_y + 234 * this.m_scale);
};

A_Jumping.prototype.getScale = function()
{
    return this.m_scale;
};

A_Jumping.prototype.getDepth = function()
{
    return this.m_depth;
};

A_Jumping.prototype.setX = function(x)
{
    this.m_x = x - (300 / 2) * this.m_scale;
};

A_Jumping.prototype.setY = function(y)
{
    this.m_y = y - 234 * this.m_scale;
};

A_Jumping.prototype.setScale = function(s)
{
    var x = this.getX();
    var y = this.getY();
    this.m_scale = s;
    this.setX(x);
    this.setY(y);
};

A_Jumping.prototype.setDepth = function(s)
{
    this.m_depth = s;
};





    //
    // use the index values to calculate the correct frame number
    //
    A_Jumping.prototype.refreshVisuals = function()
    {

            this.m_frame =	this.m_idxView * this.m_numRotStep * this.m_numCoreFrame * this.m_numEyeLidStep +
							this.m_idxRot * this.m_numCoreFrame * this.m_numEyeLidStep +
							this.m_idxEyeLid * this.m_numCoreFrame +
							this.m_frameCore;


		this.ShowPNG( this.m_frame );
    };

    A_Jumping.prototype.setAnimate = function(mS)
    {
		setTimeout("BWT_animate("+this.m_anim+")", mS);	// setInterval(this.animate, mS);
    }


    //
    // Call this periodically for the animation
    //
    A_Jumping.prototype.animate = function()
    {
        if( !(this.m_run) )
			return;

		if(this.m_imgPNG)
		{
			if(!(this.m_imgPNG.complete))
			{
				this.setAnimate(20);
				return;
			}
		}

		var stop;
        var timeCur = BWT_getTime();
        var frameAnim;

        var timeInMotion = timeCur - this.m_timeMotionStart;

        if( timeInMotion < this.m_timeMotionDuration )
        {
			stop = false;

            if( this.m_hasLerping )
            {
	            var lerp = timeInMotion / this.m_timeMotionDuration; // calculate new interpolated values

                this.setX( this.m_xStart + this.m_xDelta * lerp );
                this.setY( this.m_yStart + this.m_yDelta * lerp );
                this.setScale( this.m_scaleStart + this.m_scaleDelta * lerp );
            }
        }
        else
        {
			stop = true;	// we are done with this motion...

            if( this.m_hasLerping )
            {
                this.setX( this.m_xTarget );
                this.setY( this.m_yTarget );
                this.setScale( this.m_scaleTarget );
            }
            
            timeInMotion = this.m_timeMotionDuration - 1;
        }

        frameAnim = Math.floor(((timeInMotion % this.m_curMotionDuration) / this.m_curMotionDuration) * this.m_curFrameCount);

	    if( this.m_reverse )
		    this.m_frameCore = (this.m_curStartFrame - 1) + this.m_curFrameCount -frameAnim;
		else
	        this.m_frameCore = this.m_curStartFrame + frameAnim;


        this.refreshVisuals();

        if( stop )
            this.stopMotion();
        else
			this.setAnimate(1000/10.000);
    };

// eof