123
This commit is contained in:
420
CryMovie/AnimSequence.cpp
Normal file
420
CryMovie/AnimSequence.cpp
Normal file
@@ -0,0 +1,420 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: animsequence.cpp
|
||||
// Version: v1.00
|
||||
// Created: 29/4/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "AnimSequence.h"
|
||||
#include "SceneNode.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAnimSequence::CAnimSequence( IMovieSystem *pMovieSystem )
|
||||
{
|
||||
m_pMovieSystem = pMovieSystem;
|
||||
m_flags = 0;
|
||||
m_pSceneNode=NULL;
|
||||
m_timeRange.Set( 0,10 );
|
||||
m_bPaused = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::SetName( const char *name )
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char* CAnimSequence::GetName()
|
||||
{
|
||||
return m_name.c_str();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::SetFlags( int flags )
|
||||
{
|
||||
m_flags = flags;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CAnimSequence::GetFlags() const
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CAnimSequence::GetNodeCount() const
|
||||
{
|
||||
return m_nodes.size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IAnimNode* CAnimSequence::GetNode( int index ) const
|
||||
{
|
||||
assert( index >= 0 && index < (int)m_nodes.size() );
|
||||
return m_nodes[index].node;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IAnimBlock* CAnimSequence::GetAnimBlock( int index ) const
|
||||
{
|
||||
assert( index >= 0 && index < (int)m_nodes.size() );
|
||||
return m_nodes[index].anim;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAnimSequence::AddNode( IAnimNode *node )
|
||||
{
|
||||
assert( node != 0 );
|
||||
|
||||
// Check if this node already in sequence.
|
||||
for (int i = 0; i < (int)m_nodes.size(); i++)
|
||||
{
|
||||
if (node == m_nodes[i].node)
|
||||
{
|
||||
// Fail to add node second time.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ANode an;
|
||||
an.node = node;
|
||||
an.anim = new CAnimBlock;//node->CreateAnimBlock();
|
||||
an.anim->SetTimeRange( m_timeRange );
|
||||
an.node->SetAnimBlock( an.anim );
|
||||
m_nodes.push_back( an );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::RemoveNode( IAnimNode *node )
|
||||
{
|
||||
assert( node != 0 );
|
||||
for (int i = 0; i < (int)m_nodes.size(); i++)
|
||||
{
|
||||
if (node == m_nodes[i].node)
|
||||
{
|
||||
if (node->GetAnimBlock() == m_nodes[i].anim)
|
||||
node->SetAnimBlock( 0 );
|
||||
m_nodes.erase( m_nodes.begin()+i );
|
||||
if (node && (node==m_pSceneNode))
|
||||
m_pSceneNode=NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IAnimNode* CAnimSequence::AddSceneNode()
|
||||
{
|
||||
if (m_pSceneNode)
|
||||
return NULL;
|
||||
m_pSceneNode=new CAnimSceneNode(GetMovieSystem());
|
||||
m_pSceneNode->SetName("Scene");
|
||||
AddNode(m_pSceneNode);
|
||||
return m_pSceneNode;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::RemoveAll()
|
||||
{
|
||||
m_nodes.clear();
|
||||
m_pSceneNode=NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::Reset()
|
||||
{
|
||||
// Animation sequence should not be animated on Reset.
|
||||
Activate();
|
||||
|
||||
SAnimContext ec;
|
||||
ec.bSingleFrame = true;
|
||||
ec.bResetting = true;
|
||||
ec.sequence = this;
|
||||
ec.time = m_timeRange.start;
|
||||
Animate( ec );
|
||||
|
||||
Deactivate();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::Pause()
|
||||
{
|
||||
if (m_bPaused)
|
||||
return;
|
||||
m_bPaused = true;
|
||||
// Detach animation block from all nodes in this sequence.
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
it->node->Pause();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::Resume()
|
||||
{
|
||||
if (!m_bPaused)
|
||||
return;
|
||||
m_bPaused = false;
|
||||
// Detach animation block from all nodes in this sequence.
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
it->node->Resume();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::Animate( SAnimContext &ec )
|
||||
{
|
||||
ec.sequence = this;
|
||||
// Evaluate all animation nodes in sequence.
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
// Make sure correct animation block is binded to node.
|
||||
IAnimBlock *ablock = it->anim;
|
||||
if (it->node->GetAnimBlock() != ablock)
|
||||
{
|
||||
ablock->SetTimeRange( m_timeRange );
|
||||
it->node->SetAnimBlock( ablock );
|
||||
}
|
||||
// Animate node.
|
||||
it->node->Animate( ec );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::Activate()
|
||||
{
|
||||
// Assign animation block to all nodes in this sequence.
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
IAnimBlock *ablock = it->anim;
|
||||
ablock->SetTimeRange( m_timeRange );
|
||||
it->node->SetAnimBlock( ablock );
|
||||
}
|
||||
|
||||
// If this sequence is cut scene disable player.
|
||||
if (m_flags & CUT_SCENE)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::Deactivate()
|
||||
{
|
||||
// Detach animation block from all nodes in this sequence.
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
it->node->Reset();
|
||||
it->node->SetAnimBlock( 0 );
|
||||
}
|
||||
// If this sequence is cut scene, enable player.
|
||||
if (m_flags & CUT_SCENE)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::Serialize( XmlNodeRef &xmlNode,bool bLoading, bool bLoadEmptyTracks )
|
||||
{
|
||||
if (bLoading)
|
||||
{
|
||||
// Load.
|
||||
RemoveAll();
|
||||
|
||||
Range timeRange;
|
||||
const char *name = xmlNode->getAttr( "Name" );
|
||||
xmlNode->getAttr( "Flags",m_flags );
|
||||
xmlNode->getAttr( "StartTime",timeRange.start );
|
||||
xmlNode->getAttr( "EndTime",timeRange.end );
|
||||
|
||||
SetName( name );
|
||||
SetTimeRange( timeRange );
|
||||
// Loading.
|
||||
XmlNodeRef nodes = xmlNode->findChild( "Nodes" );
|
||||
if (nodes)
|
||||
{
|
||||
int id;
|
||||
int type;
|
||||
for (int i = 0; i < nodes->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef xn = nodes->getChild(i);
|
||||
xn->getAttr( "Id",id );
|
||||
IAnimNode *node=NULL;
|
||||
if (!id) // scene-node-id
|
||||
{
|
||||
if (m_pSceneNode)
|
||||
node=m_pSceneNode;
|
||||
else
|
||||
node=AddSceneNode();
|
||||
}else
|
||||
{
|
||||
node = m_pMovieSystem->GetNode(id);
|
||||
}
|
||||
if (!node)
|
||||
{
|
||||
if (!xn->getAttr( "Type",type ))
|
||||
continue;
|
||||
node = m_pMovieSystem->CreateNode( type );
|
||||
if (!node)
|
||||
continue;
|
||||
const char *sName = xn->getAttr( "Name" );
|
||||
if (sName)
|
||||
node->SetName(sName);
|
||||
}
|
||||
|
||||
// Add nodes to sequence and intialize its animation block for this sequence.
|
||||
if (node!=m_pSceneNode)
|
||||
AddNode(node);
|
||||
|
||||
IAnimBlock *ablock = node->GetAnimBlock();
|
||||
if (ablock)
|
||||
{
|
||||
ablock->Serialize( node,xn,bLoading,bLoadEmptyTracks );
|
||||
}
|
||||
}
|
||||
}
|
||||
Deactivate();
|
||||
//ComputeTimeRange();
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlNode->setAttr( "Name",GetName() );
|
||||
xmlNode->setAttr( "Flags",m_flags );
|
||||
xmlNode->setAttr( "StartTime",m_timeRange.start );
|
||||
xmlNode->setAttr( "EndTime",m_timeRange.end );
|
||||
|
||||
// Save.
|
||||
XmlNodeRef nodes = xmlNode->newChild( "Nodes" );
|
||||
int num = GetNodeCount();
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
IAnimNode *node = GetNode(i);
|
||||
if (!node)
|
||||
continue;
|
||||
XmlNodeRef xn = nodes->newChild( "Node" );
|
||||
xn->setAttr( "Id",node->GetId() );
|
||||
xn->setAttr( "Type",node->GetType() );
|
||||
xn->setAttr( "Name",node->GetName() );
|
||||
|
||||
IAnimBlock *ablock = GetAnimBlock(i);
|
||||
if (!ablock)
|
||||
continue;
|
||||
|
||||
ablock->Serialize( node,xn,bLoading );
|
||||
}
|
||||
/*
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
IAnimNode *node = it->node;
|
||||
if (!node)
|
||||
continue;
|
||||
IAnimBlock *ablock = it->anim;
|
||||
XmlNodeRef xn = nodes->newChild( "Node" );
|
||||
xn->setAttr( "Id",node->GetId() );
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::SetTimeRange( Range timeRange )
|
||||
{
|
||||
m_timeRange = timeRange;
|
||||
// Set this time range for every track in animation.
|
||||
// Set time range to be in range of largest animation track.
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
IAnimBlock *ablock = it->anim;
|
||||
if (!ablock)
|
||||
continue;
|
||||
ablock->SetTimeRange( timeRange );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::ScaleTimeRange( const Range &timeRange )
|
||||
{
|
||||
// Calculate scale ratio.
|
||||
float scale = timeRange.Length() / m_timeRange.Length();
|
||||
m_timeRange = timeRange;
|
||||
|
||||
// Set time range to be in range of largest animation track.
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
IAnimBlock *ablock = it->anim;
|
||||
if (!ablock)
|
||||
continue;
|
||||
|
||||
int paramCount = ablock->GetTrackCount();
|
||||
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++)
|
||||
{
|
||||
int trackType;
|
||||
IAnimTrack *pTrack;
|
||||
if (!ablock->GetTrackInfo( paramIndex,trackType,&pTrack ))
|
||||
continue;
|
||||
if (pTrack)
|
||||
{
|
||||
int nkey = pTrack->GetNumKeys();
|
||||
for (int k = 0; k < nkey; k++)
|
||||
{
|
||||
float keytime = pTrack->GetKeyTime(k);
|
||||
keytime = keytime*scale;
|
||||
pTrack->SetKeyTime(k,keytime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAnimSequence::ComputeTimeRange()
|
||||
{
|
||||
Range timeRange;
|
||||
//timeRange.start = FLT_MAX;
|
||||
//timeRange.end = FLT_MIN;
|
||||
|
||||
timeRange = m_timeRange;
|
||||
|
||||
// Set time range to be in range of largest animation track.
|
||||
for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
|
||||
{
|
||||
IAnimBlock *ablock = it->anim;
|
||||
if (!ablock)
|
||||
continue;
|
||||
|
||||
int paramCount = ablock->GetTrackCount();
|
||||
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++)
|
||||
{
|
||||
int trackType;
|
||||
IAnimTrack *pTrack;
|
||||
if (!ablock->GetTrackInfo( paramIndex,trackType,&pTrack ))
|
||||
continue;
|
||||
if (pTrack)
|
||||
{
|
||||
int nkey = pTrack->GetNumKeys();
|
||||
if (nkey > 0)
|
||||
{
|
||||
timeRange.start = min( timeRange.start,pTrack->GetKeyTime(0) );
|
||||
timeRange.end = max( timeRange.end,pTrack->GetKeyTime(nkey-1) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (timeRange.start > 0)
|
||||
timeRange.start = 0;
|
||||
|
||||
m_timeRange = timeRange;
|
||||
}
|
||||
Reference in New Issue
Block a user