
//
// JavaScript class for A_demo1
//
// 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_demo1();
//    to create a sprite instance
//

//
// A_demo1 resources
//
function A_demo1( xScr, yScr, name, scale, depth )
{
	this.m_anim = ++BWT_numAnim;
	BWT_arrAnim.push(this);

	if( typeof(name)=='undefined' )
		name = A_demo1;
    this.m_name = name;

    this.m_numView = 1;
    // view direction in polar coordinates
    this.m_arrViewTheta = new Array( 0.085, 0.000 );
    this.m_arrViewPhi = new Array( -0.055, 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 = 3;


    this.m_pmotmodel_walk = 2;



    //
    this.m_numCoreFrame = 21;

    // these arrays describe the core output
    this.m_nCoreListSize = 1;
    this.m_arrPLike = new Array( 2, 0 );
    this.m_arrELike = new Array( 3, 0 );
    this.m_arrStartFrame = new Array( 1, 0 );
    this.m_arrFrameCount = new Array( 21, 0 );
    this.m_arrMotionDuration = new Array( 1800, 0 );


    this.m_arrJPG = new Array( 21 );
    this.m_frameJPG = -1;
	this.m_imgJPG = 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_demo1.prototype.show = function()
{
    this.ShowJPG( this.m_frame );
};

A_demo1.prototype.hide = function()
{
    if( this.m_imgJPG )
        this.m_imgJPG.style.visibility="hidden";
};


//
// if multiple views are available, tries to find the best one,
//  sets m_idxView
//
A_demo1.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_demo1.prototype.setViewIdx = function( idx )
{
    if( (idx >= 0) && (idx < this.m_numView) )
    {
        this.m_idxView = idx;
        this.refreshVisuals();
    }
};








//
// a static pose + expression
//
A_demo1.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_demo1.prototype.findOffset = function( pLike, eLike )
{
    var n;

    for( n = 0; n < 1; n++ )
    {
        if( (this.m_arrPLike[n] == pLike) && (this.m_arrELike[n] == eLike) )
            return n;
    }


    // actually an error condition...
    return 0;
};



A_demo1.prototype.setStartTime = function( startTime )
{
    if(typeof( startTime ) != 'number')
        startTime = BWT_getTime();

    this.m_timeMotionStart = startTime;
}


//
// stop animation
//
A_demo1.prototype.stopMotion = function()
{
    if( this.m_run )
    {
      this.m_run = false;

      this.onMotionStopped();
    }
};

A_demo1.prototype.onMotionStopped = function()
{
    if( this.m_onStop )
    {
        eval(this.m_onStop);
    }
};

A_demo1.prototype.preloadImgages = function()
{
    if( !this.m_preloaded )
    {
        var n;
        for( n = 0; n < 21; n++ )
        {
            this.getImgJPG(n);
        }
        this.m_preloaded = true;
    }
};

A_demo1.prototype.complete = function()
{
    if( !this.m_complete )
    {
        this.preloadImgages();

        var n = 21;
        while( --n >= 0)
        {
            if( !this.m_arrJPG[n].complete )
                return false;
        }
        this.complete = true;
    }
    return true;
};

A_demo1.prototype.getImgJPG = function( n )
{
    var imgJPG, srcJPG;

    imgJPG = this.m_arrJPG[n];
    if( typeof(imgJPG)=='undefined' )
    {
        srcJPG = 'A_demo1_'+BWT_PadLeft(n.toString(), 4, '0')+'.JPG';
        imgJPG = new Image(200/** this.m_scale*/, 144/** this.m_scale*/);
        imgJPG.style.visibility="hidden";
        imgJPG.src = srcJPG;


        document.body.appendChild(imgJPG);
        imgJPG.style.position="absolute";

        this.m_arrJPG[n] = imgJPG;
    }
    return imgJPG;
};


A_demo1.prototype.gotoAndStop = function( frame )
{
    this.m_run = false;
    this.m_frame = frame;
    this.ShowJPG( frame );
};

A_demo1.prototype.ShowJPG = function( frame )
{
    var imgJPG;

    if(this.m_frameJPG == --frame)
    {
        imgJPG = this.m_imgJPG;	// this.m_arrJPG[frame];

    } else
    {
        if( this.m_frameJPG >= 0)
            this.m_arrJPG[this.m_frameJPG].style.visibility="hidden";

        this.m_frameJPG = frame;

        imgJPG = this.getImgJPG(frame);
        this.m_imgJPG = imgJPG;
    }

    imgJPG.width=200* this.m_scale;
    imgJPG.height=144* this.m_scale;

    imgJPG.style.zIndex = this.m_depth;

    imgJPG.style.left = this.getX();
    imgJPG.style.top  = this.getY();

    imgJPG.style.visibility="visible";
};


//
// start an animation
//
A_demo1.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_demo1.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_demo1.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_demo1.prototype.getReverse = function()
{
    return this.m_reverse;
};
A_demo1.prototype.setReverse = function(r)
{
    this.m_reverse = r;
};

A_demo1.prototype.getX = function()
{
    return (this.m_x + (200 / 2) * this.m_scale);
};

A_demo1.prototype.getY = function()
{
    return (this.m_y + 144 * this.m_scale);
};

A_demo1.prototype.getScale = function()
{
    return this.m_scale;
};

A_demo1.prototype.getDepth = function()
{
    return this.m_depth;
};

A_demo1.prototype.setX = function(x)
{
    this.m_x = Math.floor(x - (200 / 2) * this.m_scale);
};

A_demo1.prototype.setY = function(y)
{
    this.m_y = y - 144 * this.m_scale;
};

A_demo1.prototype.setScale = function(s)
{
    var x = this.getX();
    var y = this.getY();
    this.m_scale = s;
    this.setX(x);
    this.setY(y);
};

A_demo1.prototype.setDepth = function(s)
{
    this.m_depth = s;
};





    //
    // use the index values to calculate the correct frame number
    //
    A_demo1.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.ShowJPG( this.m_frame );
    };

    A_demo1.prototype.setAnimate = function(mS)
    {
		setTimeout("BWT_animate("+this.m_anim+")", mS);	// setInterval(this.animate, mS);
    }


    //
    // Call this periodically for the animation
    //
    A_demo1.prototype.animate = function()
    {
        if( !(this.m_run) )
			return;

		if(this.m_imgJPG)
		{
			if(!(this.m_imgJPG.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/12.000);
    };

// eof
