#include "StdAfx.h"
#include "effectscenenode.h"
#include "NifAnimationInfo.h"

#include "ResourceManager.h"
#include "DynamicSceneNode.h"
#include "SceneManager.h"

cEffectSceneNode::cEffectSceneNode( eType type )
: cSceneNode( type )
, mpFollowSceneNode(0)
, mpDummy(0)
, mFadeOut(false)
, mRemoved(false)
{
	mNifAniInfo = new cNifAnimationInfo;
}

cEffectSceneNode::~cEffectSceneNode()
{
	if( mpDummy )
		mpDummy->DetachChild( mNiObject );

	SAFE_DELETE(mNifAniInfo);
}

bool cEffectSceneNode::InitSelfNode( cString pathName, NiTransform& trans, bool bLoop )
{
	if( RESOURCEMAN->LoadMapNIF( pathName.Cstr() ) == false )
	{
//		assert( 0 && "failed to load nif file" );
		return false;
	}
	NiNode* n = RESOURCEMAN->CloneObjectByName( pathName.Cstr() );
	if( n == 0 )
	{
		assert( 0 && "failed to clone node from resource manager" );
		return false;
	}

	mpFollowSceneNode = 0;
	mpDummy = 0;

	NiTransform kWorld = trans * n->GetLocalTransform();
	n->SetTranslate( kWorld.m_Translate );
	n->SetRotate( kWorld.m_Rotate );
	n->SetScale( kWorld.m_fScale );

	n->SetName( "EffectSceneNode" );

	/// 애니메이션 컨트롤러 정보 수집
	mNifAniInfo->CollectData( n );
	if( mNifAniInfo->GetNumberOfControllers() )
	{
		mNifAniInfo->SetAnimType( NiTimeController::APP_INIT );
		mNifAniInfo->SetLooping( bLoop );
	}
	else
	{
		/// 애니 정보가 없다면 메모리 해제
		SAFE_DELETE(mNifAniInfo);
//		assert(0 && "wrong effect animInfo");
//		return false;
	}

	NiFogProperty* pFog = NiNew NiFogProperty;
	pFog->SetFog( false );
	n->AttachProperty( pFog );

	/// 엔진 노드를 설정
	n->SetSelectiveUpdate( true );
	n->SetSelectiveUpdateTransforms( true );
	n->SetSelectiveUpdatePropertyControllers( true );
	n->SetSelectiveUpdateRigid( false );

	/// 엔진 노드를 처리
	n->UpdateProperties();
	n->UpdateEffects();
	n->Update( 0.0f );
	n->UpdateNodeBound();

	mNiObject = n;

	return true;

}

