/***************************************************************/
//
//
//		DirectX	[ rendererdx9.cpp ]
//
//											Author	kazuki tanaka
//											Date	2017 5/10
/*---------------------------------------------------------------
■Update : 2017/5/10
			rendererdx9.cppの作成

/*---------------------------------------------------------------
	Include File
---------------------------------------------------------------*/


//#include <Windows.h>
//#include <stdio.h>
//#include <d3dx9.h>

#include "rendererdx9.h"

#include "game_manager.h"
#include "renderer_manager.h"

//#pragma comment (lib,"d3d9.lib")
//#pragma comment (lib,"d3dx9.lib")
//#pragma comment (lib,"dxguid.lib")


/*---------------------------------------------------------------
	Macro Difinition
---------------------------------------------------------------*/


/*---------------------------------------------------------------
	Const Number Difinition
---------------------------------------------------------------*/				


/*----------------------------------------------------------------
	static member variable Initialize 
----------------------------------------------------------------*/



// RendererDX9 Constructor
RendererDX9::RendererDX9( )
	: pD3D(nullptr)
	, pD3DDevice(nullptr)
{

	// Menber Clear Process

}

// RendererDX9 Destructor
RendererDX9::~RendererDX9( )
{

	// Do Nothing!!

}

// RendererDX9 Create Instance 
Renderer* RendererDX9::Create( void )
{

	// Create Class Instance
	RendererDX9* pObject;
	pObject = new RendererDX9;

	return pObject;

}

// RendererDX9 Initialize
void RendererDX9::Init( HWND hWnd, bool bWindow )
{

	// Initialize Process
	
	//DirectX9の設定(初期化)
	//IDirect3DDevice9インターフェースの取得

	D3DPRESENT_PARAMETERS d3dpp={0};			// デバイスの動作を設定する構造体
	D3DDISPLAYMODE d3ddm;						// ディスプレイの設定

	pD3D = Direct3DCreate9(D3D_SDK_VERSION);	// D3D9インターフェースの取得
	if( pD3D==NULL ){
		return;
	}

	//現在のデバイスモードの取得
	if(FAILED( pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddm))){
		return;
	}

	//デバイスのプレゼンテーションパラメーターの設定
	ZeroMemory(&d3dpp,sizeof(d3dpp));

	const int SCREEN_WIDTH  = 1280;
	const int SCREEN_HEIGHT = 720;

	d3dpp.BackBufferWidth=SCREEN_WIDTH;			// backbufferのサイズ(横)
	d3dpp.BackBufferHeight=SCREEN_HEIGHT;		// backbufferのサイズ(縦)
	d3dpp.BackBufferFormat=d3ddm.Format;		// FULLSCREENのときはこれの限りではない、WINDOWMODEは別
	d3dpp.BackBufferCount=1;					// backBufferの数
	d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;		// doubleBufferの切り替え
	d3dpp.EnableAutoDepthStencil=TRUE;			// ※重要 ;DepthStencilの使用
	d3dpp.AutoDepthStencilFormat=D3DFMT_D16;	// D3Dフォーマットの設定
	d3dpp.Windowed=bWindow;						// WindowMode trueでウィンドウ falseでFullScreen(※WindowStyleをpopup)
	d3dpp.FullScreen_RefreshRateInHz
	=D3DPRESENT_RATE_DEFAULT;					// 書き換えスピード(fullscreenのときのみ設定可能)
	d3dpp.PresentationInterval
	=D3DPRESENT_INTERVAL_DEFAULT;				// fullscreenの時のみ 書き換えを見せるかどうか

	//Direct3Dデバイスの設定
	if(FAILED( pD3D ->CreateDevice(
	D3DADAPTER_DEFAULT,							// デフォルトのアダプターを取得
	D3DDEVTYPE_HAL,								// 描画処理typeの指定(ハードでやるかソフトでやるか)HAL=ハード
	hWnd,										// どのウィンドウの上に作成するか(フォーカスウィンドウ)
	D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,		// デバイス作成オプションフラグ(今回はハードウェアで頂点処理をする)
	&d3dpp,										// その他設定
	&pD3DDevice )))								// デバイスのポインタのポインタ
	//失敗したらNULLが返る
	{

		MessageBox( hWnd, "処理速度を下げます", "注意", MB_OK );
		if(FAILED( pD3D ->CreateDevice(
		D3DADAPTER_DEFAULT,							// デフォルトのアダプターを取得
		D3DDEVTYPE_HAL,								// 描画処理typeの指定(ハードでやるかソフトでやるか)HAL=ハード
		hWnd,										// どのウィンドウの上に作成するか(フォーカスウィンドウ)
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,		// デバイス作成オプションフラグ(今回はソフトウェアで頂点処理をする)
		&d3dpp,										// その他設定
		&pD3DDevice )))								// デバイスのポインタのポインタ
		{	

			if(FAILED( pD3D ->CreateDevice(
			D3DADAPTER_DEFAULT,							// デフォルトのアダプターを取得
			D3DDEVTYPE_REF,								// 描画処理typeの指定(ハードでやるかソフトでやるか)
			hWnd,										// どのウィンドウの上に作成するか(フォーカスウィンドウ)
			D3DCREATE_SOFTWARE_VERTEXPROCESSING,		// デバイス作成オプションフラグ(今回はソフトウェアで頂点処理をする)
			&d3dpp,										// その他設定
			&pD3DDevice )))								// デバイスのポインタのポインタ
			{
				return;
			}
		}
	}
		 
	// レンダ―ステートの設定
	//pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);					// 時計回りを裏面とする
	pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );					// 裏時計回りを裏面とする
	//pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);					// 両面を描画する

	pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );				// ポリゴンを実線で描く
	//pD3DDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);				// ポリゴンをワイヤーフレームで描く

	// 現在画面に描かれている状態にして今から描画する内容
	pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );					// 半透明処理
	pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );			// 元のα
	pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );		// 先のα(INVは逆の意味,ここではα値の逆)

	// αテストの設定
	pD3DDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
	pD3DDevice->SetRenderState( D3DRS_ALPHAREF, 128 );
	pD3DDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );

	// サンプラーステートの設定(stagesteat texturestate)
	pD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
	pD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );

	pD3DDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
	pD3DDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );
	//pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
	//pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
	
	// テクスチャステートの設定( α透過処理設定 )
	pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
	pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
	pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );

	pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
	pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
	pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );



}

