// 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(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; }