/*!	
	@file
	@brief	ゲーム側から扱うレンダラ
*/

#ifndef CGraphic_h
#define CGraphic_h

#include"../Setup/CompileMode.h"
#include"../template/GlobalPointer.h"
#include"../Auxiliary/Thread/CThreadMutex.h"

#include"Core/CGraphicCore.h"
#include"Core/Driver/CFontDriver.h"
#include"Color.h"


#include"CTexture.h"
#include"CTextureFile.h"
#include"CVertex.h"
#include"CIndex.h"
#include"CVertexShaderDefault.h"
#include"CPixelShaderDefault.h"
#include"CVertexDeclarationDefault.h"
#include"CSurface.h"
#include"CFontCache.h"
#include"CCamera.h"
#include"CModelFile.h"
#include"CSprite.h"
#include<vector>
#include<map>


namespace Maid
{
	class CGraphic : public GlobalPointer<CGraphic>
	{
	public:
		struct SCREENMODE
		{
			enum TYPE
			{
				TYPE_FULL16=0,
				TYPE_FULL32,
				TYPE_WINDOW,
			};

			TYPE	Mode;
			SIZE2DI Size;
			int		RefreshRate;
			bool	IsSoftTnL;
			bool	IsWaitVSync;

			bool	IsAspectLock;
		};

		CGraphic();
		virtual ~CGraphic();

		struct FRAMEINFO
		{
			RENDERMESSAGEQUE	que;
			bool				IsForce;
		};

		void Initialize( const SCREENMODE& mode, const SPFONTDRIVER& pFontDriver, FRAMEINFO* pInfo );
		void NextFrame();
		void Finalize();
		void OnReturnMessage( const RETURNMESSAGEQUE& ret );

		FRAMEINFO* GetFrameInfo();
		const SCREENMODE& GetScreenMode();

		void PostRenderMessage( const SPRENDERMESSAGE& pMess, bool IsForce=false );
		void ChangeScreenMode( const SCREENMODE& Mode  );

		//	各種登録・削除命令---------------
		void RegistSurface( const mstring& id, const SIZE2DI& size, PIXELFORMAT fmt );
		void RegistTexture( const mstring& id, const boost::shared_ptr<CTextureBufferMemory>& pBuff );
		void RegistRTTexture( const mstring& id, const SIZE2DI& size, PIXELFORMAT fmt );
		void RegistVertex( const mstring& id, const SPBINARY& pBuff, VERTEXFORMAT fmt );
		void RegistIndex( const mstring& id, const SPBINARY& pBuff, int Stride );
		void RegistVertexShaderDefault( const mstring& id );
		void RegistVertexShaderCustom( const mstring& id, const SPBINARY& pCode );
		void RegistPixelShaderDefault( const mstring& id );
		void RegistPixelShaderCustom( const mstring& id, const SPBINARY& pCode );
		void RegistVertexDeclarationDefault( const mstring& id );

		void DeleteSurface( const mstring& id );
		void DeleteTexture( const mstring& id );
		void DeleteVertex( const mstring& id );
		void DeleteIndex( const mstring& id );
		void DeleteVertexShader( const mstring& id );
		void DeletePixelShader( const mstring& id );
		void DeleteVertexDeclaration( const mstring& id );



		//	各種描画命令---------------
		void ClearRenderTargetColor( const COLOR_R08G08B08I& Color );
		void ClearRenderTargetZ( float val );

		void SetTexture( const CTexture& tex, int pos = 0 );
		void UnsetTexture( int pos = 0 );
		void UnsetAllTexture();
		void SetVertex( const CVertex& vertex, int pos = 0 );
		void SetIndex( const CIndex& index );
		void SetVertexShader( const CVertexShader& shader );
		void SetPixelShader( const CPixelShader& shader );
		void SetVertexDeclaration( const CVertexDeclaration& decl );

		void SetCamera( const CCamera& camera );

		MATRIX4DF	GetViewMatrix();
		MATRIX4DF	GetProjectionMatrix();
		MATRIX4DF	GetCameraMatrix();


		void SetRenderTarget( const CSurface& target );
		void SetRenderTarget( const CTexture& target );
		void SetDepthStencil( const CSurface& target );
		void ResetRenderTarget();
		void ResetDepthStencil();