// RendererDX9 Uninitialize
void RendererDX9::Uninit( void )
{

	{ // Uninitialize Process
	
		// デバイスの破棄
		SAFE_RELEASE( pD3DDevice )

		// Direct3Dオブジェクトの破棄
		SAFE_RELEASE( pD3D )

	}	// -> End
}

// RendererDX9 Draw Start
bool RendererDX9::RenderBegin( void )
{

	// Draw Begin Process

	D3DXCOLOR screenClearColor = D3DCOLOR_RGBA(192,192,192,0);
	
	// バックバッファとZバッファのクリア
	pD3DDevice->Clear(0,NULL,
	D3DCLEAR_TARGET								// 色
	| D3DCLEAR_ZBUFFER,							// 深度情報
	screenClearColor,							// クリア色
	1.0f,										// クリア深度値
	0);											// ステンシル値

	// 描画の開始
	if( SUCCEEDED( pD3DDevice ->BeginScene( ) )) {
		return true;
	}

	return false;
}

// RendererDX9 Draw End
void RendererDX9::RenderEnd( void )
{

	// Draw End Process
	pD3DDevice->EndScene( );
	
}

// RendererDX9 Present 
void RendererDX9::Present( void )
{

	// Present Process
	pD3DDevice->Present( NULL, NULL, NULL, NULL );
	
}

// RendererDX9 GetDevice
LPDIRECT3DDEVICE9 RendererDX9::GetDevice( void )
{

	// return DirectX9 Device Object
	return pD3DDevice;

}

// RendererDX9 SetRenderState
void RendererDX9::RenderState( int* stateArray, bool* flaglist, int dataNumber )
{

	for( int index = 0; index < dataNumber; index++ ){
		pD3DDevice->SetRenderState( (D3DRENDERSTATETYPE)stateArray[index], flaglist[index] );
	}

}

// Global Func : Get Device
LPDIRECT3DDEVICE9 RendererDevice::GetDevice( void )
{

	Renderer* pRenderer= GameManager::Operate( )->GetRendererManager( )->GetRenderer( );
	return	(dynamic_cast< RendererDX9* >(pRenderer)->GetDevice());

}





