/* ==========================================================================
* 작 성 자 : 이순규
* 작 성 일 : 2006.12.20
* 내    용 : 동적 장면 노드
* 주의사항 : 
*===========================================================================*/
#pragma once

#include "SceneNode.h"
#include "ActorManagerForPartition.h"
#include "TrailGeometry.h"

class cEffectSceneNode;
//class cShadowGeometry;
class cSoundSceneNode;
//class cObjectNameCard;
//class cChatBubble;
//class cBaseObject;

/// 동적 장면 노드 인자
class cDynamicSceneNodeParam : public cSceneNodeParam
{
public:
	cDynamicSceneNodeParam();

public:
	bool mUseShadow;
};

inline cDynamicSceneNodeParam::cDynamicSceneNodeParam()
: mUseShadow( true )
{
}

struct sTrailInfo
{
	cRibbonGeometry*	mRibbonGeom;
	float				mLifeTime;

	unsigned int		mStartLink;
	unsigned int		mEndLink;

	bool				mLoop;

	sTrailInfo()
	{
		mRibbonGeom = 0;
		mLoop = false;
	}
	~sTrailInfo()
	{
		SAFE_NIDELETE(mRibbonGeom);
	}
};

/// 동적 장면 노드
class cDynamicSceneNode : public cSceneNode
{
	friend class cSceneManager;

public:
	/// 처리
	virtual void OnProcess( float deltaTime, float accumTime  );
	virtual bool OnVisible( cSceneCuller& culler );

	virtual bool Pick( const NiPoint3& origin, const NiPoint3& dir );

	/// 이동
	virtual bool Move( float /*x*/, float /*y*/ ) { return true; }

	/// 분할 객체를 바꾼다. (기존 객체를 새로운 객체로 대체한다.)
	virtual bool			ChangeParts( unsigned int /*partIdx*/, const char* /*fileName*/ ) { return true; }
	virtual bool			ChangeParts( unsigned int partsIdx, NiNode* pNode );

	virtual bool			ChangePartsTexture( unsigned int /*partsIdx*/, const char* /*fileName*/ ) { return true; }
	virtual bool			ChangePartsTexture( unsigned int /*partsIdx*/, NiTexture* /*pTex*/ );

	/// 더미에 객체를 링크 언링크 한다. (무기등 추가 모델 정보)
	virtual unsigned int	LinkObrject( unsigned int /*dummyIdx*/, const char* /*fileName*/ ) { return UINT_MAX; }
	virtual unsigned int	LinkObject( unsigned int dummyIdx, NiNode* pNode );

	/// 링크 해제
	void					UnLinkObject( unsigned int linkIdx );

	cEffectSceneNode* 		LinkEffect( unsigned int dummyIdx, const char* fileName, NiTransform* trans, bool bLoop, bool bFollow );
	void					UnLinkEffect( cEffectSceneNode* pnode );

	void ClearAllEffect();

	///// 실제로 객체를 링크하는 것이 아니고,
	cSoundSceneNode*		LinkSound( unsigned long soundIdx, bool bLoop );
	void					UnLinkSound( cSoundSceneNode* pnode );

	//cEffectSceneNode*		LinkDamage( unsigned int dummyIdx, const char* fileName, NiTransform* trans, bool bLoop, bool bFollow );

	sTrailInfo*				LinkTrailEffect( cString str, float lifeTime, unsigned int link1, unsigned int link2, float lenPer, float factor );
	void					UnLinkTrailEffect( sTrailInfo* pInfo );


	///// 현재 객체에 링크된 유효 이펙트 노드인지 검사한다.
	bool					IsLinkedEffect( cEffectSceneNode* pnode );
	bool					IsLinkedSound( cSoundSceneNode* pnode );

	NiAVObject*				GetLinkObject( unsigned int linkId );

	/// 
	void	UpdateAniScaleFactor( float factor );

	/// 중점을 리턴
	/// 주의: 바운딩 박스의 중심이 아니다.
	virtual NiPoint3 GetObjectCenter() = 0;

	/// 분할 객체
	virtual NiAVObject*		GetPartObject( unsigned int index ) const;
	virtual NiAVObject*		GetPartWeapon( unsigned int /*objectIdx*/, bool /*left*/ ) { return 0; }

	/// 액터 관리자를 리턴
	inline cActorManagerForPartition* GetActorManager() { return mActorManager; }

	/// 현재 애니메이션
	cActorManagerForPartition::EventCode GetTargetAnimation() const { return mTargetAnimation; }
	virtual void SetTargetAnimation( unsigned int code );
	virtual bool UpdateTargetAnimation( unsigned int code );

	/// 게임 객체에 대한 연결
	//inline cBaseObject* GetGameObject() { return mpGameObject; }