		struct VIEWPORT
		{
			RECT2DI Screen;
			float	MinZ;
			float	MaxZ;
		};

		void SetViewPort( const VIEWPORT& view );


		enum CULLINGMODE
		{
			CULLINGMODE_NONE=0,
			CULLINGMODE_LEFT,
			CULLINGMODE_RIGHT
		};

		void SetCullingMode( CULLINGMODE mode );

		enum CMPTYPE
		{
			CMPTYPE_NEVER		= 1,	//!<	常に通る
			CMPTYPE_LESS		= 2,	//!<	o >  n
			CMPTYPE_EQUAL		= 3,	//!<	o == n
			CMPTYPE_LESSEQUAL	= 4,	//!<	o >= n
			CMPTYPE_GREATER		= 5,	//!<	o <  n
			CMPTYPE_NOTEQUAL	= 6,	//!<	o != n
			CMPTYPE_GREATEREQUAL= 7,	//!<	o <= n
			CMPTYPE_ALWAYS		= 8,	//!<	常にダメ
		};

		void SetRenderStateZWriteEnable( bool Enable );
		void SetRenderStateZWriteFunc( CMPTYPE Type );
		void SetRenderStateZTestEnable( bool Enable );


		enum FILTERTYPE
		{
			FILTERTYPE_POINT,
			FILTERTYPE_LINEAR,
			FILTERTYPE_ANISOTROPIC,
		};

		void SetSamplerStateMagFilter( int Stage, FILTERTYPE type );
		void SetSamplerStateMinFilter( int Stage, FILTERTYPE type );

		enum TEXTUREADDRESS
		{
			TEXTUREADDRESS_WRAP,
			TEXTUREADDRESS_MIRROR,
			TEXTUREADDRESS_CLAMP,
		};

		void SetSamplerStateAddressU( int Stage, TEXTUREADDRESS address );
		void SetSamplerStateAddressV( int Stage, TEXTUREADDRESS address );


		/////////////////	２Ｄ周りの描画
		/*!
		 	@enum	BLTSTATE CVideoRenderEx.h
		 	@brief	描画タイプ
		 */
		enum BLTSTATE
		{
			BLTSTATE_NORMAL=0,	//!<	普通描画
			BLTSTATE_ADD,		//!<	加算描画
			BLTSTATE_SUB,		//!<	減算描画
			BLTSTATE_MUL,		//!<	乗算描画
			BLTSTATE_REVERSE,	//!<	反転描画
			BLTSTATE_MAX,		//!<	色の強いほう

			_BLTSTATE_MAX,	//!<	全部でいくつあるか？
		};

		void SetBltState( BLTSTATE state );
		void SetFilterType( FILTERTYPE type );


		void Fill    ( const POINT2DF& Pos, const SIZE2DF& Size, const COLOR_A08R08G08B08I& Color );
		void Fill    ( const RECT2DF&  rc, const COLOR_A08R08G08B08I& Color );
		void FillSR  ( const RECT2DF& Rect, const SIZE2DF& Scale, float Rotate, const VECTOR3DF& vec, const POINT2DF& Center, const COLOR_A08R08G08B08I& ColorLT, const COLOR_A08R08G08B08I& ColorRT, const COLOR_A08R08G08B08I& ColorLB, const COLOR_A08R08G08B08I& ColorRB );

		void Blt  ( const POINT2DF& Pos, const CTexture& tex, const RECT2DI& rc, const POINT2DF& Center = POINT2DF(0,0), unt08 Alpha = 0xFF );
		void BltS ( const POINT2DF& Pos, const CTexture& Src, const RECT2DI& rc, const SIZE2DF& Scale, const POINT2DF& Center=POINT2DF(0,0), unt08 Alpha=0xFF );
		void BltR ( const POINT2DF& Pos, const CTexture& Src, const RECT2DI& rc, float Rotate, const VECTOR3DF& vec=VECTOR3DF(0,0,1), const POINT2DF& Center=POINT2DF(0,0), unt08 Alpha=0xFF );
		void BltSR( const POINT2DF& Pos, const CTexture& Src, const RECT2DI& rc, const SIZE2DF& Scale, float Rotate, const VECTOR3DF& vec=VECTOR3DF(0,0,1), const POINT2DF& Center=POINT2DF(0,0), unt08 Alpha=0xFF );

