Files
FC1/CryMovie/AnimTrack.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

406 lines
10 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001.
// -------------------------------------------------------------------------
// File name: animtrack.h
// Version: v1.00
// Created: 22/4/2002 by Timur.
// Compilers: Visual C++ 7.0
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#ifndef __animtrack_h__
#define __animtrack_h__
#if _MSC_VER > 1000
#pragma once
#endif
//forward declarations.
#include "IMovieSystem.h"
/** General templated track for event type keys.
KeyType class must be derived from IKey.
*/
template <class KeyType>
class TAnimTrack : public IAnimTrack
{
public:
TAnimTrack();
//! Return number of keys in track.
virtual int GetNumKeys() { return m_keys.size(); };
//! Set number of keys in track.
//! If needed adds empty keys at end or remove keys from end.
virtual void SetNumKeys( int numKeys ) { m_keys.resize(numKeys); };
//! Remove specified key.
virtual void RemoveKey( int num );
int CreateKey( float time );
int CloneKey( int fromKey );
int CopyKey( IAnimTrack *pFromTrack, int nFromKey );
//! Get key at specified location.
//! @param key Must be valid pointer to compatable key structure, to be filled with specified key location.
virtual void GetKey( int index,IKey *key );
//! Get time of specified key.
//! @return key time.
virtual float GetKeyTime( int index );
//! Find key at givven time.
//! @return Index of found key, or -1 if key with this time not found.
virtual int FindKey( float time );
//! Get flags of specified key.
//! @return key time.
virtual int GetKeyFlags( int index );
//! Set key at specified location.
//! @param key Must be valid pointer to compatable key structure.
virtual void SetKey( int index,IKey *key );
//! Set time of specified key.
virtual void SetKeyTime( int index,float time );
//! Set flags of specified key.
virtual void SetKeyFlags( int index,int flags );
//! Sort keys in track (after time of keys was modified).
virtual void SortKeys();
//! Get track flags.
virtual int GetFlags() { return m_flags; };
//! Set track flags.
virtual void SetFlags( int flags ) { m_flags = flags; };
//////////////////////////////////////////////////////////////////////////
// Get track value at specified time.
// Interpolates keys if needed.
//////////////////////////////////////////////////////////////////////////
virtual void GetValue( float time,float &value ) { assert(0); };
virtual void GetValue( float time,Vec3 &value ) { assert(0); };
virtual void GetValue( float time,Quat &value ) { assert(0); };
virtual void GetValue( float time,bool &value ) { assert(0); };
//////////////////////////////////////////////////////////////////////////
// Set track value at specified time.
// Adds new keys if required.
//////////////////////////////////////////////////////////////////////////
virtual void SetValue( float time,const float &value,bool bDefault=false ) { assert(0); };
virtual void SetValue( float time,const Vec3 &value,bool bDefault=false ) { assert(0); };
virtual void SetValue( float time,const Quat &value,bool bDefault=false ) { assert(0); };
virtual void SetValue( float time,const bool &value,bool bDefault=false ) { assert(0); };
/** Assign active time range for this track.
*/
virtual void SetTimeRange( const Range &timeRange ) { m_timeRange = timeRange; };
/** Serialize this animation track to XML.
Do not ovveride this method, prefere to override SerializeKey.
*/
virtual bool Serialize( XmlNodeRef &xmlNode,bool bLoading, bool bLoadEmptyTracks=true );
/** Serialize single key of this track.
Ovvride this in derived classes.
Do not save time attribute, it is already saved in Serialize of the track.
*/
virtual void SerializeKey( KeyType &key,XmlNodeRef &keyNode,bool bLoading ) = 0;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/** Get last key before specified time.
@return Index of key, or -1 if such key not exist.
*/
int GetActiveKey( float time,KeyType *key );
protected:
void CheckValid()
{
if (m_bModified)
SortKeys();
};
void Invalidate() { m_bModified = true; };
typedef std::vector<KeyType> Keys;
Keys m_keys;
Range m_timeRange;
int m_currKey;
bool m_bModified;
float m_lastTime;
int m_flags;
};
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline TAnimTrack<KeyType>::TAnimTrack()
{
m_currKey = 0;
m_flags = 0;
m_lastTime = -1;
m_bModified = false;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline void TAnimTrack<KeyType>::RemoveKey( int index )
{
assert( index >= 0 && index < (int)m_keys.size() );
m_keys.erase( m_keys.begin() + index );
Invalidate();
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline void TAnimTrack<KeyType>::GetKey( int index,IKey *key )
{
assert( index >= 0 && index < (int)m_keys.size() );
assert( key != 0 );
*(KeyType*)key = m_keys[index];
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline void TAnimTrack<KeyType>::SetKey( int index,IKey *key )
{
assert( index >= 0 && index < (int)m_keys.size() );
assert( key != 0 );
m_keys[index] = *(KeyType*)key;
Invalidate();
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline float TAnimTrack<KeyType>::GetKeyTime( int index )
{
assert( index >= 0 && index < (int)m_keys.size() );
return m_keys[index].time;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline void TAnimTrack<KeyType>::SetKeyTime( int index,float time )
{
assert( index >= 0 && index < (int)m_keys.size() );
m_keys[index].time = time;
Invalidate();
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline int TAnimTrack<KeyType>::FindKey( float time )
{
for (int i = 0; i < (int)m_keys.size(); i++)
{
if (m_keys[i].time == time)
return i;
}
return -1;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline int TAnimTrack<KeyType>::GetKeyFlags( int index )
{
assert( index >= 0 && index < (int)m_keys.size() );
return m_keys[index].flags;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline void TAnimTrack<KeyType>::SetKeyFlags( int index,int flags )
{
assert( index >= 0 && index < (int)m_keys.size() );
m_keys[index].flags = flags;
Invalidate();
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline void TAnimTrack<KeyType>::SortKeys()
{
std::sort( m_keys.begin(),m_keys.end() );
m_bModified = false;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline bool TAnimTrack<KeyType>::Serialize( XmlNodeRef &xmlNode,bool bLoading,bool bLoadEmptyTracks )
{
if (bLoading)
{
int num = xmlNode->getChildCount();
Range timeRange;
int flags = m_flags;
xmlNode->getAttr( "Flags",flags );
xmlNode->getAttr( "StartTime",timeRange.start );
xmlNode->getAttr( "EndTime",timeRange.end );
SetFlags( flags );
SetTimeRange(timeRange);
SetNumKeys( num );
for (int i = 0; i < num; i++)
{
XmlNodeRef keyNode = xmlNode->getChild(i);
keyNode->getAttr( "time",m_keys[i].time );
SerializeKey( m_keys[i],keyNode,bLoading );
}
if ((!num) && (!bLoadEmptyTracks))
return false;
}
else
{
int num = GetNumKeys();
CheckValid();
xmlNode->setAttr( "Flags",GetFlags() );
xmlNode->setAttr( "StartTime",m_timeRange.start );
xmlNode->setAttr( "EndTime",m_timeRange.end );
for (int i = 0; i < num; i++)
{
XmlNodeRef keyNode = xmlNode->newChild( "Key" );
keyNode->setAttr( "time",m_keys[i].time );
SerializeKey( m_keys[i],keyNode,bLoading );
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline int TAnimTrack<KeyType>::CreateKey( float time )
{
KeyType key,akey;
int nkey = GetNumKeys();
SetNumKeys( nkey+1 );
key.time = time;
SetKey( nkey,&key );
return nkey;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline int TAnimTrack<KeyType>::CloneKey( int fromKey )
{
KeyType key;
GetKey( fromKey,&key );
int nkey = GetNumKeys();
SetNumKeys( nkey+1 );
SetKey( nkey,&key );
return nkey;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline int TAnimTrack<KeyType>::CopyKey( IAnimTrack *pFromTrack, int nFromKey )
{
KeyType key;
pFromTrack->GetKey( nFromKey,&key );
int nkey = GetNumKeys();
SetNumKeys( nkey+1 );
SetKey( nkey,&key );
return nkey;
}
//////////////////////////////////////////////////////////////////////////
template <class KeyType>
inline int TAnimTrack<KeyType>::GetActiveKey( float time,KeyType *key )
{
CheckValid();
int nkeys = m_keys.size();
if (nkeys == 0)
{
m_lastTime = time;
m_currKey = -1;
return m_currKey;
}
bool bTimeWrap = false;
if ((m_flags&ATRACK_CYCLE) || (m_flags&ATRACK_LOOP))
{
// Warp time.
const char *desc = 0;
float duration = 0;
GetKeyInfo( nkeys-1,desc,duration );
float endtime = GetKeyTime(nkeys-1) + duration;
time = cry_fmod( time,endtime );
if (time < m_lastTime)
{
// Time is wrapped.
bTimeWrap = true;
}
}
m_lastTime = time;
// Time is before first key.
if (m_keys[0].time > time)
{
if (bTimeWrap)
{
// If time wrapped, active key is last key.
m_currKey = nkeys-1;
*key = m_keys[m_currKey];
}
else
m_currKey = -1;
return m_currKey;
}
if (m_currKey < 0)
m_currKey = 0;
// Start from current key.
int i;
for (i = m_currKey; i < nkeys; i++)
{
if (time >= m_keys[i].time)
{
if ((i >= nkeys-1) || (time < m_keys[i+1].time))
{
m_currKey = i;
*key = m_keys[m_currKey];
return m_currKey;
}
}
else
break;
}
// Start from begining.
for (i = 0; i < nkeys; i++)
{
if (time >= m_keys[i].time)
{
if ((i >= nkeys-1) || (time < m_keys[i+1].time))
{
m_currKey = i;
*key = m_keys[m_currKey];
return m_currKey;
}
}
else
break;
}
m_currKey = -1;
return m_currKey;
}
#endif // __animtrack_h__