#pragma once

#include "Mix/Tool/Win32/Core/Dynamics/Design/Basic.h"

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{
	class World;
	class KinematicCharacter;
}}}}

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{ namespace Design{

	class Part;

	class Actor : public Mix::Tool::Win32::Dynamics::Design::Basic
	{
	private:
		Mix::Tool::Win32::Dynamics::Design::Part* m_pRoot;

		Mix::Tool::Win32::Dynamics::KinematicCharacter* m_pKinematicCharacter;
		D3DXVECTOR3 m_KCCenterPos;
		D3DXMATRIX m_KCLoadMat;
		D3DXMATRIX m_KCStoreMat;

		Mix::Tool::Win32::Dynamics::Design::Part* m_pCastMotionPart;
		D3DXMATRIX m_ReceiveMotionMat;

		D3DXQUATERNION m_AngularVelocity;
		D3DXVECTOR3 m_LinearVelocity;

	private:
		Actor( void );

	public:
		virtual ~Actor( void );

	public:
		void Initialize(	Basic::COORDINATE_SYSTEM coordinateSystem,
							const D3DXMATRIX& initalWorldMat,
							const D3DXQUATERNION& defCenterRot,
							const D3DXVECTOR3& defCenterPos );

		Mix::Tool::Win32::Dynamics::Design::Part* CreateRoot(	const D3DXVECTOR3& localPos,
																const D3DXMATRIX& worldMat,
																const D3DXQUATERNION& centerRot,
																const D3DXVECTOR3& centerPos );

		Mix::Tool::Win32::Dynamics::Design::Part* CreateRoot(	const D3DXVECTOR3& localPos,
																const D3DXQUATERNION& worldRot,
																const D3DXVECTOR3& worldPos,
																const D3DXQUATERNION& centerRot,
																const D3DXVECTOR3& centerPos );

		Mix::Tool::Win32::Dynamics::Design::Part* GetRoot( void );

		void SetWorld( Mix::Tool::Win32::Dynamics::World* pWorld );

		Mix::Tool::Win32::Dynamics::KinematicCharacter* KinematicCharacter_Get( void );
		void KinematicCharacter_Set( Mix::Tool::Win32::Dynamics::KinematicCharacter* pKinematicCharacter );

		const D3DXVECTOR3& KinematicCharacter_GetCenterPosition( void ) const;
		void KinematicCharacter_SetCenterPosition( const D3DXVECTOR3& pos );

		const D3DXMATRIX& KinematicCharacter_GetLoadMatrix( void ) const;
		const D3DXMATRIX& KinematicCharacter_GetStoreMatrix( void ) const;

		const D3DXMATRIX& GetReceiveMotionMatrix( void ) const;

		void SetMode( Basic::MODE mode );

		bool Update_NeedVelocity( void ) const;
		void Update_SetVelocity( const D3DXQUATERNION& av, const D3DXVECTOR3& lv );

		void Reset( void );
		void Update( void );
		void Refresh( void );
		void Draw(	Mix::Tool::Win32::Graphics::LineHelper* pLineHelper,
					bool bKinematicCharacter,
					bool bSensor,
					bool bBody,
					bool bJoint,
					const D3DXVECTOR4& selectedColor,
					const D3DXVECTOR4& kcColor,
					const D3DXVECTOR4& sensorColor,
					const D3DXVECTOR4& bodyColor,
					const D3DXVECTOR4& jointAxisColor,
					const D3DXVECTOR4& jointBallColor,
					const D3DXVECTOR4& jointLimitColor,
					float jointScale,
					float axisScale,
					bool bDrawPart );

	public:
		virtual void SetWorldMatrix( const D3DXMATRIX& worldMat );

		virtual bool IsWorldMatrixRefreshed( void ) const;
		virtual bool IsWorldPositionRefreshed( void ) const;

	protected:
		virtual void OnWorldChanged( const Basic::WORLD_CHANGED_EVENT_ARGS& args );
		virtual void OnModeChanged( const Basic::MODE_CHANGED_EVENT_ARGS& args );
		virtual void OnColliderChanged( void );
		virtual void OnRefresh( void );
		virtual bool OnRefreshWorldTransform( D3DXMATRIX& worldMat );

	private:
		void KC_UpdateCenterTransform( void );
		void Reset( Mix::Tool::Win32::Dynamics::Design::Part* pPart );
		void UpdateCastMotionPart( void );
		Mix::Tool::Win32::Dynamics::Design::Part* FindCastMotionPart( Mix::Tool::Win32::Dynamics::Design::Part* pPart );
		bool IsCastMotionPart( const Mix::Tool::Win32::Dynamics::Design::Basic* pBasic ) const;
		bool IsCastMotion( const Mix::Tool::Win32::Dynamics::Design::Basic* pBasic );
		void CastMotion( const D3DXMATRIX& worldMat );

	public:
		MIX_OBJECT_TYPE( Mix::Tool::Win32::Object::DYNAMICS__MODEL_DESIGNER, Mix::Tool::Win32::Dynamics::Design::Basic )

		friend class Factory;
		friend class Basic;
		friend class Part;
	};

}}}}}