		void BltSprite  ( const POINT2DF& Pos, const SPRITE& Sprite, unt08 Alpha = 0xFF );
		void BltSpriteS ( const POINT2DF& Pos, const SPRITE& Sprite, const SIZE2DF& Scale, unt08 Alpha = 0xFF );
		void BltSpriteR ( const POINT2DF& Pos, const SPRITE& Sprite, float Rotate, const VECTOR3DF& vec, unt08 Alpha = 0xFF );
		void BltSpriteSR( const POINT2DF& Pos, const SPRITE& Sprite, const SIZE2DF& Scale, float Rotate, const VECTOR3DF& vec, unt08 Alpha = 0xFF );
		void BltPolygon ( const POINT2DF& Pos, const CTexture& Src, const MySTL::vector<POINT2DI>& Poly, unt08 Alpha = 0xFF );


		SPFONT CreateFont( int FontNo, const SIZE2DI& size, bool IsAntialias, bool IsBold, bool IsItalic ) const;
		SPFONT CreateFont( const mstring& FontName, const SIZE2DI& size, bool IsAntialias, bool IsBold, bool IsItalic ) const;
		//! テキストの描画方向
		/*! 
		 */
		enum TEXTDIRECTION
		{
			TEXTDIRECTION_LEFT,		//!< Text の最初の文字がPos.x,Pos.y にくるように描画する（横書き）
			TEXTDIRECTION_RIGHT,	//!< Text の最後の文字がPos.x,Pos.y にくるように描画する（横書き）
			TEXTDIRECTION_TOP,		//!< Text の最初の文字がPos.x,Pos.y にくるように描画する（縦書き）
			TEXTDIRECTION_BOTTOM,	//!< Text の最後の文字がPos.x,Pos.y にくるように描画する（縦書き）
		};
		/// 文字列描画
		void AddGaizi( unt32 no, const CTextureFile& tex );
		void BltText( const POINT2DF& Pos, const SPFONT& pFont, const COLOR_A08R08G08B08I& Color, const mstring& Text, int StrCount=-1, TEXTDIRECTION eDir=TEXTDIRECTION_LEFT );
		///	数字描画
		void BltNumber( const POINT2DF& Pos, const CTexture& Src, const RECT2DI* pRect, int Number, int Len=-1, TEXTDIRECTION dir=TEXTDIRECTION_LEFT );


		/////////////////	２Ｄ周りの描画終了



		/////////////////	３Ｄ描画
		enum PRIMITIVE
		{
			PRIMITIVE_POINTLIST=0,
			PRIMITIVE_LINELIST,
			PRIMITIVE_LINESTRIP,
			PRIMITIVE_TRIANGLELIST,
			PRIMITIVE_TRIANGLESTRIP,
			PRIMITIVE_TRIANGLEFAN,
		};

		void DrawPrimitive( PRIMITIVE prim, unt StartVertex, unt PrimitiveCount );
		void DrawPrimitiveUP( PRIMITIVE prim, const void* pStartVertex, unt Stride, unt PrimitiveCount );
		void DrawIndexedPrimitive( PRIMITIVE prim, int BaseVertexOffset, unt MinIndex, unt NumVertices, unt StartIndex, unt PrimitiveCount );
		void DrawIndexPrimitiveUP( PRIMITIVE prim, int MinIndex, int NumVertices, const void* pVertex, int VertexSize,
														int PrimitiveCount, const void* pIndex, int IndexSize  );

		void SetBlt3DZTest( bool IsEnable );

		void Fill3DSR( const POINT3DF& Pos, const SIZE2DF& Size, const SIZE2DF& Scale, float Rotate, const VECTOR3DF& vec, const POINT3DF& Center, const COLOR_A08R08G08B08I& ColorLT, const COLOR_A08R08G08B08I& ColorRT, const COLOR_A08R08G08B08I& ColorLB, const COLOR_A08R08G08B08I& ColorRB );
		void Fill3D( const MATRIX4DF& mat, const SIZE2DF& Size, const POINT3DF& Center, const COLOR_A08R08G08B08I& ColorLT, const COLOR_A08R08G08B08I& ColorRT, const COLOR_A08R08G08B08I& ColorLB, const COLOR_A08R08G08B08I& ColorRB );