/// param을 생성하는 경우 dummy를 포함해야 한다.
bool cEffectSceneNode::Init( const cEffectSceneNodeParam& param )
{
	/// 파일을 로딩
	if( RESOURCEMAN->LoadMapNIF( param.mPathName.Cstr() ) == false )
	{
//		assert( 0 && "failed to load nif file" );
		return false;
	}
	if( param.mpDummy == 0 )
	{
		assert(0);
		return false;
	}

	/// 리소스 관리자로부터 엔진 노드를 복제
	NiNode*	n = RESOURCEMAN->CloneObjectByName( param.mPathName.Cstr() );
	if( n == 0 )
	{
		assert( 0 && "failed to clone node from resource manager" );
		return false;
	}

	n->SetTranslate( param.mTranslate );
	n->SetRotate( param.mRotate );
	n->SetScale( param.mScale );
/*
	NiMaterialProperty* mp = 0;
	NiAVObject* o = n->GetObjectByName("emiter");
	if( o )
	{
		NiAVObject* geom = GetGeom( o );
		NiVertexColorProperty* vp = (NiVertexColorProperty*)geom->GetProperty( NiProperty::VERTEX_COLOR );
		if( vp )
			vp->SetLightingMode( NiVertexColorProperty::LIGHTING_E );

		mp = (NiMaterialProperty*)geom->GetProperty( NiProperty::MATERIAL );
		if( mp )
		{
			int a = 0;
			a = 1;
		}
	}
*/

	mpFollowSceneNode = param.mpFollowSceneNode;
	if( param.mFollowing == false )
	{
		NiTransform kWorld =  param.mpDummy->GetWorldTransform() * n->GetLocalTransform();
		n->SetWorldScale( kWorld.m_fScale );

		NiPoint3 trans = param.mpDummy->GetWorldTranslate();
		n->SetTranslate( n->GetTranslate() + trans );
	}
	else
	{
		mpDummy = param.mpDummy;
	}
/*

	mpFollowSceneNode = param.mpFollowSceneNode;
	if( param.mFollowing == false )
	{
		NiTransform kWorld =  param.mpDummy->GetWorldTransform() * n->GetLocalTransform();
		n->SetScale( kWorld.m_fScale );

		NiPoint3 trans = param.mpDummy->GetWorldTranslate();
		n->SetTranslate( trans + n->GetTranslate()  );
	}
	else
	{
		mpDummy = param.mpDummy;
	}
*/
	n->SetName("EffectSceneNode");

	Test( n );

	/// 애니메이션 컨트롤러 정보 수집
	mNifAniInfo->CollectData( n );
	if( mNifAniInfo->GetNumberOfControllers() )
	{
		mNifAniInfo->SetAnimType( NiTimeController::APP_INIT );
		mNifAniInfo->SetLooping( param.mLooping );
	}
	else
	{
		/// 애니 정보가 없다면 메모리 해제
		SAFE_DELETE(mNifAniInfo);
		assert(0 && "wrong effect animInfo");
		return false;
	}

	NiFogProperty* pFog = NiNew NiFogProperty;
	pFog->SetFog( false );
	n->AttachProperty( pFog );

	if( param.mFollowing == true )
	{
		mpDummy->AttachChild( n );
	}

	/// 엔진 노드를 설정
	n->SetSelectiveUpdate( true );
	n->SetSelectiveUpdateTransforms( false );
	n->SetSelectiveUpdatePropertyControllers( true );
	n->SetSelectiveUpdateRigid( true );

	/// 엔진 노드를 처리
	n->Update( 0.0f );
	n->UpdateProperties();
	n->UpdateEffects();
	n->UpdateNodeBound();

	mNiObject = n;

	return true;
}

bool cEffectSceneNode::InitDamageEffect( const cEffectSceneNodeParam& param )
{
	/// 파일을 로딩
	if( RESOURCEMAN->LoadMapNIF( param.mPathName.Cstr() ) == false )
	{
		//		assert( 0 && "failed to load nif file" );
		return false;
	}
	if( param.mpDummy == 0 )
	{
		assert(0);
		return false;
	}

	//////////////////////////////////////////////////////////////////////////
	// 공유 GeomData를 버리고 새로 갱신한다.
	NiNode* src = RESOURCEMAN->GetObjectByName( param.mPathName.Cstr() );
	NiNode* des = RESOURCEMAN->CloneObjectByName( param.mPathName.Cstr() );
	if( src == 0 || des == 0 )
		return false ;

	NiGeometry* sGeom[4] = {0,};
	if( FindDamageGeom( src, sGeom ) == false )
		return false;
	NiGeometry* dGeom[4] = {0,};
	if( FindDamageGeom( des, dGeom ) == false )
		return false;

	for( unsigned int i=0; i<4; i++ )
	{
		NiGeometryDataPtr g = NiSmartPointerCast( NiGeometryData, sGeom[i]->GetModelData()->CreateDeepCopy() );
		g->SetConsistency( NiGeometryData::VOLATILE );

		dGeom[i]->SetModelData( g );
	}
	//////////////////////////////////////////////////////////////////////////

	des->SetTranslate( param.mTranslate );
	des->SetRotate( param.mRotate );
	des->SetScale( param.mScale );

	mpFollowSceneNode = param.mpFollowSceneNode;
	if( param.mFollowing == false )
	{
		NiPoint3 trans = param.mpDummy->GetWorldTranslate();
		des->SetTranslate( des->GetTranslate() + trans );

//		NiTransform kWorld =  param.mpDummy->GetWorldTransform() * des->GetLocalTransform();
//		des->SetTranslate( kWorld.m_Translate );
//		des->SetRotate( kWorld.m_Rotate );
//		des->SetScale( kWorld.m_fScale );
	}
	else
	{
		mpDummy = param.mpDummy;
	}

	des->SetName("EffectSceneNode");

	/// 애니메이션 컨트롤러 정보 수집
	mNifAniInfo->CollectData( des );
	if( mNifAniInfo->GetNumberOfControllers() )
	{
		mNifAniInfo->SetAnimType( NiTimeController::APP_INIT );
		mNifAniInfo->SetLooping( param.mLooping );
	}
	else
	{
		/// 애니 정보가 없다면 메모리 해제
		SAFE_DELETE(mNifAniInfo);
		assert(0 && "wrong effect animInfo");
		return false;
	}

	NiFogProperty* pFog = NiNew NiFogProperty;
	pFog->SetFog( false );
	des->AttachProperty( pFog );

	if( param.mFollowing == true )
		mpDummy->AttachChild( des );

	/// 엔진 노드를 설정
	des->SetSelectiveUpdate( true );
	des->SetSelectiveUpdateTransforms( false );
	des->SetSelectiveUpdatePropertyControllers( true );
	des->SetSelectiveUpdateRigid( true );

	/// 엔진 노드를 처리
	des->Update( 0.0f );
	des->UpdateProperties();
	des->UpdateEffects();
	des->UpdateNodeBound();

	mNiObject = des;

	return true;
}

