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

1386 lines
30 KiB
C++

// KSeqAvatar.cpp: implementation of the KSeqAvatar class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "KViewport.h"
#include ".\kseqavatar.h"
#include "KResourceManager.h"
#include "KRenderObjectBone.h"
#include "KRenderObjectMesh.h"
//#include "Util.h"
#include <toolkit/SafeTickCount.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BOOL KSeqAvatar::m_bEffectPosRenderFlag = FALSE;
BOOL KSeqAvatar::m_sMeshRenderFlag = TRUE;
KSeqAvatar::KSeqAvatar( int nAniPartIndex )
{
m_ViewVectorX = K3DVector(1,0,0); //좌우
m_ViewVectorZ = K3DVector(1,0,0); //상하
m_BodyVector = K3DVector(1,0,0); //몸통
m_CurViewVector = K3DVector(1,0,0); //현재 뷰~
m_nPrevViewVector = K3DVector(1,0,0); //전 뷰~
m_vViewTarget = K3DVector(0,0,0); //보는 위치~
for( int i(0); MPART_MAX>i; i++ )
{
m_pMeshPart[i] = NULL;
m_bMeshRender[i] = FALSE;
}
for( int i(0); MDECOPART_MAX>i ; ++i )
{
m_pDecoMeshPart[i] = NULL;
m_bDecoMeshRender[i] = FALSE;
}
for( int i(0); ATTACH_MAX>i; i++ )
{
m_pItemPart[i] = NULL;
m_bItemRender[i] = FALSE;
}
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
m_pEffectPos[i] = NULL;
m_bEffectPos[i] = FALSE;
}
for( int i(0); BONE_EFFECT_MAX>i; i++ )
{
m_pBoneEffect[i] = NULL;
m_bBoneEffect[i] = FALSE;
m_nBoneEffectIndex[i] = -1;
}
m_bBoneEffectCheck = FALSE;
m_bRenderRotCube = FALSE;
m_bItemCheck = FALSE;
m_bEffectPosCheck = FALSE;
m_bMeshCheck = FALSE;
m_bDecoMeshCheck = FALSE;
K3DMatrixIdentity( m_matTransform );
m_nAniPartIndex = nAniPartIndex;
m_decoShoulderPrevTime = 0;
}
KSeqAvatar::~KSeqAvatar()
{
Clear();
}
void KSeqAvatar::Clear()
{
KSeqForm::Clear();
for( int i(0); MPART_MAX>i; i++ )
{
SAFE_DELETE( m_pMeshPart[i]);
m_bMeshRender[i] = FALSE;
}
for( int i(0); MDECOPART_MAX>i ; ++i )
{
SAFE_DELETE( m_pDecoMeshPart[i] );
m_bDecoMeshRender[i] = FALSE;
}
m_bDecoMeshCheck = FALSE;
for( int i(0); ATTACH_MAX>i; i++ )
{
SAFE_DELETE( m_pItemPart[i] );
m_bItemRender[i] = FALSE;
}
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
SAFE_DELETE( m_pEffectPos[i] );
m_bEffectPos[i] = FALSE;
}
for( int i(0); BONE_EFFECT_MAX>i; i++ )
{
SAFE_DELETE( m_pBoneEffect[i] );
m_bBoneEffect[i] = FALSE;
m_nBoneEffectIndex[i] = -1;
}
}
void KSeqAvatar::ClipTest( const K3DVector* pFrustrum )
{
/// 2010.01.03 - prodongi
bool isMeshPart = false;
for( int i(0); MPART_MAX>i; i++ )
{
if( m_pMeshPart[i] )
{
isMeshPart = true;
m_pMeshPart[i]->ClipTest( pFrustrum );
}
}
/// 2011.01.03 일반 메쉬가 없을 때는 데코 메쉬를 검사해야 된다 - prodongi
if (!isMeshPart)
{
for (int i = 0; i < MDECOPART_MAX; ++i)
{
if (m_pDecoMeshPart[i])
m_pDecoMeshPart[i]->ClipTest(pFrustrum);
}
}
}
bool KSeqAvatar::GetIsClip()
{
/// 2010.01.03 - prodongi
bool isMeshPart = false;
bool bIsClip = true;
for( int i(0); MPART_MAX>i; i++ )
{
if( m_pMeshPart[i] )
{
isMeshPart = true;
bIsClip = m_pMeshPart[i]->GetIsClip();
if( !bIsClip ) return bIsClip;
}
}
/// 2011.01.03 일반 메쉬가 없을 때는 데코 메쉬를 검사해야 된다 - prodongi
if (!isMeshPart)
{
for (int i = 0; i < MDECOPART_MAX; ++i)
{
if (m_pDecoMeshPart[i])
{
bIsClip = m_pDecoMeshPart[i]->GetIsClip();
if (!bIsClip) return bIsClip;
}
}
}
return bIsClip;
}
void KSeqAvatar::ClearAnimation()
{
StopAnimation();
KSeqForm::Clear();
}
void KSeqAvatar::DelAnimation( const char *pszAniKey )
{
RemoveAnimation( pszAniKey );
}
bool KSeqAvatar::AddAnimation( const char *filename, BOOL bOld, bool bNowLoading )
{
std::string strKey;
CStringUtil::GetStrKey( filename, '_' , strKey, bOld );
if( strKey.length() <= 0 ) return false;
return KSeqForm::AddAnimation( strKey.c_str(), filename, bNowLoading );
}
void KSeqAvatar::ClearMesh()
{
for( int i(0); MPART_MAX>i; i++ )
{
SAFE_DELETE( m_pMeshPart[i]); //이미 있는것 제거..
m_bMeshRender[i] = FALSE;
}
for( int i(0); MDECOPART_MAX>i; ++i )
{
SAFE_DELETE( m_pDecoMeshPart[i] );
m_bDecoMeshRender[i] = FALSE;
}
for( int i(0); ATTACH_MAX>i; i++ )
{
SAFE_DELETE( m_pItemPart[i] );
m_bItemRender[i] = FALSE;
}
}
void KSeqAvatar::AddBoneEffect( int nIndex, KSeqObject *obj )
{
SAFE_DELETE( m_pBoneEffect[nIndex]); //이미 있는것 제거..
m_pBoneEffect[nIndex] = static_cast<KSeqForm*>(obj);
if( obj )
{
m_bBoneEffect[nIndex] = true;
m_bBoneEffectCheck = TRUE;
obj->SetParentTransform( m_pMatParent, NULL, TRUE );
}
else
{
m_bBoneEffect[nIndex] = false;
m_nBoneEffectIndex[nIndex] = -1;
}
}
bool KSeqAvatar::AddBoneEffect( int nIndex, const char *bonename, const char *filename )
{
if( nIndex < 0 || nIndex >= BONE_EFFECT_MAX ) return false;
NX3LoadPack loadpack;
loadpack.Init();
_CID( GETBONEMATRIX );
KSeqForm* obj = new KSeqForm;
obj->AddAnimation( "default", filename );
obj->PlayAnimation( m_dwTime, "default", SEQTYPE_LOOP );
AddBoneEffect( nIndex, obj );
if( !obj )
{
_oprint( "!!!Graphic resource Bone Effect Error: %s\n", filename );
return false;
}
else
{
KMsgGET_BONEMATRIX msg;
msg.strBoneName = bonename;
Perform( id_GETBONEMATRIX, msg );
m_nBoneEffectIndex[nIndex] = msg.nBoneMatIndex;
if( m_bBoneEffect[nIndex] && m_pBoneEffect[nIndex] && m_nBoneEffectIndex[nIndex] != -1 )
{
m_pBoneEffect[nIndex]->SetParentTransform( m_pMatParent, msg.pBoneMat );
// if( m_pCurSeq ) m_pCurSeq->SetAttachEffectBone( m_nBoneEffectIndex[nIndex], m_pBoneEffect[nIndex] );
}
}
return true;
}
bool KSeqAvatar::AddEffectPos( int nAttachIndex, const char *filename )
{
//TODO : 외부에서 받거나, 옵션에서 얻어 올 수 있게 바꿔야 한다.
NX3LoadPack loadpack;
loadpack.Init();
KSeqObject *obj = KNX3Manager::GetManager()->CreateSequencer( filename, &loadpack );
AddEffectPos( nAttachIndex, obj );
if( !obj )
{
_oprint( "Graphic Resource Effect Pos Error: %s\n", filename );
return false;
}
return true;
}
void KSeqAvatar::AddMorphMesh( KMsgSET_MORPHMESH* pMsg )
{
_CID( SET_MORPHMESH );
for( int i(0); MPART_MAX>i; i++ )
{
if( m_pMeshPart[i] )
m_pMeshPart[i]->Perform( id_SET_MORPHMESH, *pMsg );
}
}
void KSeqAvatar::SetFixTexture( KMsgSET_FIXTEXTURE* pMsg )
{
_CID( SET_FIX_TEXTURE );
for( int i(0); MPART_MAX>i; ++i )
{
if( m_pMeshPart[i] )
m_pMeshPart[i]->Perform( id_SET_FIX_TEXTURE, *pMsg );
}
for( int i(0); MDECOPART_MAX>i; ++i )
{
if( m_pDecoMeshPart[i] )
m_pDecoMeshPart[i]->Perform( id_SET_FIX_TEXTURE, *pMsg );
}
for( int i(0); ATTACH_MAX>i; ++i )
{
if( m_bItemRender[i] && m_pItemPart[i] )
m_pItemPart[i]->Perform( id_SET_FIX_TEXTURE, *pMsg );
}
}
void KSeqAvatar::AddEffectPos( int nAttachIndex, KSeqObject *obj )
{
SAFE_DELETE( m_pEffectPos[nAttachIndex]); //이미 있는것 제거..
m_pEffectPos[nAttachIndex] = obj;
m_bEffectPos[nAttachIndex] = false;
if( obj )
{
m_bEffectPos[nAttachIndex] = true;
m_bEffectPosCheck = TRUE;
// if( m_bEffectPosCheck == FALSE )
// obj->Perform( id_SETFORCERENDER_FLAG, NULL ); //강제로 Off
obj->SetParentTransform( &m_matResult, NULL, TRUE );
}
}
//아바타 살들~
KSeqObject *KSeqAvatar::GetMesh( int nIndex )
{
assert(nIndex>=0 && nIndex<MPART_MAX);
return m_pMeshPart[nIndex];
}
int KSeqAvatar::IsExistMesh( int nIndex )
{
if( nIndex>=0 && nIndex<MPART_MAX)
{
if( m_pMeshPart[nIndex] != NULL )
return 1;
}
return 0;
}
KSeqObject *KSeqAvatar::GetDecoMesh( int nIndex )
{
assert(nIndex>=0 && nIndex<MDECOPART_MAX);
return m_pDecoMeshPart[nIndex];
}
int KSeqAvatar::IsExistDecoMesh( int nIndex )
{
if( nIndex>=0 && nIndex<MDECOPART_MAX)
{
if( m_pDecoMeshPart[nIndex] != NULL )
return 1;
}
return 0;
}
// 2010.06.10 - prodongi
bool KSeqAvatar::isRenderDecoMesh(int index)
{
if( index>=0 && index<MDECOPART_MAX)
{
return m_bDecoMeshRender[index];
}
return false;
}
// 2010.06.14 - prodongi
bool KSeqAvatar::isRenderMesh(int index)
{
if( index>=0 && index<MPART_MAX)
{
return m_bMeshRender[index];
}
return false;
}
void KSeqAvatar::AddMesh( int nIndex, KSeqObject *obj )
{
SAFE_DELETE( m_pMeshPart[nIndex]); //이미 있는것 제거..
m_pMeshPart[nIndex] = obj;
m_bMeshRender[nIndex] = false;
_CID( GETMESH_NAME );
if ( obj )
{
m_bMeshCheck = true;
m_bMeshRender[nIndex] = true;
//몸통에 1st가 있으면, Foot, Hand의 겹치는 부분을 Off
//없으면, Foot, Hand 에 2nd 가 붙으면, 몸통의 교차 부분 Off
//
//Hand, Foot 일 경우 Body와 겹치는 부분이 있으면, Body의 Mesh들을 Render Off 한다.
if( nIndex == MPART_FOOT )
{
KMsgGET_MESHNAME msg;
obj->Perform( id_GETMESH_NAME, msg );
//모두 On
SetRenderFlag( "leg", TRUE );
for( unsigned int i(0); msg.vNameList.size()>i; i++ )
{
const char * pName = msg.vNameList[i];
//상위
if( strstr( pName, "leg" ) != NULL ) //겹치는게 있으면서 Off
{
SetRenderFlag( "leg", FALSE );
}
}
}
else if( nIndex == MPART_HAND )
{
KMsgGET_MESHNAME msg;
obj->Perform( id_GETMESH_NAME, msg );
//모두 On
SetRenderFlag( "arm", true );
for( unsigned int i(0); msg.vNameList.size()>i; i++ )
{
const char * pName = msg.vNameList[i];
//하위
if( strstr( pName, "arm" ) != NULL ) //겹치는게 있으면서 Off
{
SetRenderFlag( "arm", false );
}
}
}
obj->SetParentTransform( &m_matResult );
}
}
bool KSeqAvatar::AddMesh( int nIndex, const char *filename )
{
//TODO
NX3LoadPack loadpack;
loadpack.Init();
#ifdef _RAC
KSeqObject *obj = KNX3Manager::GetManager()->CreateSequencer( filename, &loadpack, (KNX3Manager::SEQTYPE_ALL & (~KNX3Manager::SEQTYPE_CAMERA)) );
#else
KSeqObject *obj = KNX3Manager::GetManager()->CreateSequencer( filename, &loadpack, (KNX3Manager::SEQTYPE_ALL) );
#endif
AddMesh( nIndex, obj );
if( obj )
return true;
else
{
#ifdef _DEBUG
if( strlen(filename) > 0 )
_oprint( "!!!Resource Not Found (AddMesh) : %s\n", filename );
#endif
return false;
}
return true;
}
void KSeqAvatar::AddDecoMesh( int nIndex, KSeqObject *obj )
{
SAFE_DELETE( m_pDecoMeshPart[nIndex]); //이미 있는것 제거..
m_pDecoMeshPart[nIndex] = obj;
m_bDecoMeshRender[nIndex] = FALSE;
_CID( GETMESH_NAME );
if ( obj )
{
m_bDecoMeshCheck = TRUE;
m_bDecoMeshRender[nIndex] = TRUE;
//몸통에 1st가 있으면, Foot, Hand의 겹치는 부분을 Off
//없으면, Foot, Hand 에 2nd 가 붙으면, 몸통의 교차 부분 Off
//
//Hand, Foot 일 경우 Body와 겹치는 부분이 있으면, Body의 Mesh들을 Render Off 한다.
/* if( nIndex == MDECOPART_FOOT )
{
KMsgGET_MESHNAME msg;
obj->Perform( id_GETMESH_NAME, msg );
//모두 On
SetRenderFlag( "leg", TRUE );
for( unsigned int i(0); msg.vNameList.size()>i; i++ )
{
const char * pName = msg.vNameList[i];
//상위
if( strstr( pName, "leg" ) != NULL ) //겹치는게 있으면서 Off
{
SetRenderFlag( "leg", FALSE );
}
}
}
else if( nIndex == MDECOPART_HAND )
{
KMsgGET_MESHNAME msg;
obj->Perform( id_GETMESH_NAME, msg );
//모두 On
SetRenderFlag( "arm", true );
for( unsigned int i(0); msg.vNameList.size()>i; i++ )
{
const char * pName = msg.vNameList[i];
//하위
if( strstr( pName, "arm" ) != NULL ) //겹치는게 있으면서 Off
{
SetRenderFlag( "arm", false );
}
}
}*/
obj->SetParentTransform( &m_matResult );
}
}
bool KSeqAvatar::AddDecoMesh( int nIndex, const char *filename )
{
//TODO
NX3LoadPack loadpack;
loadpack.Init();
#ifdef _RAC
KSeqObject *obj = KNX3Manager::GetManager()->CreateSequencer( filename, &loadpack, (KNX3Manager::SEQTYPE_ALL & (~KNX3Manager::SEQTYPE_CAMERA)) );
#else
KSeqObject *obj = KNX3Manager::GetManager()->CreateSequencer( filename, &loadpack, (KNX3Manager::SEQTYPE_ALL) );
#endif
AddDecoMesh( nIndex, obj );
if( obj ) return true;
else return false;
return true;
}
//아바타 무기 링크들~
void KSeqAvatar::AddAttachItem( int nIndex, KSeqObject *obj )
{
SAFE_DELETE( m_pItemPart[nIndex] );
m_pItemPart[nIndex] = static_cast<KSeqForm*>(obj);
_CID ( SETRENDER_FLAG );
if ( obj )
{
m_bItemCheck = true;
if( nIndex == ATTACH_HAND_LEFT )
{
KMsgSET_RENDERFLAG rendermsg;
rendermsg.pName = "right";
rendermsg.bRenderFlag = FALSE;
obj->Perform( id_SETRENDER_FLAG, rendermsg);
}
else if( nIndex == ATTACH_HAND_RIGHT )
{
KMsgSET_RENDERFLAG rendermsg;
rendermsg.pName = "left";
rendermsg.bRenderFlag = FALSE;
obj->Perform( id_SETRENDER_FLAG, rendermsg);
}
m_bItemRender[nIndex] = TRUE;
obj->SetParentTransform( &m_matResult );
}
}
void KSeqAvatar::AddAttachItem( int nIndex, const char *filename )
{
//UV Ani 있는 것이 있음.
KSeqForm* obj = new KSeqForm;
obj->AddAnimation( "default", filename, true );
obj->PlayAnimation( m_dwTime, "default", SEQTYPE_LOOP );
AddAttachItem( nIndex, obj );
//임시
//m_bRenderRotCube = true;
}
void KSeqAvatar::SetItemRenderFlag( int nIndex, BOOL bRenderFlag )
{
m_bItemRender[nIndex] = bRenderFlag;
}
void KSeqAvatar::SetItemRenderFlag( BOOL bRenderFlag )
{
_CID( SETRENDER_FLAG );
KMsgSET_RENDERFLAG msg;
msg.bRenderFlag = bRenderFlag;
msg.pName = "NULL";
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_bItemRender[i] && m_pItemPart[i] )
m_pItemPart[i]->Perform( id_SETRENDER_FLAG , msg );
}
}
// Bone sequencer포인터를 직접 돌려줌
KBoneSeqObject* KSeqAvatar::getBoneSequencer()
{
if (m_pCurSeq) {
return (KBoneSeqObject*)((KSequencer*)m_pCurSeq)->GetSeqObject(0);
}
return NULL;
}
//Perform로 바꾸자~
float KSeqAvatar::GetHeadZ()
{
if(m_pCurSeq)
{
KBoneSeqObject* pBoneSeq = (KBoneSeqObject*)((KSequencer*)m_pCurSeq)->GetSeqObject(0);
if( pBoneSeq )
return pBoneSeq->GetHeadZ();
}
return 0.f;
}
//Perform로 바꾸자~
void KSeqAvatar::GetHandPos( K3DVector &posLeft, K3DVector &posRight )
{
if(m_pCurSeq)
{
KBoneSeqObject* pBoneSeq = (KBoneSeqObject*)((KSequencer*)m_pCurSeq)->GetSeqObject(0);
if( pBoneSeq )
{
pBoneSeq->GetHandLeft( posLeft );
pBoneSeq->GetHandRight( posRight );
}
}
}
bool KSeqAvatar::PlayAnimation( DWORD dwCurTime, const char *name, int nAniType, float fPlayRate )
{
/// 2011.01.25 false 체크 - prodongi
if (!KSeqForm::PlayAnimation( dwCurTime, name, nAniType, fPlayRate ))
return false;
SetDeform(); //현재 애니메이션과 메쉬 스키닝
SetAttach(); //아이템 붙이기
SetAttachEffectPos(); //이펙트 위치 붙이기
SetAttachEffectBone();
return true;
}
bool KSeqAvatar::PlayOverride( DWORD dwCurTime, const char *name, float fPlayRate /* = 4.8f */ )
{
if ( KSeqForm::PlayOverride( dwCurTime, name, fPlayRate ) == true )
{
SetDeform();
SetAttach();
SetAttachEffectPos();
SetAttachEffectBone();
return true;
}
return false;
}
KSeqObject* KSeqAvatar::Clone()
{
KSeqAvatar *newobj = new KSeqAvatar;
SeqObjList::iterator it = m_vSeqObj.begin();
//Animation
while ( it != m_vSeqObj.end() )
{
newobj->KSeqForm::AddAnimation( (*it)->strName.c_str(), (*it)->strFileName.c_str() );
++it;
}
//살들~
for( int i(0); MPART_MAX>i; i++ )
{
if( m_pMeshPart[i] )
newobj->AddMesh( i, m_pMeshPart[i]->Clone() );
}
//치장용
for( int i(0); MDECOPART_MAX>i ; ++i )
{
if( m_pDecoMeshPart[i] )
newobj->AddDecoMesh( i, m_pDecoMeshPart[i]->Clone() );
}
//아이템들
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_pItemPart[i] )
newobj->AddAttachItem( i, m_pItemPart[i]->Clone() );
}
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
if( m_pEffectPos[i] )
newobj->AddEffectPos( i, m_pEffectPos[i]->Clone() );
}
for( int i(0); BONE_EFFECT_MAX>i; i++ )
{
if( m_pBoneEffect[i] )
newobj->AddBoneEffect( i, m_pBoneEffect[i]->Clone() );
}
return (KSeqObject*)(newobj);
}
int KSeqAvatar::Process( DWORD dwTime )
{
int process_state = KSeqForm::Process( dwTime );
if ( m_pCurSeq ) {
KSequencer *kseq=dynamic_cast<KSequencer *>(m_pCurSeq);
if (kseq!=NULL) kseq->Process( kseq->GetCurTime() );
}
if ( isPendActivate() )
{
SetDeform(); //현재 애니메이션과 메쉬 스키닝
SetAttach(); //아이템 붙이기
SetAttachEffectPos();
SetAttachEffectBone();
}
//Mesh
if( m_bMeshCheck )
{
for( int i(0); MPART_MAX>i; i++ )
{
if( m_bMeshRender[i] && m_pMeshPart[i] )
m_pMeshPart[i]->SetTime( dwTime );
}
}
if( m_bDecoMeshCheck )
{
for( int i(0); MDECOPART_MAX>i ; ++i )
{
if( m_bDecoMeshRender[i] && m_pDecoMeshPart[i] )
{
const KInterval inter = m_pDecoMeshPart[i]->GetInterval();
if ((i == MDECOPART_SHOULDER || i == MDECOPART_SHOULDER2 ) && (inter.GetEnd() != 0)) // 어깨치창아이템이고 애니메이션이 있을 경우 재생
{
/// 2012.08.13 꾸미기 어깨 이전 애니메이션 시간이 static으로 되어 있어서 한 유저의 꾸미기 어깨만 애니메이션이 되고 있었다.
/// static을 클래스 멤버 변수로 바꿈, 그런데 왜 꾸미기 어깨만 따로 관리를 하고 있나?,
/// SetAniTime에서도 SetTime을 하고 있는데, 왜 여기서 따로 관리를 하나? - prodongi
if (0 == m_decoShoulderPrevTime) m_decoShoulderPrevTime = dwTime;
DWORD advance = (DWORD)((dwTime - m_decoShoulderPrevTime) * 4.8f);
DWORD nowTime = m_pDecoMeshPart[i]->GetCurTime();
DWORD newTime = nowTime + advance;
newTime = newTime % inter.GetEnd();
m_pDecoMeshPart[i]->SetTime( newTime );
m_decoShoulderPrevTime = dwTime;
}
}
}
}
//Item
if( m_bItemCheck )
{
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_bItemRender[i] && m_pItemPart[i] )
m_pItemPart[i]->Process( dwTime );
}
}
//Effect Pos
if( m_bEffectPosCheck )
{
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
if( m_bEffectPos[i] && m_pEffectPos[i] )
m_pEffectPos[i]->SetTime( dwTime );
}
}
//Bone Effect
if( m_bBoneEffectCheck )
{
for( int i(0); BONE_EFFECT_MAX>i; i++ )
{
if( m_bBoneEffect[i] && m_pBoneEffect[i] )
m_pBoneEffect[i]->Process( dwTime );
}
}
return process_state;
}
void KSeqAvatar::SetAniTime( DWORD dwTime )
{
KSeqForm::SetAniTime(dwTime);
//if( m_pCurSeq ) m_pCurSeq->SetTime( dwTime );
if ( m_pCurSeq ) {
KSequencer *kseq=dynamic_cast<KSequencer *>(m_pCurSeq);
if (kseq!=NULL) kseq->Process( kseq->GetCurTime() );
}
//Mesh
for( int i(0); MPART_MAX>i; i++ )
{
if( m_bMeshRender[i] && m_pMeshPart[i] )
m_pMeshPart[i]->SetTime( dwTime );
}
if( m_bDecoMeshCheck )
{
for( int i(0); MDECOPART_MAX>i; ++i )
{
if( m_bDecoMeshRender[i] && m_pDecoMeshPart[i] )
m_pDecoMeshPart[i]->SetTime( dwTime );
}
}
if( m_bItemCheck )
{
//Item
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_bItemRender[i] && m_pItemPart[i] )
m_pItemPart[i]->Process( GetSafeTickCount() );
}
}
//Effect Pos
if( m_bEffectPosCheck )
{
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
if( m_bEffectPos[i] && m_pEffectPos[i] )
m_pEffectPos[i]->SetTime( dwTime );
}
}
//Bone Effect
if( m_bBoneEffectCheck )
{
for( int i(0); BONE_EFFECT_MAX>i; i++ )
{
if( m_bBoneEffect[i] && m_pBoneEffect[i] )
m_pBoneEffect[i]->SetTime( dwTime );
}
}
}
const char* KSeqAvatar::GetMeshSeqObjName( int nMeshIndex )
{
if( nMeshIndex >= 0 && nMeshIndex < MPART_MAX )
{
if( m_pMeshPart[nMeshIndex] )
return m_pMeshPart[nMeshIndex]->GetName();
}
return NULL;
}
void *KSeqAvatar::MeshPerform( int nMeshIndex, KID id, KArg& msg )
{
// Apply only to the skin mesh
if( nMeshIndex >= 0 && nMeshIndex < MPART_MAX )
{
if( m_pMeshPart[nMeshIndex] )
return m_pMeshPart[nMeshIndex]->Perform( id, msg );
}
return NULL;
}
void *KSeqAvatar::DecoMeshPerform( int nMeshIndex, KID id, KArg& msg )
{
//살~ Mesh 한테만~
if( nMeshIndex >= 0 && nMeshIndex < MPART_MAX )
{
if( m_pDecoMeshPart[nMeshIndex] )
return m_pDecoMeshPart[nMeshIndex]->Perform( id, msg );
}
return NULL;
}
void *KSeqAvatar::Perform( KID id, KArg& msg )
{
_CID( SETBONEBLEND );
_CID( ITEM_RENDER );
_CID( SET_MTETEX );
if( id == id_SETBONEBLEND )
{
KMsgGET_SETBONEBLEND *useBlend = static_cast<KMsgGET_SETBONEBLEND*>(&msg);
m_bUseBlend = useBlend->bUseBlend;
return NULL;
}
//MTE
if( id == id_SET_MTETEX )
{
for( int i(0); MPART_MAX>i; i++ )
{
if( m_pMeshPart[i] )
m_pMeshPart[i]->Perform( id, msg );
}
return NULL;
}
if( id == id_ITEM_RENDER )
m_bItemCheck = !m_bItemCheck;
if( m_bMeshCheck )
{
//살~ Mesh 한테두~
for( int i(0); MPART_MAX>i; i++ )
{
if( m_bMeshRender[i] && m_pMeshPart[i] )
m_pMeshPart[i]->Perform( id, msg );
}
}
if( m_bDecoMeshCheck )
{
for( int i(0); MDECOPART_MAX>i ; ++i )
{
if( m_bDecoMeshRender[i] && m_pDecoMeshPart[i] )
m_pDecoMeshPart[i]->Perform( id, msg );
}
}
if( m_bItemCheck )
{
//Item
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_bItemRender[i] && m_pItemPart[i] )
m_pItemPart[i]->Perform( id, msg );
}
}
//Effect Pos 얻기 위함~
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
if( m_bEffectPos[i] && m_pEffectPos[i] )
m_pEffectPos[i]->Perform( id, msg );
}
//Bone
if ( m_pCurSeq )
{
return m_pCurSeq->Perform( id, msg );
}
return NULL;
}
//
void *KSeqAvatar::PerformWithIgnoreMesh( KID id, KArg& msg, std::set<int>* ignoreMeshList )
{
_CID( SETBONEBLEND );
_CID( ITEM_RENDER );
// 2010.06.24 - prodongi
_CID( SET_COLORIZE );
if( id == id_SETBONEBLEND )
{
KMsgGET_SETBONEBLEND *useBlend = static_cast<KMsgGET_SETBONEBLEND*>(&msg);
m_bUseBlend = useBlend->bUseBlend;
return NULL;
}
if( id == id_ITEM_RENDER )
m_bItemCheck = !m_bItemCheck;
if( m_bMeshCheck )
{
// 2010.06.24 - prodongi
int oldMode;
KMsgSET_COLORIZE* colorize;
if (id == id_SET_COLORIZE)
{
colorize = static_cast<KMsgSET_COLORIZE*>(&msg);
oldMode = colorize->nMode;
}
//살~ Mesh 한테두~
for( int i(0); MPART_MAX>i; i++ )
{
if( m_bMeshRender[i] && m_pMeshPart[i] )
{
if (ignoreMeshList)
{
std::set<int>::iterator it = ignoreMeshList->find(i);
if (it != ignoreMeshList->end())
continue;
}
// 2010.06.24 살이 없는 part는 알파값을 유지하도록 수정- prodongi
if (id == id_SET_COLORIZE)
{
if (i >= MPART_L_SKIRT && i <= MPART_HELM)
colorize->nMode = K3DTexture::COLORIZED_KEEP_ALPHA;
else
colorize->nMode = oldMode;
}
m_pMeshPart[i]->Perform( id, msg );
}
}
// 2010.07.09 복구 - prodongi
if (id == id_SET_COLORIZE)
{
colorize->nMode = oldMode;
}
}
if( m_bDecoMeshCheck )
{
for( int i(0); MDECOPART_MAX>i ; ++i )
{
if( m_bDecoMeshRender[i] && m_pDecoMeshPart[i] )
m_pDecoMeshPart[i]->Perform( id, msg );
}
}
if( m_bItemCheck )
{
//Item
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_bItemRender[i] && m_pItemPart[i] )
m_pItemPart[i]->Perform( id, msg );
}
}
//Effect Pos 얻기 위함~
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
if( m_bEffectPos[i] && m_pEffectPos[i] )
m_pEffectPos[i]->Perform( id, msg );
}
//Bone
if ( m_pCurSeq )
{
return m_pCurSeq->Perform( id, msg );
}
return NULL;
}
void KSeqAvatar::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat )
{
if ( m_pCurSeq )
{
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;
m_pCurSeq->SetVisibility( m_fMasterVisibility );
m_pCurSeq->SetSkinDiffuse( m_SkinDiffuse );
m_pCurSeq->SetParentTransform( &m_matResult );
m_pCurSeq->Render( viewport );
//Mesh 그리기
if( m_sMeshRenderFlag && m_bMeshCheck )
{
for( int i(0); MPART_MAX>i; i++ )
{
if( m_bMeshRender[i] && m_pMeshPart[i] )
{
m_pMeshPart[i]->SetVisibility( m_fMasterVisibility );
m_pMeshPart[i]->SetSkinDiffuse( m_SkinDiffuse );
m_pMeshPart[i]->Render(viewport, flag, m_pMatAttach);
}
}
}
//DecoMesh 그리기
if( m_bDecoMeshCheck )
{
for( int i(0); MDECOPART_MAX > i; ++i )
{
if( m_bDecoMeshRender[i] && m_pDecoMeshPart[i] )
{
m_pDecoMeshPart[i]->SetVisibility( m_fMasterVisibility );
m_pDecoMeshPart[i]->SetSkinDiffuse( m_SkinDiffuse );
m_pDecoMeshPart[i]->Render(viewport, flag, m_pMatAttach);
}
}
}
//Item
if( m_bItemCheck )
{
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_bItemRender[i] && m_pItemPart[i] )
{
m_pItemPart[i]->SetVisibility( m_fMasterVisibility );
m_pItemPart[i]->Render(viewport, flag);
}
}
}
if( viewport->GetAttributes() & KViewportObject::VIEWPORT_GAME )
{
//Effect Pos
if( m_bEffectPosRenderFlag && m_bEffectPosCheck )
{ //Le rendu doit être effectué en raison de l'emplacement du SeqPoint. Pour vérifier l'emplacement, désactivez l'indicateur de rendu.
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
if( m_bEffectPos[i] && m_pEffectPos[i] )
{
//TODO : 임시 사각 박스 끄기, 추후에 제대로 되게 수정 요.
//m_pEffectPos[i]->Perform( id_SETFORCERENDER_FLAG, NULL );
m_pEffectPos[i]->Render(viewport, flag);
}
}
}
//Bone Effect
if( m_bBoneEffectCheck )
{
for( int i(0); BONE_EFFECT_MAX>i; i++ )
{
if( m_bBoneEffect[i] && m_pBoneEffect[i] )
{
m_pBoneEffect[i]->SetVisibility( m_fMasterVisibility );
m_pBoneEffect[i]->Render(viewport, flag);
}
}
}
if( m_bRenderRotCube )
GetBoundCube()->Render( viewport );
}
}
}
//void KSeqAvatar::SetAttachBone( const K3DMatrix *pMatParent, const K3DMatrix *pMatAttach )
//{
// _oprint( "KSeqAvatar::SetAttachBone\n" );
//
// if( m_pCurSeq )
// m_pCurSeq->SetAttachBone( pMatParent, pMatAttach );
//}
//현재 Animation에 Attach
void KSeqAvatar::SetAttach()
{
if( m_pCurSeq )
{
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_bItemRender[i] && m_pItemPart[i] )
{
m_pCurSeq->SetAttach( i, m_pItemPart[i] );
}
}
}
}
void KSeqAvatar::SetAttachEffectPos()
{
if( m_pCurSeq )
{
for( int i(0); EFFECT_POS_MAX>i; i++ )
{
if( m_bEffectPos[i] && m_pEffectPos[i] )
{
//Top, Middle 일때만, 뼈에 Link
if( i == EFFECT_POS_TOP || i == EFFECT_POS_MIDDLE || i == EFFECT_POS_SADDLE ||
i == EFFECT_POS_W_LEFT || i == EFFECT_POS_W_RIGHT || i == EFFECT_POS_W_TWOHAND )
m_pCurSeq->SetAttachEffectPos( i, m_pEffectPos[i] );
}
}
}
}
void KSeqAvatar::SetAttachEffectBone()
{
if( m_pCurSeq )
{
_CID( GETBONEMATRIX3 );
for( int i(0); BONE_EFFECT_MAX>i; i++ )
{
if( m_bBoneEffect[i] && m_pBoneEffect[i] && m_nBoneEffectIndex[i] != -1 )
{
KMsgGET_BONEMATRIX3 msg;
msg.nBoneIndex = m_nBoneEffectIndex[i];
Perform( id_GETBONEMATRIX3, msg );
m_pBoneEffect[i]->SetParentTransform( m_pMatParent, msg.pBoneMat );
// m_pCurSeq->SetAttachEffectBone( m_nBoneEffectIndex[i], m_pBoneEffect[i] );
}
}
}
}
void KSeqAvatar::SetParentTransform( const K3DMatrix *pMatParent, const K3DMatrix *pMatAttach, BOOL bRotationLock )
{
m_pMatParent = pMatParent;
m_pMatAttach = pMatAttach;
//뭔가 이상함...
for( int i(0); MPART_MAX>i; i++ )
{
if( m_bMeshRender[i] && m_pMeshPart[i] )
{
m_pMeshPart[i]->SetParentTransform(pMatParent, pMatAttach, bRotationLock);
}
}
if( m_bDecoMeshCheck )
{
for( int i(0); MDECOPART_MAX > i; ++i )
{
if( m_bDecoMeshRender[i] && m_pDecoMeshPart[i] )
{
if (i == MDECOPART_SHOULDER || i == MDECOPART_SHOULDER2 )
{
if (m_pDecoMeshPart[i]->GetAttachTransform() == NULL)
m_pDecoMeshPart[i]->SetParentTransform( pMatParent, pMatAttach, bRotationLock );
else
m_pDecoMeshPart[i]->SetParentTransform( pMatParent, m_pDecoMeshPart[i]->GetAttachTransform(), bRotationLock );
}
else
m_pDecoMeshPart[i]->SetParentTransform( pMatParent, pMatAttach, bRotationLock );
}
}
}
#ifndef _RAC //뭐하는 코드 였지?? - -;;
if( m_pCurSeq )
{
m_pCurSeq->SetParentTransform( pMatParent, pMatAttach, bRotationLock );
}
#endif
}
//현재 채널과 Deform
void KSeqAvatar::SetDeform()
{
//뼈를 Mesh들에게 Deform
if( m_pCurSeq )
{
//모든 Mesh에게 뼈 설정.
for( int i(0); MPART_MAX>i; i++ )
{
if( m_pMeshPart[i] )
m_pCurSeq->SetDeform( m_pMeshPart[i] );
}
if( m_bDecoMeshCheck )
{
for( int i(0); MDECOPART_MAX > i; ++i )
{
if( m_pDecoMeshPart[i] )
m_pCurSeq->SetDeform( m_pDecoMeshPart[i] );
}
}
}
}
void KSeqAvatar::SetMeshRenderFlag( int nIndex, BOOL bRenderFlag )
{
if( nIndex < MPART_MAX )
m_bMeshRender[nIndex] = bRenderFlag;
}
void KSeqAvatar::SetDecoMeshRenderFlag( int nIndex, BOOL bRenderFlag )
{
if( nIndex < MDECOPART_MAX )
m_bDecoMeshRender[nIndex] = bRenderFlag;
}
//교차 부위 없애기~
void KSeqAvatar::SetRenderFlag( const char * pStr, BOOL bRenderFlag )
{
_CID( SETRENDER_FLAG );
KMsgSET_RENDERFLAG rendermsg;
rendermsg.pName = pStr;
rendermsg.bRenderFlag = bRenderFlag;
if( m_pMeshPart[MPART_BODY] && m_bMeshRender[MPART_BODY] )
m_pMeshPart[MPART_BODY]->Perform( id_SETRENDER_FLAG, rendermsg);
}
//몬스터 같은 경우는 없다.
void KSeqAvatar::Weld(int nIndex)
{
}
void KSeqAvatar::GetFrameInfo( const char * strKey, int &nBoneCount, DWORD &dwMinTime, DWORD &dwMaxTime )
{
KSeqObject *obj = GetAnimation( strKey );
_CID( GETBONEINFO );
KMsgGET_BONEINFO msg;
if( obj && obj->Perform( id_GETBONEINFO, msg ) )
{
nBoneCount = msg.nBoneCount;
dwMinTime = msg.dwMinTime ;
dwMaxTime = msg.dwMaxTime ;
}
}
bool KSeqAvatar::CheckPendingSeq()
{
return KSeqForm::CheckPendingSeq();
}
// sfreer 임시코드임. 인벤토리 창에 나오는 아바타에서 방패 장착시 표시 안되0 버그을 위해 추가한 함수. 2009.03.09
bool KSeqAvatar::PlayAnimation_temp( DWORD dwCurTime, const char *name, int nAniType, float fPlayRate )
{
KSeqForm::PlayAnimation( dwCurTime, name, nAniType, fPlayRate );
if( m_bItemCheck )
{
for( int i(0); ATTACH_MAX>i; i++ )
{
if( m_bItemRender[i] && m_pItemPart[i] )
{
//if( m_pItemPart[i]->GetAnimation("default") != NULL)
{
//_oprint("KSeqAvatar::PlayAnimation_temp - default 애니메이션이 없음으로 아이템(방패등) 출력이 안되니 주의바람." );
m_pItemPart[i]->PlayAnimation(dwCurTime, "default"/*GetCurrentAnimationName()*/, nAniType, fPlayRate);
}
}
}
}
SetDeform(); //현재 애니메이션과 메쉬 스키닝
SetAttach(); //아이템 붙이기
SetAttachEffectPos(); //이펙트 위치 붙이기
SetAttachEffectBone();
return true;
}