MercuryObjectCommands.cpp

Go to the documentation of this file.
00001 #include "global.h"
00002 #include "MercuryObjectCommands.h"
00003 #include "MercuryObject.h"
00004 #include "MercuryUtil.h"
00005 #include "MercuryMath.h"
00006 #include "MercuryLog.h"
00007 
00008 using namespace std;
00009 
00010 //ObjectFunctions Registering system
00011 AutoCommandRegisterer CommandRegisterer;
00012 
00013 map< MString, vector< MercuryTween * > > MercuryTweenState::m_GlobalTweens;
00014 
00015 MercuryTweenFunction AutoCommandRegisterer::GetFunction( const MString &name )
00016 {
00017     if ((sMapFunctions == NULL) || (sMapFunctions->find( name ) == sMapFunctions->end() ))
00018         return NULL;
00019 
00020     return (*sMapFunctions)[name];
00021 }
00022 
00023 int AutoCommandRegisterer::RegisterFunction( MercuryTweenFunction fnct, const MString & name )
00024 {
00025     if ( sMapFunctions == NULL )
00026         sMapFunctions = new map< MString, MercuryTweenFunction >;
00027 
00028     (*sMapFunctions)[name] = fnct;
00029 
00030     sNumFunctions++;
00031 
00032     return sNumFunctions;
00033 }
00034 
00035 MercuryTweenType AutoCommandRegisterer::GetTweenType( const MString &name )
00036 {
00037     if ((sMapTweens == NULL) || (sMapTweens->find( name ) == sMapTweens->end() ))
00038         return NULL;
00039 
00040     return (*sMapTweens)[name];
00041 }
00042 
00043 int AutoCommandRegisterer::RegisterTweenType( MercuryTweenType fnct, const MString & name )
00044 {
00045     if ( sMapTweens == NULL )
00046         sMapTweens = new map< MString, MercuryTweenType >;
00047 
00048     (*sMapTweens)[name] = fnct;
00049 
00050     sNumFunctions++;
00051 
00052     return sNumFunctions;
00053 }
00054 
00055 //Object Functions ( Actual Command, Name of Command, Forceful Typecast )
00056 #define STD_COMMAND( x, y, z ) \
00057 static void CMD##x( const float fPercent, const float fLastPercent, MercuryObject * pObject, MercuryTweenOperation * pOperation ) \
00058 { \
00059     float newloc; \
00060     if  ( pOperation->Parameters.PeekItem().GetType() == PSElement::PARAMETER ) {\
00061         newloc = pObject->Tweening.m_pCurrentTween->pKArgs.PeekItem( pOperation->Parameters.PeekItem().GetValueI() ).GetValueF(); \
00062     } else \
00063         newloc = pOperation->Parameters.PeekItem().GetValueF(); \
00064     float oldloc = pObject->Get##x(); \
00065     float diffloc = newloc-oldloc; \
00066     float totalmove = diffloc/(1-fLastPercent); \
00067     float fToMove = totalmove * ( fPercent - fLastPercent ); \
00068     pObject->Set##x( (z)( fToMove + oldloc ) ); \
00069 } \
00070  \
00071 static int FunctionNumberCMD##x = CommandRegisterer.RegisterFunction( CMD##x, y );
00072 
00073 #define STD_FLOAT_COMMAND( x, y ) STD_COMMAND( x, y, float )
00074 
00075 STD_FLOAT_COMMAND( X, "x" )
00076 STD_FLOAT_COMMAND( Y, "y" )
00077 STD_FLOAT_COMMAND( Z, "z" )
00078 STD_FLOAT_COMMAND( RotX, "rotationx" )
00079 STD_FLOAT_COMMAND( RotY, "rotationy" )
00080 STD_FLOAT_COMMAND( RotZ, "rotationz" )
00081 STD_FLOAT_COMMAND( ScaleX, "scalex" )
00082 STD_FLOAT_COMMAND( ScaleY, "scaley" )
00083 STD_FLOAT_COMMAND( ScaleZ, "scalez" )
00084 STD_COMMAND( DrawOrder, "draworder", int )  //FIXME
00085 
00086 //For object-specific commands, we have to register a special type of handler
00087 
00088 static void ExecuteObjectCommand( const float fPercent, const float fLastPercent, MercuryObject * pObject, MercuryTweenOperation * pOperation ) 
00089 {
00090     if ( fPercent == 1 )
00091     {
00092         PStack ret;
00093         pObject->Command( ret, pOperation->Command, pOperation->Parameters );
00094     }
00095 }
00096 
00097 static int FunctionNumberExecCommand = CommandRegisterer.RegisterFunction( ExecuteObjectCommand, "cmd" );
00098 
00099 //Alpha is not an object-specific command and cannot be grouped as an STD_COMMAND, so we have to explicitly work on it
00100 #define ADD_COLOR_COMMAND( x, y ) \
00101 static void ADDCCMD##x( const float fPercent, const float fLastPercent, MercuryObject * pObject, MercuryTweenOperation * pOperation ) \
00102 { \
00103     MercuryColor newloc; \
00104     if ( pOperation->Parameters.PeekItem(0).GetType() == PSElement::PARAMETER ) \
00105         newloc.SetR( pObject->Tweening.m_pCurrentTween->pKArgs.PeekItem( pOperation->Parameters.PeekItem(0).GetValueI() ).GetValueF() ); \
00106     else \
00107         newloc.SetR( pOperation->Parameters.PeekItem(0).GetValueF() ); \
00108     if ( pOperation->Parameters.PeekItem(1).GetType() == PSElement::PARAMETER ) \
00109         newloc.SetG( pObject->Tweening.m_pCurrentTween->pKArgs.PeekItem( pOperation->Parameters.PeekItem(1).GetValueI() ).GetValueF() ); \
00110     else \
00111         newloc.SetG( pOperation->Parameters.PeekItem(1).GetValueF() ); \
00112     if ( pOperation->Parameters.PeekItem(2).GetType() == PSElement::PARAMETER ) \
00113         newloc.SetB( pObject->Tweening.m_pCurrentTween->pKArgs.PeekItem( pOperation->Parameters.PeekItem(2).GetValueI() ).GetValueF() ); \
00114     else \
00115         newloc.SetB( pOperation->Parameters.PeekItem(2).GetValueF() ); \
00116     if ( pOperation->Parameters.PeekItem(3).GetType() == PSElement::PARAMETER ) \
00117         newloc.SetA( pObject->Tweening.m_pCurrentTween->pKArgs.PeekItem( pOperation->Parameters.PeekItem(3).GetValueI() ).GetValueF() ); \
00118     else \
00119         newloc.SetA( pOperation->Parameters.PeekItem(3).GetValueF() ); \
00120  \
00121     MercuryColor oldloc = pObject->Get##x(); \
00122     MercuryColor diffloc = newloc-oldloc; \
00123     MercuryColor totalmove = diffloc*(1/(1-fLastPercent)); \
00124     MercuryColor fToMove = totalmove * ( fPercent - fLastPercent ); \
00125  \
00126     pObject->Set##x( fToMove + oldloc ); \
00127 } \
00128  \
00129 static int FunctionADDCCMD##x = CommandRegisterer.RegisterFunction( ADDCCMD##x, y );
00130 
00131 ADD_COLOR_COMMAND( Diffuse, "diffuse" )
00132 ADD_COLOR_COMMAND( Ambient, "ambient" )
00133 ADD_COLOR_COMMAND( Emissive, "emissive" )
00134 ADD_COLOR_COMMAND( Specular, "specular" )
00135 
00136 #define ADD_COMMAND( x, y ) \
00137 static void ADDCMD##x( const float fPercent, const float fLastPercent, MercuryObject * pObject, MercuryTweenOperation * pOperation ) \
00138 { \
00139     float diffloc = pOperation->Parameters.PeekItem().GetValueF(); \
00140     float oldloc = pObject->Get##x(); \
00141     float totalmove = diffloc*(fPercent-fLastPercent); \
00142     float fToMove = totalmove; \
00143     pObject->Set##x( fToMove + oldloc ); \
00144 } \
00145  \
00146 static int FunctionNumberADDCMD##x = CommandRegisterer.RegisterFunction( ADDCMD##x, y );
00147 
00148 ADD_COMMAND( X, "addx" )
00149 ADD_COMMAND( Y, "addy" )
00150 ADD_COMMAND( Z, "addz" )
00151 ADD_COMMAND( RotX, "addrotationx" )
00152 ADD_COMMAND( RotY, "addrotationy" )
00153 ADD_COMMAND( RotZ, "addrotationz" )
00154 
00155 static void CommandHide( const float fPercent, const float fLastPercent, MercuryObject * pObject, MercuryTweenOperation * pOperation ) 
00156 { 
00157     bool hideON = (pOperation->Parameters.PeekItem().GetValueF() > 0.5f ); 
00158     if ( fPercent > 0.5f )
00159         pObject->SetHide( hideON ); 
00160 } 
00161 static int FunctionHideNumber = CommandRegisterer.RegisterFunction( CommandHide, "hide" );
00162 
00163 //Register Linear and sleep
00164 static float TweenLinear( const float fPercent, PStack & pArgs )
00165 {
00166     return fPercent;
00167 }
00168 
00169 static float TweenSleep( const float fPercent, PStack & pArgs )
00170 {
00171     if ( fPercent == 1 )
00172         return 1;
00173     else
00174         return 0;
00175 }
00176 
00177 static float TweenQuadratic( const float fPercent, PStack & pArgs )
00178 {
00179     return powf(fPercent,pArgs.PeekItem().GetValueF());
00180 }
00181 
00182 static int FunctionNumberCMDlinear = CommandRegisterer.RegisterTweenType( TweenLinear, "linear" );
00183 static int FunctionNumberCMDsleep = CommandRegisterer.RegisterTweenType( TweenSleep, "sleep" );
00184 static int FunctionNumberCMDquadratic = CommandRegisterer.RegisterTweenType( TweenQuadratic, "quadratic" );
00185 
00186 //The rest of the manager.
00187 
00188 
00189 MercuryTween::MercuryTween() :
00190     fStart(0), fEnd(0) 
00191 {
00192     //No code
00193     bDeleteChildren = true;
00194     iEndBase = -1;
00195 }
00196 
00197 MercuryTween::MercuryTween( const MercuryTween & rhs )
00198 {
00199     for( unsigned i = 0; i < rhs.Operations.size(); i++ )
00200         Operations.push_back( new MercuryTweenOperation( *rhs.Operations[i] ) );
00201     fStart = rhs.fStart;
00202     fEnd = rhs.fEnd;
00203     pTT = rhs.pTT;
00204     pTArgs = rhs.pTArgs;
00205     pKArgs = rhs.pKArgs;
00206     bAutoDelete = rhs.bAutoDelete;
00207     bDeleteChildren = rhs.bDeleteChildren;
00208     iEndBase = rhs.iEndBase;
00209 }
00210 
00211 MercuryTween & MercuryTween::operator = ( const MercuryTween & rhs )
00212 {
00213     for( unsigned i = 0; i < rhs.Operations.size(); i++ )
00214         Operations.push_back( new MercuryTweenOperation( *rhs.Operations[i] ) );
00215     fStart = rhs.fStart;
00216     fEnd = rhs.fEnd;
00217     pTT = rhs.pTT;
00218     pTArgs = rhs.pTArgs;
00219     pKArgs = rhs.pKArgs;
00220     bAutoDelete = rhs.bAutoDelete;
00221     bDeleteChildren = rhs.bDeleteChildren;
00222     iEndBase = rhs.iEndBase;
00223     return *this;
00224 }
00225 
00226 MercuryTween::~MercuryTween()
00227 {
00228     if ( bDeleteChildren )
00229         for( unsigned i = 0; i < Operations.size(); i++ )
00230             SAFE_DELETE( Operations[i] );
00231 }
00232 
00233 void MercuryTween::Operate( const float fPercent, const float fLastPercent, MercuryObject * pObject )
00234 {
00235     for ( unsigned i = 0; i < Operations.size(); i++ )
00236         Operations[i]->Function( fPercent, fLastPercent, pObject, Operations[i] );
00237 }
00238 
00239 MercuryTweenState::MercuryTweenState( )
00240     :m_fCurTime(0), m_bPauseTweening(false), m_bCloned( false )
00241 {
00242         //No code
00243     m_fRunningEnd = 0;
00244     m_pCurrentTween = NULL;
00245 }
00246 
00247 MercuryTweenState::MercuryTweenState( const MercuryTweenState & rhs ) :
00248     m_fCurTime(rhs.m_fCurTime), 
00249     m_bPauseTweening(rhs.m_bPauseTweening),
00250     m_fRunningEnd(rhs.m_fRunningEnd), m_LocalTweens(rhs.m_LocalTweens),
00251     m_bCloned( true )
00252 {
00253     MDequeIterator< MercuryTween *> i;
00254     for( i = m_qTweens.begin(); i != m_qTweens.end(); ++i )
00255         m_qTweens.push_back( new MercuryTween( *i.Data() ) );
00256     m_pCurrentTween = NULL;
00257 }
00258 
00259 MercuryTweenState & MercuryTweenState::operator = ( const MercuryTweenState & rhs )
00260 {
00261     m_bCloned = true;
00262     m_bPauseTweening = rhs.m_bPauseTweening;
00263     m_fCurTime = rhs.m_fCurTime;
00264     m_fRunningEnd = rhs.m_fRunningEnd;
00265     m_LocalTweens = rhs.m_LocalTweens;
00266     MDequeIterator< MercuryTween *> i;
00267     for( i = rhs.m_qTweens.begin(); i != rhs.m_qTweens.end(); ++i )
00268         m_qTweens.push_back( new MercuryTween( *i.Data() ) );
00269     m_pCurrentTween = NULL;
00270     return *this;
00271 }
00272 
00273 MercuryTweenState::~MercuryTweenState()
00274 {
00275     StopTweening();
00276     if( !m_bCloned )
00277     {
00278         map< MString, vector< MercuryTween * > >::iterator g = m_LocalTweens.begin();
00279         for( ; g != m_LocalTweens.end(); g++ )
00280         {
00281             for ( unsigned i = 0; i < (g->second).size(); i++ )
00282                 SAFE_DELETE( (g->second)[i] );
00283         }
00284     }
00285 }
00286 
00287 void MercuryTweenState::AttachToObject( MercuryObject * object )
00288 {
00289     m_pObject = object;
00290 }
00291 
00292 void MercuryTweenState::Update( float fDeltaTime )
00293 {
00294     if ( !m_bPauseTweening ) 
00295         m_fCurTime += fDeltaTime;
00296     
00297     InternalUpdate( fDeltaTime );
00298 }
00299 
00300 void MercuryTweenState::FinishTweening()
00301 {
00302     InternalUpdate( 0, true );
00303 }
00304 
00305 void MercuryTweenState::StopTweening()
00306 {
00307     m_pCurrentTween = NULL;
00308     
00309     while ( !m_qTweens.empty() )
00310     {
00311         if ( m_qTweens.front()->bAutoDelete )
00312             SAFE_DELETE( m_qTweens.front() );
00313         m_qTweens.pop_front();
00314     }
00315 }
00316 
00317 void MercuryTweenState::InternalUpdate( float fDeltaTime, bool bFinish )
00318 {
00319     while ( !m_qTweens.empty() )
00320     {
00321         if ( !m_pCurrentTween && (m_qTweens.front()->fStart <= m_fCurTime) )
00322             m_pCurrentTween = m_qTweens.front();
00323         
00324         if ( bFinish )
00325             if ( m_pCurrentTween->fEnd > m_fCurTime )
00326             {
00327                 //If we move the time forward the next block of code should
00328                 //complete and remove the current tween. The loop should
00329                 // continue until all tweens have been completed and removed.
00330                 fDeltaTime += ( m_pCurrentTween->fEnd - m_fCurTime );
00331                 m_fCurTime = m_pCurrentTween->fEnd;
00332             }
00333 
00334         if ( m_pCurrentTween->fEnd <= m_fCurTime )
00335         {
00336             float curPercent = 1;
00337             float lastPercent = CalculateRemainingPercent( fDeltaTime );
00338     
00339             lastPercent = Clamp( lastPercent, 0.0f, 1.0f);
00340             m_pCurrentTween->Operate( curPercent, lastPercent, m_pObject );
00341             
00342             //remove tween from queue only when done
00343             m_qTweens.pop_front();
00344             if ( m_pCurrentTween->bAutoDelete )
00345                 SAFE_DELETE( m_pCurrentTween );
00346             m_pCurrentTween = NULL;
00347         } else {
00348             float curPercent = CalculateCurrentPercent( fDeltaTime );
00349             float lastPercent = CalculateRemainingPercent( fDeltaTime );
00350                 
00351             //Clamp high for bouncing.
00352             lastPercent = Clamp( lastPercent, 0.0f, 1000.0f );
00353             m_pCurrentTween->Operate( m_pCurrentTween->pTT(curPercent,m_pCurrentTween->pTArgs), 
00354                                     m_pCurrentTween->pTT(lastPercent,m_pCurrentTween->pTArgs), m_pObject );
00355             break;
00356         }
00357     }
00358 }
00359 
00360 float MercuryTweenState::CalculateRemainingPercent( float fDeltaTime )
00361 {
00362     float percent, fDeltaTweenTime;
00363     percent = 0;
00364     fDeltaTweenTime = m_pCurrentTween->fEnd - m_pCurrentTween->fStart;
00365     if (fDeltaTweenTime > 0)
00366         percent = ( m_fCurTime - fDeltaTime - m_pCurrentTween->fStart ) / fDeltaTweenTime ;
00367     return percent;
00368 }
00369 
00370 float MercuryTweenState::CalculateCurrentPercent( float fDeltaTime )
00371 {
00372     float percent, fDeltaTweenTime;
00373     percent = 0;
00374     fDeltaTweenTime = m_pCurrentTween->fEnd - m_pCurrentTween->fStart;
00375     if (fDeltaTweenTime > 0)
00376         percent = ( m_fCurTime - m_pCurrentTween->fStart ) / fDeltaTweenTime ;
00377     return percent;
00378 }
00379 
00380 void MercuryTweenState::ExecuteCommand( const MString & sName, const PStack & pKArgs )
00381 {
00382     vector< MercuryTween * > * AllTweens = NULL;
00383     if ( m_LocalTweens.find( sName ) == m_LocalTweens.end() )
00384     {
00385         if ( m_GlobalTweens.find( sName ) == m_GlobalTweens.end() )
00386             AllTweens = NULL;
00387         else
00388             AllTweens = &m_GlobalTweens[sName];
00389     } else
00390         AllTweens = &m_LocalTweens[sName];
00391 
00392     if ( AllTweens == NULL )
00393         return;
00394 
00395     vector< MercuryTween * >::iterator g = AllTweens->begin();
00396     for ( ; g != AllTweens->end(); g++ )
00397     {
00398         MercuryTween * Copied = new MercuryTween;
00399         //(*Copied) = (*(*g));
00400         if ( (*g)->iEndBase >= 0 )
00401             Copied->fEnd = pKArgs.PeekItem( (*g)->iEndBase ).GetValueF();
00402         else
00403             Copied->fEnd = (*g)->fEnd;
00404         Copied->fStart = 0;
00405         Copied->pTT = (*g)->pTT;
00406         Copied->pTArgs = (*g)->pTArgs;
00407         Copied->Operations = (*g)->Operations;
00408         Copied->pKArgs = pKArgs;
00409         Copied->bAutoDelete = true;
00410         Copied->bDeleteChildren = false;
00411         AddCommand( Copied );
00412     }
00413 }
00414 
00415 void MercuryTweenState::AddCommand( MercuryTween * ToPush, float fFuture, SPACE iWhichPlace, MString sTweenName )
00416 {
00417     if ( m_qTweens.size() > 0 )
00418     {
00419         ToPush->fStart += m_fRunningEnd;
00420         ToPush->fEnd += m_fRunningEnd;
00421     } else if ( fFuture >= 0 )
00422     {
00423         ToPush->fStart += m_fCurTime;
00424         ToPush->fEnd += ToPush->fStart;  //Relitive to when the start ends, I think.
00425     }
00426     
00427     switch ( iWhichPlace )
00428     {
00429     case CURRENT:
00430         ToPush->bAutoDelete = true;
00431         m_qTweens.push_back( ToPush );
00432         break;
00433     case LOCAL:
00434         ToPush->bAutoDelete = false;
00435         m_LocalTweens[sTweenName].push_back( ToPush );
00436         break;
00437     case GLOBAL:
00438         ToPush->bAutoDelete = false;
00439         m_GlobalTweens[sTweenName].push_back( ToPush );
00440         break;
00441     default:
00442         LOG.Warn( "Requested AddCommand to non-existant tween 'place'.  This tween will leak." );
00443         break;
00444     };
00445     
00446     m_fRunningEnd = ToPush->fEnd;
00447     
00448     //If we have just added the first tween and it is immediate,
00449     //run an update so the tween is initalized. This fixes the
00450     //problem of objects being in the wrong place for the very
00451     //first frame of an animation.
00452     if ( (m_qTweens.size() == 1) && (fFuture <= 0.0f) )
00453         InternalUpdate( 0 );
00454 }
00455 
00456 
00457 //HEAVILY OPTIMIZED!
00458 //
00459 //Noted slow downs: There does not exist a atof() that takes on a length
00460 //parameter.  We have to copy the string into a new string in order to send
00461 //it in.
00462 
00463 void MercuryTweenState::AddCommand( const MString & command, SPACE iWhichPlace, MString sTweenName )
00464 {
00465     const char *sCmd = command.c_str();
00466     const char *sEnd = sCmd + command.length();
00467     const char *sNext = 0;
00468     const char *sCur = sCmd;
00469     const char *sNextComma = 0;
00470     char    *   sTmp;
00471     unsigned int            iTmp;
00472     bool        bHasNextPart;
00473     MString     sBaseCmd;
00474     MercuryTween * cs = new MercuryTween;
00475     cs->fEnd = -1;
00476 
00477     //First if we are writing to a cache buffer, we have to clear it out.
00478     switch ( iWhichPlace )
00479     {
00480     case LOCAL:
00481         for ( iTmp = 0; iTmp < m_LocalTweens[sTweenName].size(); ++iTmp )
00482             SAFE_DELETE( m_LocalTweens[sTweenName][iTmp] );
00483         m_LocalTweens[sTweenName].clear();
00484         break;
00485     case GLOBAL:
00486         for ( iTmp = 0; iTmp < m_GlobalTweens[sTweenName].size(); ++iTmp )
00487             SAFE_DELETE( m_GlobalTweens[sTweenName][iTmp] );
00488         m_GlobalTweens[sTweenName].clear();
00489         break;
00490     default:
00491         break;
00492     }
00493 
00494     //Make sure we aren't past the end, and we aren't at/beyond the real end.
00495     while ( sCur < sEnd && sCur[0] != '\0' )
00496     {
00497         //Find next ; in string.  If it's past the end of the string, say it's at the end
00498         sNext = strchr( sCur, ';' );
00499         if ( !sNext )
00500             sNext = sEnd;
00501 
00502         //Find the next comma.  If it's beyond the end of the string, say it's at the end
00503         //and set a flag
00504         sNextComma = strchr( sCur, ',' );
00505         if ( sNextComma > sNext || !sNextComma )
00506         {
00507             bHasNextPart = false;
00508             sNextComma = sNext;
00509         } else
00510             bHasNextPart = true;
00511 
00512         //Clear out the base command, and stick in the other info.
00513         sBaseCmd.assign( sCur, sNextComma - sCur );
00514 
00515         //Say we're currently after the previous command's comma
00516         //IE:    sBaseCmd,[here],...
00517         sCur = sNextComma+1;
00518 
00519         //Check to see if we have functions or tween types
00520         MercuryTweenFunction fnct = CommandRegisterer.GetFunction( sBaseCmd );
00521         MercuryTweenType typ = CommandRegisterer.GetTweenType( sBaseCmd );
00522 
00523         //(Remaining = Current -> sNext - sCur)
00524 
00525         //SPECIAL: If we start without knowing what kind of tween type to use
00526         // we MUST set one, otherwise our tween may be thrown out, or we may 
00527         // try tweening from an unknown state.  So, we set up a dummy tween.
00528         if ( typ == NULL && cs->fEnd < 0 )
00529         {
00530             cs->fEnd = 0;
00531             cs->pTT = CommandRegisterer.GetTweenType( "sleep" );
00532             cs->fStart = 0;
00533         }
00534 
00535         if ( typ != NULL )
00536         {
00537             //We have a tween type
00538 
00539             //Check to see if cs contains a tween
00540             if ( cs->fEnd >= 0 )
00541             {
00542                 //If so add it to this.
00543                 AddCommand( cs, 0, iWhichPlace, sTweenName );
00544                 cs = new MercuryTween;
00545             }
00546 
00547             //Set the tween type
00548             cs->pTT = typ;
00549 
00550             //If we have no more parts, don't bother processing for fEnd
00551             if ( !bHasNextPart )
00552             {
00553                 cs->fEnd = 0;
00554                 cs->pTArgs.Clear();
00555             } else {
00556                 //Otherwise process for end
00557                 sNextComma = strchr( sCur, ',' );
00558                 if ( sNextComma > sNext || !sNextComma )
00559                     sNextComma = sNext;
00560 
00561                 iTmp = sNextComma - sCur;
00562                 sTmp = (char*)malloc( sNextComma - sCur + 1 );
00563                 strncpy( sTmp, sCur, iTmp );
00564                 sTmp[iTmp] = '\0';
00565                 cs->fEnd = float(atof( sTmp ));
00566                 if ( sTmp[0] == '%' )
00567                     cs->iEndBase = atoi( sTmp+1 );
00568                 free( sTmp );
00569                 sCur = sNextComma+1;
00570 
00571                 //Add on any additional arguments.  This is "safe"
00572                 cs->pTArgs = PStack( sCur, sNext - sCur );
00573 
00574                 if( sCur < sNext )
00575                     sCur = sNext + 1;
00576             }
00577         } else if ( fnct != NULL ) {
00578             MercuryTweenOperation * k = new MercuryTweenOperation;
00579             k->Function = fnct;
00580 
00581             //Dump on any additional parameters.
00582             k->Parameters = PStack( sCur, sNext - sCur );
00583 
00584             //If we have farther to go, move up to right after the next ;
00585             if ( sCur <= sNext )
00586                 sCur = sNext + 1;
00587             cs->Operations.push_back(k);
00588         } else {
00589             fnct = CommandRegisterer.GetFunction( "cmd" );
00590             if ( fnct == NULL )
00591                 LOG.Warn( "The object commands function \"cmd\" has not been registered!  Your compile may be bad" );
00592             else
00593             {
00594                 MercuryTweenOperation *k = new MercuryTweenOperation;
00595                 k->Function = fnct;
00596                 k->Command = sBaseCmd;
00597                 k->Parameters = PStack( sCur, sNext - sCur );
00598                 if ( sCur <= sNext )
00599                     sCur = sNext + 1;
00600                 cs->Operations.push_back(k);
00601             }
00602         }
00603     }
00604     if ( cs->fEnd < 0 )
00605         cs->fEnd = 0;
00606     if ( ( cs->Operations.size() > 0 ) || (cs->fEnd > 0) )
00607         AddCommand( cs, 0, iWhichPlace, sTweenName );
00608     else
00609         SAFE_DELETE( cs );
00610 }
00611 
00612 /* 
00613  * Copyright (c) 2005-2006, Charles Lohr
00614  * All rights reserved.
00615  *
00616  * Redistribution and use in source and binary forms, with or
00617  * without modification, are permitted provided that the following
00618  * conditions are met:
00619  *  -   Redistributions of source code must retain the above
00620  *      copyright notice, this list of conditions and the following disclaimer.
00621  *  -   Redistributions in binary form must reproduce the above copyright
00622  *      notice, this list of conditions and the following disclaimer in
00623  *      the documentation and/or other materials provided with the distribution.
00624  *  -   Neither the name of the <ORGANIZATION> nor the names of its
00625  *      contributors may be used to endorse or promote products derived from
00626  *      this software without specific prior written permission.
00627  *
00628  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00629  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00630  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00631  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00632  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00633  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00634  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00635  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00636  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00637  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00638  */
00639 

Hosted by SourceForge.net Logo