	/// 객체의 각종 Morpher를 제어하기 위해서..
	void StartMorpher();
	void StopMorpher();

	/// 말풍선 표현.
	//virtual void ActiveChatBubble( LPTSTR msg, unsigned long color );

	/// 객체 이름표
	//void UpdateNameCardTextValue();
	//void UpdateNameCardGaugeValue();

	/// 
	void GotoLastFrame();

	/// 반지름
	virtual float GetRadius() const;

	inline void SetBaseAnimationIndex( unsigned int idx ) { mBaseAnimationIndex = idx; }
	inline unsigned int GetBaseAnimationIndex() { return mBaseAnimationIndex; }

protected:
	cDynamicSceneNode( eType type = eDYNAMIC );
	virtual ~cDynamicSceneNode();

	/// 초기화
	virtual bool Init( const cDynamicSceneNodeParam& param );


	/// picking 용 박스, 구, 실린더 객체를 모은다.
	void CollectPickData( NiAVObject* pobj );

	void LinkDataInit( NiNode* node );

	/// 
	//virtual cObjectNameCard* CreateNameCard( cBaseObject* pObj ) = 0;
	//virtual void CreateShadow();

	///->
	/// 링크 정보를 초기화 한다.
	virtual bool InitLinkInfo() = 0;

	/// 분할 정보를 초기화 한다.
	virtual bool InitPartsName() = 0;

	/// Idle애니가 여러개 있을경우 초기화 한다.
	virtual void InitializeRandomIdle() {}

	/// 바이패드를 별도로 움직이는 경우에 대한처리 (시선 처리 등..)
	virtual void	UpdateBipedRootTransforms( float /*time*/ ) {}

	/// 객체를 따로 보관한다.
	void			KeepParts( unsigned int partIdx );

	/// 가시에 들어왔을때 별도 처리가 필요
	virtual void AddToVisibleArray( NiVisibleArray* psolidArray, NiVisibleArray* pskinedArray, NiVisibleArray* palphaArray );
	//virtual void AddDepthPlaneObject() const;

	virtual void ProcessTrail( float /*delta*/ ) {}

	virtual bool CheckParts( unsigned int /*partIdx*/ ) { return false; }

protected:
	struct sBoneDataObj : public NiMemObject
	{
		/// 뼈대 정보
		NiSkinData::BoneData* pBoneData;

		/// 뼈의 정점 정보
		NiTPrimitiveSet<NiSkinData::BoneVertData*> BoneVertData;
	};

	struct sLinkInfo : public NiMemObject
	{
		/// 더미 인덱스
		unsigned int DummyIndex;

		/// 실제 Geom 데이터의 참조
		//		NiGeometry* pObject;
		NiAVObject* pObject;
	};

protected:
	/// 액터 관리자
	cActorManagerForPartition* mActorManager;

	/// 현재 애니 인덱스
	cActorManagerForPartition::EventCode mTargetAnimation;

	/// 눈 깜빡임 모핑 제어
	NiGeomMorpherController* mMorpherController;
	float mEyeMorpherTime;
	bool mStopMorpherProcess;

	/// 윙크 주기
	float mWinkInterval;

	/// Idle애니 정보
	NiTPrimitiveArray<cActorManagerForPartition::EventCode>* mRandomIdle;

	/// 각 더미에 Link되어진 객체의 정보
	NiTPrimitiveArray<sLinkInfo*>* mLinkInfo;

	/// 현재 걸려 있는 Effect 정보
	NiTPointerList<cEffectSceneNode*> mEffectList;
	NiTPointerList<cSoundSceneNode*> mSoundList;

	/// 각 파트별 Geom객체의 이름 (그래픽 제작시 결정된 이름을 등록한다.)
	NiTPointerMap<unsigned int, const char*> mPartsNameMap;

	/// 객체 상단을 위한 정보
	NiAVObject*		mHead;
	float			mHeadDist;

	/// 객체의 정보를 표시하기 위한 객체
	//cObjectNameCard*		mpNameCard;

	/// 말풍선
	//cChatBubble*			mpChatBubble;

	typedef tList<void*> cPickDataList;
	cPickDataList mPickDataList;

	NiTPointerList<sTrailInfo*> mRibbonList;
	NiTPointerList<sTrailInfo*> mDeleteRibbonList;

protected:
	/// 애니 속도 조절자
	float	mScaleAccumTime;
	float	mLastTime;
	float	mScaleFactor;

	/// 애니메이션 관리인덱스를 참조하기 위해 모델 정보를 갖는다.
	cModelInstance* mModel;

	/// 게임 객체에 대한 연결정보(씬정보에서 게임객체를 연결하는 다리역할)
	//cBaseObject*	mpGameObject;

	unsigned int	mBaseAnimationIndex;

	/// 반지름
	float mRadius;
};
