#include "Mix/Private/Scene/Common/MotionDeformer.h"

#include "Mix/Private/Scene/Common/ActorModel.h"
#include "Mix/Private/Scene/Common/Motion.h"
#include "Mix/Private/Scene/Common/MotionCurve.h"

namespace Mix{ namespace Scene{ namespace Common{

////////////////////////////////////////////////////////////////////////////////////////////////////
// MotionDeformer::CURVE
////////////////////////////////////////////////////////////////////////////////////////////////////

MotionDeformer::CURVE::CURVE( MotionCurve* _pInterface, UInt32 _nodeIndex )
{
	MIX_ADD_REF( _pInterface );
	pInterface = _pInterface;

	nodeIndex = _nodeIndex;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// MotionDeformer
////////////////////////////////////////////////////////////////////////////////////////////////////

MotionDeformer* MotionDeformer::CreateInstance(	Mix::Scene::Common::ActorModel* pModel,
												Mix::Scene::Common::Motion* pMotion )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_SCENE, MotionDeformer, pModel, pMotion );
}

MotionDeformer::MotionDeformer(	Mix::Scene::Common::ActorModel* pModel,
								Mix::Scene::Common::Motion* pMotion )
{
	MIX_ASSERT( pModel != NULL );
	MIX_ASSERT( pMotion != NULL );

	UInt32 count = pMotion->GetBodyCurveCount();

	m_CurveList.reserve( count );

	for( UInt32 i = 0; i < count; i++ )
	{
		MotionCurve* pInterface = pMotion->GetBodyCurvePtr( i );
		MIX_ASSERT( pInterface != NULL );

		UInt32 nodeIndex = pModel->GetNodeIndex( pInterface->GetLinkNodeName() );
		if( nodeIndex != 0xFFFFFFFF )
		{
			m_CurveList.push_back( MotionDeformer::CURVE( pInterface, nodeIndex ) );
		}
	}
}


MotionDeformer::~MotionDeformer( void )
{
	for( MotionDeformer::CurveList::iterator it = m_CurveList.begin(); it != m_CurveList.end(); ++it )
	{
		MIX_RELEASE( ( *it ).pInterface );
	}
}

void MotionDeformer::Execute( Float32 blendRatio, Float32 frame, Mix::ContainerT<Mix::Scene::Common::MOTION_BODY_BLEND, Mix::Memory::SECTION_SCENE>& container )
{
	size_t count = m_CurveList.size();
	if( count == 0 )
	{
		return;
	}

	MotionDeformer::CURVE* pCurve = &( m_CurveList[0] );
	MotionDeformer::CURVE* pCurveEnd = pCurve + count;

	while( pCurve != pCurveEnd )
	{
		MotionCurve* pInterface = pCurve->pInterface;
		MOTION_BODY_BLEND* pBlend = container.Add();

		pBlend->nodeIndex = pCurve->nodeIndex;
		pBlend->ratio = blendRatio;
		pBlend->scaling = pInterface->GetScaling( frame );
		pBlend->rotation = pInterface->GetRotation( frame );
		pBlend->translation = pInterface->GetTranslation( frame );

		pCurve++;
	}
}

}}}
