#include "stdafx.h"
#include "StaticSceneNode.h"

#include "ResourceManager.h"
#include "CameraManager.h"
#include "SceneManager.h"

#include "NifAnimationInfo.h"

cStaticSceneNode::cStaticSceneNode( eType type )
: cSceneNode( type )
, mVisibleLevel( 0 )
, mOccludeLevel( 1 )
, mPickedByCamera( false )
{
	mNifAniInfo = new cNifAnimationInfo;
}

cStaticSceneNode::~cStaticSceneNode()
{
	SAFE_DELETE( mNifAniInfo );
}

void cStaticSceneNode::OnProcess( float deltaTime, float accumTime )
{

	/// 알파를 처리
	if( mAlphaForced == false && mOccludeLevel == 1 )
		OnProcessAlpha( deltaTime );

	mTargetAlpha = 1.0f;

	/// 반복 동작을 가진 경우 엔진 노드를 처리
	if( mNifAniInfo )
	{
		mNeedUpdate	= true;
		mNifAniInfo->Update( deltaTime, accumTime );
	}

	mPickedByCamera = false;
	cSceneNode::OnProcess( deltaTime, accumTime );
}

bool cStaticSceneNode::OnVisible( cSceneCuller& culler )
{
	if( mViewNode == false )
		return false;

	/// 알파를 처리
	if( mOccludeLevel == 1 && mPickedByCamera )
		mTargetAlpha = 0.4f;

	return cSceneNode::OnVisible( culler );
}

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

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

	/// 상위 초기화
	mNiObject = n;
	if( cSceneNode::Init( param ) == false )
	{
		return false;
	}

	/// 가시 레벨을 설정
	mVisibleLevel = param.mVisibleLevel;

	/// 차폐 레벨을 설정
	mOccludeLevel = param.mOccludeLevel;

	/// 알파 속성을 설정
	NiAlphaProperty* alphaProp = (NiAlphaProperty*)n->GetProperty( NiProperty::ALPHA );
	mAlphaForced = (alphaProp != 0);

	if( mAlphaForced )
	{
		mAlphaBlended = true;
	}
	else
	{
		mAlphaBlended = false;

		if( mOccludeLevel == 1 )
		{
			/// 알파 속성이 없으면 생성
			alphaProp = NiNew NiAlphaProperty;
			alphaProp->SetAlphaBlending( false );
			alphaProp->SetAlphaTesting( false );
			n->AttachProperty( alphaProp );

			bool blendEnabled = alphaProp->GetAlphaBlending();
			bool testEnabled = alphaProp->GetAlphaTesting();
			NiAlphaProperty::TestFunction testFunc = alphaProp->GetTestMode();
			unsigned char testRef = alphaProp->GetTestRef();

			mAlphaDataList.PushBack( new cAlphaData( blendEnabled, testEnabled, testFunc, testRef, alphaProp ) );
		}
	}

	/// 속성들을 수집
	CollectProperties( n );

	/// 재질을 설정
	if( param.mMaterialApplied )
		SetMaterial( param.mMaterial );

	///// 안개 속성을 부착
	//if( param.mFogApplied )
	//	n->AttachProperty( FOGAGENT->GetFogProperty() );

	if( param.mNoAttachLight == false )
	{
		n->AttachEffect( SCENEMAN->GetAmbientLight() );
//		/// 조명을 부착
//		n->AttachEffect( LIGHTAGENT->GetSceneAmbientLight( 0 ) );
//		n->AttachEffect( LIGHTAGENT->GetSceneDirLight( 0 ) );
	}

	/// 애니메이션 컨트롤러 정보 수집
	mNifAniInfo->CollectData( n );

	if( mNifAniInfo->GetNumberOfControllers() )
	{
		mNifAniInfo->SetAnimType( NiTimeController::APP_INIT );
		mNifAniInfo->SetLooping( true );
	}
	else
	{
		/// 애니 정보가 없다면 메모리 해제
		SAFE_DELETE(mNifAniInfo);
	}

	if( mNifAniInfo && param.mDisableAnimation == true )
		mNifAniInfo->Stop();

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

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

	return true;
}

bool cStaticSceneNode::Init( NiNode* node )
{
	/// 기하 오브젝트들을 수집
	CollectGeoms( node );

	/// 빌보드 노드들을 수집
	CollectBillboards( node );

	/// 속성들을 수집
	CollectProperties( node );

	/// 조명을 부착
//	node->AttachEffect( SCENEMAN->GetAmbientLight() );

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

	/// 엔진 노드를 처리
	node->UpdateProperties();
	node->UpdateEffects();
	node->Update( 0.f );

	/// 애니메이션 컨트롤러 정보 수집
	mNifAniInfo->CollectData( node );

	mNifAniInfo->SetAnimType( NiTimeController::APP_INIT );
	mNifAniInfo->SetLooping( true );

	/// 상위 초기화
	mNiObject = node;

	mBoundSphere.Set( GetCenter(), GetRadius() );

	return true;
}

void cStaticSceneNode::SetMaterial( const cMaterialData& material )
{
	cMatPropList::cIterator i = mMatPropList.Begin();
	cMatPropList::cIterator end = mMatPropList.End();

	for( ; i != end; ++i )
	{
		NiMaterialProperty* matProp = (NiMaterialProperty*)*i;

		matProp->SetAmbientColor( material.mAmbient );
		matProp->SetDiffuseColor( material.mDiffuse );
		matProp->SetSpecularColor( material.mSpecular );
		matProp->SetEmittance( material.mEmissive );
		matProp->SetShineness( material.mShininess );
		matProp->SetAlpha( material.mAlpha );
	}

	mMaterial = material;
}