void cEffectSceneNode::Remove()
{
	if( mRemoved == false )
	{
		if( mpFollowSceneNode )
		{
			mpFollowSceneNode->UnLinkEffect( this );
			if( mpDummy )
			{
				mpDummy->DetachChild( mNiObject );
				mpDummy = 0;
			}
		}
		else
			SCENEMAN->AddDeleteEffectNode( this );

		mRemoved = true;
	}
}

void cEffectSceneNode::OnProcess( float deltaTime, float accumTime )
{
	if( mFadeOut )
	{
		Remove();
	}

	/// 반복 동작을 가진 경우 엔진 노드를 처리
	if( mNifAniInfo )
	{
		if( mpDummy == 0 )
			mNiObject->Update( accumTime );

		unsigned char state = mNifAniInfo->Update( deltaTime, accumTime );
		if( state == cNifAnimationInfo::eEvent_End )
		{
			Remove();
			return;
		}
	}
}

bool cEffectSceneNode::FindDamageGeom( NiNode* /*pNode*/, NiGeometry** /*pArray*/ )
{
/*
	if( pNode == 0 || pArray == 0 )
		return false;

	cString str;
	for( unsigned int i = 0; i<4; i++ )
	{
		str.Format("Dam%d", i+1);
		NiAVObject* pobj = pNode->GetObjectByName( str.Cstr() );
		if( pobj == 0 )
		{
			assert(0);
			return false;
		}

		NiGeometry* pgeom = (NiGeometry*)cSceneNode::GetGeom( pobj );
		if( pgeom == 0 )
		{
			assert(0);
			return false;
		}

		if( pgeom->GetVertexCount() != 4 )
			return false;
		if( pgeom->GetTextureSets() != 1 )
			return false;

		pArray[i] = pgeom;
	}
*/
	return true;
}

void cEffectSceneNode::Test( NiAVObject* obj )
{
	assert( obj );

	if( NiIsKindOf(NiTriBasedGeom, obj) || NiIsKindOf(NiParticleSystem, obj) )
	{
		NiGeometry* geom = (NiGeometry*)obj;

		if( geom->GetVertexCount() >= 3 )
		{


		}
	}
	else if( NiIsKindOf(NiNode, obj) )
	{
		NiNode* node = (NiNode*)obj;

		for( unsigned int i = 0, iend = node->GetArrayCount(); i < iend; ++i )
		{
			NiAVObject* child = node->GetAt(i);
			if( child )
				CollectGeoms( child );
		}
	}
}