		void Blt3D  ( const POINT3DF& Pos, const CTexture& Src, const RECT2DI& Rect, const POINT3DF& Center=POINT3DF(0,0,0), unt08 Alpha=0xFF );
		void Blt3DS   ( const POINT3DF& Pos, const CTexture& Src, const RECT2DI& Rect, const SIZE2DF& Scale, const POINT3DF& Center=POINT3DF(0,0,0), unt08 Alpha=0xFF );
		void Blt3DR   ( const POINT3DF& Pos, const CTexture& Src, const RECT2DI& Rect, float Rotate, const VECTOR3DF& vec=VECTOR3DF(0,0,1), const POINT3DF& Center=POINT3DF(0,0,0), unt08 Alpha=0xFF );
		void Blt3DSR  ( const POINT3DF& Pos, const CTexture& Src, const RECT2DI& Rect, const SIZE2DF& Scale, float Rotate, const VECTOR3DF& vec=VECTOR3DF(0,0,1), const POINT3DF& Center=POINT3DF(0,0,0), unt08 Alpha=0xFF );


		void Blt3D  ( const MATRIX4DF& mat, const CTexture& Src, const RECT2DI& Rect, const POINT3DF& Center=POINT3DF(0,0,0), unt08 Alpha=0xFF );

		void Blt3D  ( const MATRIX4DF& mat, const CTexture& Src, const RECT2DI& Rect, const POINT3DF& Center, const COLOR_A08R08G08B08I& ColorLT, const COLOR_A08R08G08B08I& ColorRT, const COLOR_A08R08G08B08I& ColorLD, const COLOR_A08R08G08B08I& ColorRD  );



		void BltModel  ( const CModelFile& Model, const POINT3DF& Pos, unt08 Alpha=0xFF );
		void BltModelS ( const CModelFile& Model, const POINT3DF& Pos, const SIZE3DF& Scale, unt08 Alpha=0xFF );
		void BltModelR ( const CModelFile& Model, const POINT3DF& Pos, float Rotate, const VECTOR3DF& vec, unt08 Alpha=0xFF );
		void BltModelSR( const CModelFile& Model, const POINT3DF& Pos, const SIZE3DF& Scale, float Rotate, const VECTOR3DF& vec, unt08 Alpha=0xFF );

		void BltModel  ( const CModelFile& Model, const MATRIX4DF& mat, unt08 Alpha=0xFF );


		struct LIGHT
		{
			COLOR_A32R32G32B32F Diffuse;
			VECTOR3DF	Direction;
		};


		void BltModelTone  ( const CModelFile& Model, const CTexture& Shadow, const LIGHT& Light, int Rinkaku, const POINT3DF& Pos, unt08 Alpha=0xFF );
		void BltModelToneS ( const CModelFile& Model, const CTexture& Shadow, const LIGHT& Light, int Rinkaku, const POINT3DF& Pos, const SIZE3DF& Scale, unt08 Alpha=0xFF );
		void BltModelToneR ( const CModelFile& Model, const CTexture& Shadow, const LIGHT& Light, int Rinkaku, const POINT3DF& Pos, float Rotate, const VECTOR3DF& vec, unt08 Alpha=0xFF );
		void BltModelToneSR( const CModelFile& Model, const CTexture& Shadow, const LIGHT& Light, int Rinkaku, const POINT3DF& Pos, const SIZE3DF& Scale, float Rotate, const VECTOR3DF& vec, unt08 Alpha=0xFF );

		void BltModelTone  ( const CModelFile& Model, const CTexture& Shadow, const LIGHT& Light, int Rinkaku, const MATRIX4DF& mat, unt08 Alpha=0xFF );

		//	各種描画命令終了---------------

		void CopySurface( const mstring& id );
		bool IsCopySurfaceEnd( const mstring& id );
		SPSURFACEBUFFER GetCopySurface( const mstring& id );
		void SendVideoInfo();
		mstring GetVideoInfo();


