#include "StdAfx.h"
#include "PlayerSceneNode.h"

#include "ResourceManager.h"

#include "SceneManager.h"
#include "CameraManager.h"
#include "RenderSystem.h"

cPlayerSceneNode::cPlayerSceneNode( eType type )
: cDynamicSceneNode( type )
{
}

cPlayerSceneNode::~cPlayerSceneNode()
{
}

bool cPlayerSceneNode::Init( const cPlayerSceneNodeParam& param )
{
	if( cDynamicSceneNode::Init( param ) == false )
	{
		return false;
	}

	mHead = GetPartObject( eLINK_HEAD );
	if( !mHead )
		assert(0);

	return true;
}

bool cPlayerSceneNode::InitLinkInfo()
{
	// 이부분은 적당한 메모리 할당을 한다. (나중에 좀더 정확하게 계산하여 추가하거나 줄일것..)
	// 대략 계산 : 양손 무기 2개 + 방패 1개
	mLinkInfo = NiNew NiTPrimitiveArray<sLinkInfo*>(15, 5);
	assert(mLinkInfo);
	if( mLinkInfo == 0 ) 
	{
		return false;
	}

	for( unsigned int i=0; i<mLinkInfo->GetAllocatedSize(); ++i )
	{
		mLinkInfo->SetAt( i,0 );
	}

	return true;
}

/* ------------------------------------------------------------------
* 함수이름 :	InitPartsName()
* 목    적 :	그래픽팀과 맞춘 객체의 이름을 셋팅한다.
* 주의사항 :	추후에 파일로 빼는것도 고려한다.
* ------------------------------------------------------------------ */
bool cPlayerSceneNode::InitPartsName()
{
	mPartsNameMap.SetAt( ePART_HAIR,	"hair" );
	mPartsNameMap.SetAt( ePART_FACE,	"face" );
	mPartsNameMap.SetAt( ePART_BODY1,	"body1" );
	mPartsNameMap.SetAt( ePART_BODY2,	"body2" );
	mPartsNameMap.SetAt( ePART_HAND,	"hand" );
	mPartsNameMap.SetAt( ePART_FOOT,	"foot" );

	mPartsNameMap.SetAt( eLINK_HEAD,	"head_dummy" );
	mPartsNameMap.SetAt( eLINK_BODY,	"body_dummy" );
	mPartsNameMap.SetAt( eLINK_RHAND,	"Rhand_dummy" );
	mPartsNameMap.SetAt( eLINK_LHAND,	"Lhand_dummy" );
	mPartsNameMap.SetAt( eLINK_FOOT,	"foot_dummy" );
	mPartsNameMap.SetAt( eLINK_LARM,	"Larm_dummy" );

	mPartsNameMap.SetAt( eLINK_RWEAPON,	"weapon_dummy" );
	mPartsNameMap.SetAt( eLINK_LWEAPON,	"weaponL_dummy" );

	return true;
}

/* ------------------------------------------------------------------
* 함수이름 :	InitializeRandomIdle()
* 목    적 :	동작의 다양성을 제공하기 위해서
* 주의사항 :	
* ------------------------------------------------------------------ */
void cPlayerSceneNode::InitializeRandomIdle()
{
	mRandomIdle = NiNew NiTPrimitiveArray<cActorManagerForPartition::EventCode>(1);

	mRandomIdle->SetAt( 0, 0 );
	//	m_pkRandomIdle->SetAt(1, 2);
	//	m_pkRandomIdle->SetAt(1, 3);
}


NiPoint3 cPlayerSceneNode::GetObjectCenter()
{
	NiAVObject* spine = GetPartObject( eLINK_BODY );

	NiPoint3 cen = GetCenter();
	NiPoint3 pos;
	if( spine )	
	{
		pos = spine->GetWorldTranslate();
		pos = NiPoint3( pos.x, pos.y, cen.z );
		return pos;
	}
	else
	{
		return NiPoint3::ZERO;
	}
}

