Files
2026-06-01 12:46:52 +02:00

689 lines
15 KiB
C++

// KSeqForm.cpp: implementation of the KSeqForm class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "KSeqForm.h"
#include "KResourceManager.h"
//#include "K3DFrustum.h"
#include "KRenderObjectBone.h"
#include "KRenderObjectMesh.h"
#include "k3dpccp.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
KSeqForm::KSeqForm()
{
m_bPendActivate = false;
m_bIsPlaying = false;
m_nStartTime = 0;
m_fRate = 4.8f;
m_pCurSeq = NULL;
m_dwColors[0] = m_dwColors[1] = m_dwColors[2] = m_dwColors[3] = 0;
K3DMatrixIdentity( m_matTransform );
K3DMatrixIdentity( m_matResult );
m_nLoopCount = 0;
m_bValidBoundCube = false;
m_bUseBlend = false;
m_nAniPartIndex = 0;
m_bTryPlayAnimation = false;
m_dwTryTime = 0;
m_nTryAniType = 0;
m_fTryRate = 4.8f;
m_pPendSeq = NULL; // floyd 2010. 4. 23 초기화 안하는데 버그의 온상이 될 듯하여 초기화
}
KSeqForm::~KSeqForm()
{
Clear();
}
void KSeqForm::ReSet()
{
if( m_pCurSeq )
{
m_pCurSeq->SetTime( 0 );
}
}
void KSeqForm::Clear()
{
m_pCurSeq = NULL;
SeqObjList::iterator it = m_vSeqObj.begin();
while ( it != m_vSeqObj.end() )
{
delete (*it);
++it;
}
m_vSeqObj.clear();
}
void KSeqForm::clearPend()
{
m_nPendStartTime = 0;
m_fPendRate = 4.8f;
m_pPendSeq = NULL;
}
void KSeqForm::GetKeyList( std::vector< const char * > &keylist )
{
SeqObjList::iterator it = m_vSeqObj.begin();
while ( it != m_vSeqObj.end() )
{
keylist.push_back( (*it)->strName.c_str() );
++it;
}
}
void KSeqForm::Initialize( DWORD dwCurTime /* = -1 */)
{
m_bIsPlaying = false;
m_fRate = 4.8f;
// m_pCurSeq = NULL;
m_dwCurTime = dwCurTime;
m_nLoopCount = 0;
m_dwAniTime = 0;
m_nStartTime = 0;
K3DMatrixIdentity( m_matTransform );
K3DMatrixIdentity( m_matResult );
}
void KSeqForm::AddSeqObject( const char *name, KSeqObject *obj )
{
SEQOBJ tempseq;
tempseq.strName = name;
if ( obj && m_vSeqObj.has( &tempseq ) == false )
{
obj->SetParentTransform( &m_matResult );
SEQOBJ *seqobj = new SEQOBJ;
seqobj->nFlag = SEQ_SUCCESS;
seqobj->pSeq = obj;
seqobj->strName = name;
seqobj->strFileName = name;
m_vSeqObj.insert( seqobj );
}
}
bool KSeqForm::AddAnimation( const char *name, const char *filename, bool bNowLoading, int nReqType )
{
if ( GetAnimationFromSeqObjList( name ) == false )
{
SEQOBJ *seqobj = new SEQOBJ;
seqobj->nFlag = SEQ_NEEDLOADING;
seqobj->pSeq = NULL;
seqobj->strName = name;
seqobj->strFileName = filename;
m_vSeqObj.insert( seqobj );
if( bNowLoading )
{ //바로 로딩
GetAnimation( name, nReqType );
}
return true;
}
return false;
}
bool KSeqForm::GetAnimationFromSeqObjList( const char *name )
{
SEQOBJ tempobj;
tempobj.strName = name;
if( m_vSeqObj.search_index( &tempobj ) != -1 )
{
return true; //이미 리스트에 등록 돼있다
}
return false; //리스트에 없다 등록하시오
}
KSeqObject *KSeqForm::GetAnimation( const char *name, int nReqType/* = 0xfffff*/ )
{
SEQOBJ *seqobj;
SEQOBJ tempobj;
tempobj.strName = name;
int idx = m_vSeqObj.search_index( &tempobj );
if ( idx != -1 )
{
seqobj = m_vSeqObj[idx];
if ( seqobj->nFlag == SEQ_NEEDLOADING )
{
//TODO : 외부에서 받거나, 옵션에서 얻어 올 수 있게 바꿔야 한다.
NX3LoadPack loadpack;
loadpack.Init();
seqobj->pSeq = KNX3Manager::GetManager()->CreateSequencer( seqobj->strFileName.c_str(), &loadpack, nReqType );
if ( seqobj->pSeq ) seqobj->nFlag = SEQ_SUCCESS;
else seqobj->nFlag = SEQ_FAILED;
}
return seqobj->pSeq;
}
return NULL;
}
bool KSeqForm::RemoveAnimation( const char *name )
{
SEQOBJ *seqobj;
SEQOBJ tempobj;
tempobj.strName = name;
int idx = m_vSeqObj.search_index( &tempobj );
if ( idx != -1 )
{
seqobj = m_vSeqObj[idx];
if ( seqobj->pSeq == m_pCurSeq )
m_pCurSeq = NULL;
delete seqobj;
m_vSeqObj.erase( idx );
return true;
}
return false;
}
bool KSeqForm::PlayAnimation( DWORD dwCurTime, const char *name, int nAniType, float fPlayRate )
{
m_bTryPlayAnimation = true;
m_strTryAnimation = name;
m_dwTryTime = dwCurTime;
m_nTryAniType = nAniType;
m_fTryRate = fPlayRate;
clearPend();
m_dwCurTime = dwCurTime;
//현재 뼈 매트릭스를 얻어 온다.
//바뀐것에 새로 설정 또는 보간 한다.
KSeqObject *newcur = GetAnimation( name );
if ( newcur == NULL )
{
StopAnimation();
return false;
}
m_nLoopCount = 0;
if( m_pCurSeq )
{
// _oprint( "Blend Info : %s\n", ((KSequencer *)m_pCurSeq)->GetName() );
_CID( GETCACHETM );
_CID( SETCACHETM );
KMsgGET_GETCACHETM cachetm;
cachetm.bUseBlend = m_bUseBlend;
m_pCurSeq->Perform( id_GETCACHETM, cachetm );
m_pCurSeq->Reset();
newcur->Reset();
newcur->Perform( id_SETCACHETM, cachetm );
}
//else
//{
// _oprint( "Not Cur Blend Info : %s\n", ((KSequencer *)newcur)->GetName() );
//}
if ( m_bIsPlaying == true && newcur == m_pCurSeq )
{
if ( ( m_nAniType == SEQTYPE_NORMAL || m_nAniType == SEQTYPE_LASTPAGE || m_nAniType == SEQTYPE_LOOP ) &&
( nAniType == SEQTYPE_REVERSE || nAniType == SEQTYPE_REVERSE_LOOP ) )
{
m_nStartTime += (m_dwCurTime - m_nStartTime) - ((DWORD)((float)m_nLength / 4.8f) - (m_dwCurTime - m_nStartTime));
}
else if ( ( nAniType == SEQTYPE_NORMAL || nAniType == SEQTYPE_LASTPAGE || nAniType == SEQTYPE_LOOP ) &&
( m_nAniType == SEQTYPE_REVERSE || m_nAniType == SEQTYPE_REVERSE_LOOP ) )
{
m_nStartTime -= (m_dwCurTime - m_nStartTime) - ((DWORD)((float)m_nLength / 4.8f) - (m_dwCurTime - m_nStartTime));
}
m_fRate = fPlayRate;
m_nAniType = nAniType;
}
else
{
m_nAniType = nAniType;
m_fRate = fPlayRate;
m_pCurSeq = newcur;
m_pCurSeq->SetColor( m_dwColors[0], m_dwColors[1], m_dwColors[2], m_dwColors[3] );
m_bIsPlaying = true;
m_nStartTime = m_dwCurTime;
m_strCurSeq = name;
m_nLength = newcur->GetInterval().GetLength();
m_bValidBoundCube = false;
}
return true;
}
bool KSeqForm::PlayOverride( DWORD dwCurTime, const char *name, float fPlayRate /* = 4.8f */ )
{
m_dwCurTime = dwCurTime;
KSeqObject *newcur = GetAnimation( name );
if ( newcur == NULL )
{
return false;
}
if( m_pCurSeq )
{
if ( m_pPendSeq == NULL )
{
m_pPendSeq = m_pCurSeq;
m_nPendAniType = m_nAniType;
m_nPendStartTime = m_nStartTime;
m_nPendLength = m_nLength;
m_fPendRate = m_fRate;
m_strPendSeq = m_strCurSeq;
}
_CID( GETCACHETM );
_CID( SETCACHETM );
KMsgGET_GETCACHETM cachetm;
m_pCurSeq->Perform( id_GETCACHETM, cachetm );
newcur->Perform( id_SETCACHETM, cachetm );
}
m_nLoopCount = 0;
m_nAniType = SEQTYPE_NORMAL;
m_fRate = fPlayRate;
m_pCurSeq = newcur;
m_pCurSeq->SetColor( m_dwColors[0], m_dwColors[1], m_dwColors[2], m_dwColors[3] );
m_bIsPlaying = true;
m_nStartTime = m_dwCurTime;
m_strCurSeq = name;
m_nLength = newcur->GetInterval().GetLength();
m_bValidBoundCube = false;
return true;
}
void KSeqForm::SetAniTime( DWORD dwTime )
{
if( m_pCurSeq ) m_pCurSeq->SetTime( dwTime );
}
void KSeqForm::SetAnimationPos(int nPosFlag)
{
if(!m_pCurSeq )
return;
switch(nPosFlag )
{
case SEQPOS_BEGIN:
m_nStartTime = m_dwCurTime;
break;
case SEQPOS_END:
m_nStartTime = (DWORD)(m_dwCurTime - ((float)m_nLength / m_fRate) );
break;
}
}
void KSeqForm::ChangeAnimationType(int nAniType)
{
m_nAniType = nAniType;
if(m_bIsPlaying)
{
DWORD time = DWORD((m_dwCurTime - m_nStartTime) * m_fRate);
if(m_nLength > 0)
time %= (m_nLength + 1);
time =(DWORD)( time / m_fRate );
m_nStartTime = m_dwCurTime - time;
}
else
{
m_bIsPlaying = true;
m_nStartTime = m_dwCurTime;
}
}
void KSeqForm::StopAnimation()
{
clearPend();
m_strCurSeq = "";
m_bIsPlaying = false;
m_pCurSeq = NULL;
m_nStartTime = 0;
m_fRate = 4.8f;
}
void KSeqForm::SetParentTransform( const K3DMatrix *pMatParent, const K3DMatrix *pMatAttach /*= NULL*/, BOOL bRotationLock /*= FALSE*/ )
{
KSeqObject::SetParentTransform( pMatParent, pMatAttach, bRotationLock );
if( m_pCurSeq )
{
m_pCurSeq->SetParentTransform( pMatParent, pMatAttach, bRotationLock );
}
}
KSeqObject* KSeqForm::Clone()
{
KSeqForm *newobj = new KSeqForm;
SeqObjList::iterator it = m_vSeqObj.begin();
SEQOBJ *obj;
while ( it != m_vSeqObj.end() )
{
obj = (*it); it++;
newobj->AddAnimation( obj->strName.c_str(), obj->strFileName.c_str() );
}
return reinterpret_cast<KSeqObject*>(newobj);
}
void KSeqForm::SetColor( DWORD c1, DWORD c2 /* = 0 */, DWORD c3 /* = 0 */, DWORD c4 /* = 0 */, short nMode /*= 0*/ )
{
if ( m_dwColors[0] != c1 || m_dwColors[1] != c2 || m_dwColors[2] != c3 || m_dwColors[3] != c4 )
{
m_nColorizedMode = nMode;
m_dwColors[0] = c1;
m_dwColors[1] = c2;
m_dwColors[2] = c3;
m_dwColors[3] = c4;
UpdateColors();
}
}
void KSeqForm::UpdateColors()
{
m_pCurSeq->SetColor( m_dwColors[0], m_dwColors[1], m_dwColors[2], m_dwColors[3], m_nColorizedMode );
}
void KSeqForm::realizeTime()
{
if ( m_pMatAttach != NULL && m_pMatParent != NULL )
{
K3DMatrix matTemp;
K3DMatrixIdentity( matTemp );
K3DMatrixMultiply( matTemp, *m_pMatAttach, *m_pMatParent );
K3DMatrixMultiply( m_matResult, m_matTransform, matTemp );
}
else if ( m_pMatParent != NULL )
K3DMatrixMultiply( m_matResult, m_matTransform, *m_pMatParent );
else
m_matResult = m_matTransform;
/* if ( m_pMatParent != NULL )
K3DMatrixMultiply( m_matResult, m_matTransform, *m_pMatParent );
else
m_matResult = m_matTransform;*/
}
void KSeqForm::TryPlayAnimation()
{
if( m_bTryPlayAnimation && m_pCurSeq == NULL )
{
PlayAnimation( m_dwTryTime, m_strTryAnimation.c_str(), m_nTryAniType, m_fTryRate );
if( m_pCurSeq )
{
m_bTryPlayAnimation = false;
m_strTryAnimation = "";
m_dwTryTime = 0;
m_nTryAniType = 0;
m_fTryRate = 4.8f;
}
}
}
int KSeqForm::Process( DWORD dwTime )
{
int process_state = (m_bIsPlaying) ? (SEQINFO_PLAYING) : (SEQINFO_STOPPED);
m_bPendActivate = false;
if( m_pCurSeq == NULL )
return SEQINFO_STOPPED;
if ( dwTime != m_dwCurTime )
{
m_dwCurTime = dwTime;
//DWORD dwCurTime = m_dwCurTime;
//DWORD dwStartTime = m_nStartTime;
DWORD time = DWORD((m_dwCurTime - DWORD(m_nStartTime)) * m_fRate);
if ( m_nAniType == SEQTYPE_LOOP )
{
if ( m_nLength > 0 )
{
time %= (m_nLength+1);
if ( time < m_pCurSeq->GetCurTime() )
{
process_state = SEQINFO_LOOPWRAP;
m_nLoopCount++;
}
}
else time = 0;
m_pCurSeq->SetTime( time );
}
else if ( m_nAniType == SEQTYPE_NORMAL || m_nAniType == SEQTYPE_LASTPAGE )
{
if ( time <= m_nLength )
{
m_pCurSeq->SetTime( time );
}
else
{
//show last frame
m_pCurSeq->SetTime( m_nLength );
m_bIsPlaying = false;
process_state = SEQINFO_STOPPED;
}
}
else if ( m_nAniType == SEQTYPE_REVERSE_LOOP )
{
if ( m_nLength > 0 )
{
time %= (m_nLength+1);
if ( time > m_pCurSeq->GetCurTime() )
{
process_state = SEQINFO_LOOPWRAP;
m_nLoopCount++;
}
}
else time = 0;
m_pCurSeq->SetTime( m_nLength - time );
}
else // SEQTYPE_REVERSE
{
if ( time <= m_nLength )
{
m_pCurSeq->SetTime( m_nLength - time );
}
else
{
//show last frame
m_pCurSeq->SetTime( 0 );
m_bIsPlaying = false;
process_state = SEQINFO_STOPPED;
}
}
m_dwAniTime = time;
if ( m_pPendSeq != NULL && process_state == SEQINFO_STOPPED )
{
//Override Ani 가 종료된 상태
_CID( GETCACHETM );
_CID( SETCACHETM );
KMsgGET_GETCACHETM cachetm;
m_pCurSeq->Perform( id_GETCACHETM, cachetm );
m_pPendSeq->Perform( id_SETCACHETM, cachetm );
//Pending Ani 복구
m_nAniType = m_nPendAniType;
m_nStartTime = m_nPendStartTime;
m_nLength = m_nPendLength;
m_fRate = m_fPendRate;
m_strCurSeq = m_strPendSeq;
m_pCurSeq = m_pPendSeq;
clearPend();
m_bPendActivate = true;
process_state = SEQINFO_PLAYING;
m_bIsPlaying = true;
time = DWORD((m_dwCurTime - DWORD(m_nStartTime)) * m_fRate);
if ( m_nAniType == SEQTYPE_NORMAL || m_nAniType == SEQTYPE_LASTPAGE )
{
if ( time > m_nLength )
{
m_pCurSeq->SetTime( m_nLength );
m_bIsPlaying = false;
process_state = SEQINFO_STOPPED;
}
}
}
}
return process_state;
}
void *KSeqForm::Perform( KID id, KArg& msg )
{
if ( m_pCurSeq )
{
return m_pCurSeq->Perform( id, msg );
}
return NULL;
}
void KSeqForm::SetTransform( const K3DMatrix &mat )
{
m_matTransform = mat;
}
void KSeqForm::ClipTest( const K3DVector* pFrustum)
{
if ( m_pCurSeq )
{
// 네가티브스케일을 지닌 cube때문에 cube를 항상 재정의함
K3DBoundRotCube cube = GetBoundCube();
cube.AddCube(*GetBoundCube());
m_bIsClip = !KPCCP::nonuniformcube_collide_nonuniformcube(pFrustum, cube.GetVertices());
}
}
void KSeqForm::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat )
{
if ( m_pCurSeq )
{
// GetBoundCube()->Render( viewport );
realizeTime();
m_pCurSeq->SetVisibility( m_fMasterVisibility );
m_pCurSeq->Render( viewport, flag, pAttachMat );
}
}
void KSeqForm::buildBoundCube()
{
_CID( REQ_BOUNDBOX );
KMsgREQ_BOUNDBOX msg;
Perform( id_REQ_BOUNDBOX, msg );
if ( msg.IsValid() )
m_BoundCube = msg.GetCube();
// else
// assert(0);
m_bValidBoundCube = true;
}
K3DBoundRotCube* KSeqForm::GetBoundCube( const char * pName )
{
realizeTime();
if( pName == NULL )
{
if( m_bValidBoundCube == false )
buildBoundCube();
}
else //특정 Cube를 Get
{
_CID( REQ_BOUNDBOXEX );
KMsgREQ_BOUNDBOXEX msg;
msg.pSearchName = pName;
Perform( id_REQ_BOUNDBOXEX, msg );
if ( msg.IsValid() )
m_BoundCube = msg.GetCube();
m_bValidBoundCube = true;
}
m_BoundCube.GetVertices();
return &m_BoundCube;
}
void KSeqForm::SetViewVector( const K3DVector &view )
{
m_matTransform._11 = -view.y;
m_matTransform._21 = -view.x;
m_matTransform._31 = 0;
m_matTransform._12 = view.x;
m_matTransform._22 = -view.y;
m_matTransform._32 = 0;
}
void KSeqForm::SetRoll( float rad )
{
K3DMatrix myRotate;
K3DMatrixIdentity(myRotate);
//K3DMatrixRotationY( myRotate, 30 );
K3DMatrixRotationY( myRotate, rad );
K3DMatrix res;
K3DMatrixMultiply( res, myRotate, m_matTransform );
//m_matTransform = myRotate;
m_matTransform = res;
}
void KSeqForm::RotateX( float rad )
{
K3DMatrix myRotate;
K3DMatrixIdentity(myRotate);
K3DMatrixRotationX( myRotate, rad );
K3DMatrix res;
K3DMatrixMultiply( res, myRotate, m_matTransform );
m_matTransform = res;
}
void KSeqForm::RotateY( float rad )
{
K3DMatrix myRotate;
K3DMatrixIdentity(myRotate);
K3DMatrixRotationY( myRotate, rad );
K3DMatrix res;
K3DMatrixMultiply( res, myRotate, m_matTransform );
m_matTransform = res;
}
void KSeqForm::RotateZ( float rad )
{
K3DMatrix myRotate;
K3DMatrixIdentity(myRotate);
K3DMatrixRotationZ( myRotate, rad );
K3DMatrix res;
K3DMatrixMultiply( res, myRotate, m_matTransform );
m_matTransform = res;
}
void KSeqForm::SetPosition( const K3DVector &pos )
{
m_matTransform.SetPosVector( pos );
}
void KSeqForm::SetPosition( float x, float y, float z )
{
m_matTransform.SetPosVector( K3DVector( x, y, z ) );
}
const char* KSeqForm::GetSeqObjName()
{
if( m_pCurSeq ) return m_pCurSeq->GetName();
return NULL;
}