	protected:
		void BltPrimitive  ( const CModelFile::LAYERINFO::PRIMITIVE& pri, const MATRIX4DF& mat, int VertexCount, unt08 Alpha );
		CVertexShader& SerchModelShaderVS  ( const CModelFile::LAYERINFO::PRIMITIVE& pri );
		CPixelShader&  SerchModelShaderPS  ( const CModelFile::LAYERINFO::PRIMITIVE& pri );
		CVertexDeclaration&  SerchModelShaderDC  ( const CModelFile::LAYERINFO::PRIMITIVE& pri );

		void BltPrimitiveTone  ( const CModelFile::LAYERINFO::PRIMITIVE& pri, const CTexture& Shadow, const LIGHT& Light, int Rinkaku, const MATRIX4DF& mat, const MATRIX4DF& world, int VertexCount, unt08 Alpha );
		CVertexShader& SerchModelShaderVSTone  ( const CModelFile::LAYERINFO::PRIMITIVE& pri );
		CPixelShader&  SerchModelShaderPSTone  ( const CModelFile::LAYERINFO::PRIMITIVE& pri );
		CVertexDeclaration&  SerchModelShaderDCTone  ( const CModelFile::LAYERINFO::PRIMITIVE& pri );

		const CTexture&	GetFont( const SPFONT& pFont, unt32 Code );
	protected:
		virtual void LocalInitialize(){}
		virtual void LocalFinalize(){}

		SCREENMODE	m_ScreenMode;
		FRAMEINFO*	m_pFrameInfo;
		CFontCache	m_FontCache;



		MATRIX4DF	m_ViewMatrix;
		MATRIX4DF	m_ProjectionMatrix;
		MATRIX4DF	m_CameraMatrix;
		MATRIX4DF	m_Blt3DParentMatrix;
		bool		m_IsBlt3DZTest;

	protected:
		CThreadMutex	m_ReturnDateMutex;
		struct MEMORYSURFACE
		{
			SPSURFACEBUFFER pSurface;
		};

		typedef MySTL::map<mstring,MEMORYSURFACE> MEMORYSURFACEMAP;
		MEMORYSURFACEMAP	m_MemorySurface;
		mstring				m_VideoInfo;

		typedef MySTL::map<unt32,CTextureFile> GAIZIMAP;
		GAIZIMAP			m_GaiziMap;

	protected:
		const CTexture* m_pTextureCache[8];	//	現在設定されているテクスチャキャッシュ

	protected:
		BLTSTATE		m_BltState;
		FILTERTYPE		m_FilterType;
		SPFONTDRIVER	m_pFontDriver;

	protected:	//	FillXXX() の時のシェーダー
		MySTL::vector<CVertexShaderDefault>	m_VertexShaderFill;
		MySTL::vector<CPixelShaderDefault>	m_PixelShaderFill;
	
	protected:	//	BltXXX() の時のシェーダー
		MySTL::vector<CVertexShaderDefault>	m_VertexShaderBlt;
		MySTL::vector<CPixelShaderDefault>	m_PixelShaderBlt;

	protected:	//	Blt3DXXX() の時のシェーダー
		MySTL::vector<CVertexShaderDefault>	m_VertexShaderBlt3D;

	protected:	//	テキスト描画時() の時のシェーダー
		MySTL::vector<CPixelShaderDefault>	m_PixelShaderFont;

	protected:	//	モデル描画時のアレ
		MySTL::vector<CVertexShaderDefault>			m_VertexShaderModel;
		MySTL::vector<CPixelShaderDefault>			m_PixelShaderModel;
		MySTL::vector<CVertexDeclarationDefault>	m_DeclModel;
	protected:	//	モデル描画時のアレ
		MySTL::vector<CVertexShaderDefault>			m_VertexShaderModelTone;
		MySTL::vector<CVertexShaderDefault>			m_VertexShaderModelToneLine;
		MySTL::vector<CPixelShaderDefault>			m_PixelShaderModelTone;
		MySTL::vector<CVertexDeclarationDefault>	m_DeclModelTone;
	};
}


#endif