/*
#include "stdafx.h"
#include "StaticSceneNode.h"

#include "ResourceManager.h"
#include "CameraManager.h"
#include "SceneManager.h"

#include "NifAnimationInfo.h"

cStaticSceneNode::cStaticSceneNode( eType type )
: cSceneNode( type )
, mVisibleLevel( 0 )
, mOccludeLevel( 1 )
, mPickedByCamera( false )
{
	mNifAniInfo = new cNifAnimationInfo;
}

cStaticSceneNode::~cStaticSceneNode()
{
	SAFE_DELETE( mNifAniInfo );
}

void cStaticSceneNode::OnProcess( float deltaTime, float accumTime )
{
	/// 알파를 처리
	if( mAlphaForced == false && mOccludeLevel == 1 )
		OnProcessAlpha( deltaTime );

	mTargetAlpha = 1.0f;

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

	mPickedByCamera = false;
	cSceneNode::OnProcess( deltaTime, accumTime );
}

bool cStaticSceneNode::OnVisible( cSceneCuller& culler )
{
	/// 알파를 처리
	if( mOccludeLevel == 1 && mPickedByCamera )
		mTargetAlpha = 0.4f;
	//else
	//	mTargetAlpha = 1.f;

	if( mAlpha < 0.00001f )
		return false;

	return cSceneNode::OnVisible( culler );
}

bool cStaticSceneNode::Init( const cStaticSceneNodeParam& param )
{
	/// 파일을 로딩
	if( RESOURCEMAN->LoadNIF( param.mPathName.Cstr() ) == false )
	{
//		assert( 0 && "failed to load nif file" );
		return false;
	}

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

	/// 상위 초기화
	mNiObject = n;
	param.mNiObject = mNiObject;
	if( cSceneNode::Init( param ) == false )
	{
		return false;
	}

	/// 가시 레벨을 설정
	mVisibleLevel = param.mVisibleLevel;

	/// 차폐 레벨을 설정
	mOccludeLevel = param.mOccludeLevel;

	/// 알파 속성을 설정
	NiAlphaProperty* alphaProp = (NiAlphaProperty*)n->GetProperty( NiProperty::ALPHA );
	mAlphaForced = (alphaProp != 0);

	if( mAlphaForced )
	{
		mAlphaBlended = true;
	}
	else
	{
		mAlphaBlended = false;
	}

	/// 속성들을 수집
	CollectProperties( n );

	/// 재질을 설정
	SetMaterial( param.mMaterial );

	/// 조명을 부착
	n->AttachEffect( SCENEMAN->GetAmbientLight() );
//	n->AttachEffect( LIGHTAGENT->GetSceneDirLight( 0 ) );

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

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

	/// 애니메이션 컨트롤러 정보 수집
	mNifAniInfo->CollectData( n );

	if( mNifAniInfo->GetNumberOfControllers() )
	{
		mNifAniInfo->SetAnimType( NiTimeController::APP_INIT );
		mNifAniInfo->SetLooping( true );
	}
	else
	{
		/// 애니 정보가 없다면 메모리 해제
		SAFE_DELETE(mNifAniInfo);
	}
	return true;
}

bool cStaticSceneNode::Init( NiNode* node )
{
	/// 기하 오브젝트들을 수집
	CollectGeoms( node );

	/// 빌보드 노드들을 수집
	CollectBillboards( node );

	/// 속성들을 수집
	CollectProperties( node );

	/// 조명을 부착
	node->AttachEffect( SCENEMAN->GetAmbientLight() );

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

	/// 엔진 노드를 처리
	node->UpdateProperties();
	node->UpdateEffects();
	node->Update( 0.f );

	/// 애니메이션 컨트롤러 정보 수집
	mNifAniInfo->CollectData( node );

	mNifAniInfo->SetAnimType( NiTimeController::APP_INIT );
	mNifAniInfo->SetLooping( true );

	/// 상위 초기화
	mNiObject = node;

	mBoundSphere.Set( GetCenter(), GetRadius() );

	return true;
}

void cStaticSceneNode::SetMaterial( const cMaterialData& material )
{
	cMatPropList::cIterator i = mMatPropList.Begin();
	cMatPropList::cIterator end = mMatPropList.End();

	for( ; i != end; ++i )
	{
		NiMaterialProperty* matProp = (NiMaterialProperty*)*i;

		matProp->SetAmbientColor( material.mAmbient );
		matProp->SetDiffuseColor( material.mDiffuse );
		matProp->SetSpecularColor( material.mSpecular );
		matProp->SetEmittance( material.mEmissive );
		matProp->SetShineness( material.mShininess );
		matProp->SetAlpha( material.mAlpha );
	}

	mMaterial = material;
}

/*
void cStaticSceneNode::SetMaterial( const cMaterialData& material )
{
	mMaterial = material;

	NiMaterialProperty* pmpt = NULL;
	unsigned int size = mMaterialPropertyList.GetSize();

	for( unsigned int i=0; i<size; ++i )
	{
		pmpt = mMaterialPropertyList.GetAt(i);
		if( pmpt )
		{
			pmpt->SetAmbientColor( material.mAmbient );
			pmpt->SetDiffuseColor( material.mDiffuse );
			pmpt->SetSpecularColor( material.mSpecular );
			pmpt->SetEmittance( material.mEmissive );
			pmpt->SetShineness( material.mShininess );
			pmpt->SetAlpha( material.mAlpha );
		}
	}
}
*/
