#include "StdAfx.h"
#include "nifanimationinfo.h"


cNifAnimationInfo::cNifAnimationInfo()
{
	mStartTime = FLT_MAX;
	mMinTime = FLT_MAX;
	mMaxTime = 0.0f;
	mKeyframeCount = 0;
	mControllerCount = 0;

	mLooping = false;
	mEnable = false;
}

cNifAnimationInfo::~cNifAnimationInfo()
{
	mControllerList.RemoveAll();
}

/// 주의사항 : 
void cNifAnimationInfo::CollectData( NiNode* pRoot )
{
	mMinTime = FLT_MAX;
	mMaxTime = 0.0f;
	mKeyframeCount = 0;

	FindAndAdd( pRoot );

	float fStartTime = NiParticleSystem::GetMinBeginKeyTime( pRoot );

	if( fStartTime < mMinTime )
		mMinTime = fStartTime;
}

/// 주의사항 : 
void cNifAnimationInfo::Add(NiTimeController* pController)
{
	if(pController == 0)
	{
		return;
	}

	AddInfo(pController);

	if( pController->GetBeginKeyTime() < mMinTime )
		mMinTime = pController->GetBeginKeyTime();
	if(pController->GetEndKeyTime() > mMaxTime)
		mMaxTime = pController->GetEndKeyTime();

	mControllerCount++;

	if(NiIsKindOf(NiInterpController, pController))
		AddInterpInfo((NiInterpController*) pController);
	else if(NiIsKindOf(NiUVController, pController))
		AddUVInfo((NiUVController*) pController);
}

/// 주의사항 : 
void cNifAnimationInfo::FindAndAdd(NiObjectNET* pRoot)
{
	if(pRoot == 0)
		return;

	NiTimeController* pController = pRoot->GetControllers();

	// Gather all time controllers from this object
	while(pController != 0)
	{
		Add(pController);
		pController = pController->GetNext();
	}

	if(NiIsKindOf(NiAVObject, pRoot))
	{
		// NiProperties can have time controllers, so search them too
		NiAVObject* pObj = (NiAVObject*) pRoot;
		NiPropertyList* pPropList = &(pObj->GetPropertyList());
		NiTListIterator iter = pPropList->GetHeadPos();
		while(pPropList != 0 && !pPropList->IsEmpty()&& iter)
		{
			NiProperty* pProperty = pPropList->GetNext(iter);
			if(pProperty)
				FindAndAdd(pProperty);
		}
	}
	if(NiIsKindOf(NiNode, pRoot))
	{
		NiNode* pNode = (NiNode*) pRoot;
		// Search all of the children
		for(unsigned int ui = 0; ui < pNode->GetArrayCount(); ui++)
		{
			NiAVObject* pObj = pNode->GetAt(ui);
			FindAndAdd(pObj);
		}
		// NiDynamicEffects can have time controllers, so search them too
		const NiDynamicEffectList* pEffectList= &(pNode->GetEffectList());

		NiTListIterator iter = pEffectList->GetHeadPos();
		while(pEffectList != 0 && !pEffectList->IsEmpty() && iter)
		{
			NiDynamicEffect* pEffect = pEffectList->GetNext(iter);
			if( pEffect )
				FindAndAdd( pEffect );
		}
	}
}

/// 주의사항 : 
void cNifAnimationInfo::AddInfo( NiTimeController* pController )
{
	/// 만약 컨트롤러들에 대한 참조를 갖으려면 이곳에..
	mControllerList.AddTail( pController );

	if( pController->GetCycleType() == NiTimeController::LOOP )
		mLooping = true;
}

/// 주의사항 : 
void cNifAnimationInfo::AddInterpInfo( NiInterpController* pController )
{
	for( unsigned short us = 0; us <  pController->GetInterpolatorCount(); us++ )
	{
		NiInterpolator* pInterp = pController->GetInterpolator( us );
		if( NiIsKindOf(NiKeyBasedInterpolator, pInterp) )
		{
			NiKeyBasedInterpolator* pKeyInterp = (NiKeyBasedInterpolator*)pInterp;
			for( unsigned short usc = 0; usc < pKeyInterp->GetKeyChannelCount(); usc++ )
			{
				mKeyframeCount += pKeyInterp->GetKeyCount( usc );
			}
		}
	}
}

/// 주의사항 : 
void cNifAnimationInfo::AddUVInfo( NiUVController* pController )
{
	mKeyframeCount += pController->GetNumUOffsetKeys () +
		pController->GetNumVOffsetKeys () + 
		pController->GetNumUTilingKeys () +
		pController->GetNumVTilingKeys ();
}

/// 주의사항 : 
void cNifAnimationInfo::SetAnimType( NiTimeController::AnimType type)
{
	NiTListIterator pos = mControllerList.GetHeadPos();
	while( pos )
	{
		NiTimeController* pcon = mControllerList.GetNext(pos);
		if( pcon )
			pcon->SetAnimType( type );
	}
}

/// 주의사항 : 
unsigned char cNifAnimationInfo::Update( float time )
{
	unsigned char ev = eEvent_None;

	/// 
	if( mStartTime == FLT_MAX )
		Start( time );


	if( mEnable == false ) 
		return ev;

	/// 전체 종료 여부 확인..
	if( mMaxTime <= time - mStartTime )
	{
		if( mLooping )
			return eEvent_Ing;

		mEnable = false;
		ev = eEvent_End;
	}

	return ev;
}

/// 주의사항 : 
void cNifAnimationInfo::Start( float time )
{
	mStartTime = time;

	NiTListIterator pos = mControllerList.GetHeadPos();
	while( pos )
	{
		NiTimeController* pcon = mControllerList.GetNext(pos);
		if( pcon )
		{
			pcon->Start( mMinTime );

			if( NiIsKindOf(NiGeomMorpherController, pcon) )
				((NiGeomMorpherController*)pcon)->SetManagerControlled( false );
		}
	}

	mEnable = true;
}

/// 주의사항 : 
void cNifAnimationInfo::Stop()
{
	NiTListIterator pos = mControllerList.GetHeadPos();
	while( pos )
	{
		NiTimeController* pcon = mControllerList.GetNext(pos);
		if( pcon )
		{
			pcon->Stop();

			if( NiIsKindOf(NiGeomMorpherController, pcon) )
				((NiGeomMorpherController*)pcon)->SetManagerControlled( true );
		}
	}

	mEnable = false;
}