/* ------------------------------------------------------------------
* 함수이름 :	ChangeParts( unsigned int index, const cString& pathName )
* 목    적 :	파트 교체용 인터페이스 제공
* 주의사항 :	
* ------------------------------------------------------------------ */
bool cPlayerSceneNode::ChangeParts( unsigned int partIdx, const char* fileName )
{
	if( fileName == 0 )
		return false;

	///
	cString pathName;
	pathName.Format( "Data/Character/%s", fileName );
	RESOURCEMAN->LoadNIF( pathName );

	///
	NiNode* pNode = RESOURCEMAN->CloneObjectByName( fileName );
	if( !pNode ) 
	{
		return false;
	}

	return cDynamicSceneNode::ChangeParts( partIdx, pNode );
}

bool cPlayerSceneNode::ChangePartsTexture( unsigned int partsIdx, const char* fileName )
{
	cString pathName;
	pathName.Format( "Data/Character/%s", fileName );
	NiTexture* pTexture = RESOURCEMAN->LoadTexture( pathName );
	if( pTexture == 0 )
	{
		return false;
	}

	return cDynamicSceneNode::ChangePartsTexture( partsIdx, pTexture );
}


/* ------------------------------------------------------------------
* 함수이름 :	LinkToDummy( unsigned int index, const cString& pathName )
* 목    적 :	객체 링크용 인터페이스
* 주의사항 :	
* ------------------------------------------------------------------ */
unsigned int cPlayerSceneNode::LinkObject( unsigned int dummyIdx, const char* fileName )
{
	if( fileName == 0 )
		return UINT_MAX;


	cString pathName;
	pathName.Format( "Data/Character/%s", fileName );
	if( RESOURCEMAN->LoadNIF( pathName ) == false )
		return UINT_MAX;

	///
	NiNode* pNode = RESOURCEMAN->GetObjectByName( fileName );
	if( !pNode ) 
	{
		assert(0);
		return UINT_MAX;
	}

	return cDynamicSceneNode::LinkObject( dummyIdx, pNode );
}

NiAVObject*	 cPlayerSceneNode::GetPartWeapon( unsigned int objectIdx, bool left )
{
	NiAVObject* pObj = GetLinkObject( objectIdx );
	if( pObj == 0 )
		return 0;

	unsigned int partIdx = (left == true)? eLINK_LWEAPON:eLINK_RWEAPON;
	const char* partsName = NULL;
	if( mPartsNameMap.GetAt( partIdx, partsName ) == false )
	{
		return NULL;
	}
	return pObj->GetObjectByName( partsName );
}

bool cPlayerSceneNode::UpdateTargetAnimation( unsigned int code )
{
	return cDynamicSceneNode::UpdateTargetAnimation( code );
}

void cPlayerSceneNode::ProcessTrail( float delta )
{
//	unsigned long scaleDelta = (unsigned long)(delta * mScaleFactor);

	///
	NiTListIterator pos = mRibbonList.GetHeadPos();
	while( pos )
	{
		sTrailInfo* p = mRibbonList.GetNext(pos);
		cRibbonGeometry* geom = p->mRibbonGeom;
		if( p->mLoop == false )
		{
			if( p->mLifeTime <= delta )
			{
				p->mLifeTime = 0;
				geom->SetPushEnabled( false );

				if( geom->GetNumVerts() == 0 )
				{
					/// delete
					mDeleteRibbonList.AddTail(p);
					continue;
				}
			}
			else
				p->mLifeTime -= delta;
		}

		if( geom )
		{
			/// push point
			NiAVObject* obj1 = GetPartObject( ePART_MAX + p->mStartLink );
			NiAVObject* obj2 = GetPartObject( ePART_MAX + p->mEndLink );

			if( obj1 && obj2 )
			{
				const NiPoint3& pos1 = obj1->GetWorldTranslate();
				const NiPoint3& pos2 = obj2->GetWorldTranslate();

				geom->SetPushPoint( pos1, pos2 );
			}

			geom->Process( delta );
		}
	}
}
