#include "stdafx.h"

#include "Mix/IO.h"
#include "Mix/HID.h"
#include "Mix/Graphics.h"
#include "Mix/Scene.h"

#include "Utility/Common.h"
#include "Utility/ViewCameraHelper.h"

#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768

int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
{
	Mix::ENGINE_CONFIG engineConfig;

	engineConfig.flags = Mix::EC_IO_NARROW | Mix::EC_KEYBOARD | Mix::EC_MOUSE | Mix::EC_GRAPHICS | Mix::EC_SCENE;
	engineConfig.pRootDirectoryPath = Utility::GetRootDirectoryPath();
	engineConfig.pPluginDirectoryPath = Utility::GetPluginsDirectoryPath();
	engineConfig.pUserDirectoryPath = Utility::GetUserDirectoryPath( L"Scene\\Basic" );
	engineConfig.pCaption = L"Scene - Basic";
	engineConfig.targetSize = Mix::Point( SCREEN_WIDTH, SCREEN_HEIGHT );
	engineConfig.shaderModel = Mix::Graphics::SHADER_MODEL_3;

	if( Mix::Initialize( engineConfig ) == True )
	{
		Mix::IEngine* pEngine = Mix::GetEnginePtr();

		Mix::IO::IManager* pIOMgr = Mix::IO::GetManagerPtr();
		Mix::HID::IManager* pInputMgr = Mix::HID::GetManagerPtr();
		Mix::Graphics::IManager* pGraphicsMgr = Mix::Graphics::GetManagerPtr();
		Mix::Scene::IManager* pSceneMgr = Mix::Scene::GetManagerPtr();

		Mix::HID::IMouse* pMouse = NULL;
		Mix::HID::IKeyboard* pKeyboard = NULL;

		Mix::Graphics::IDevice* pGraphicsDev = NULL;
		Mix::Graphics::Utility::ICanvasRenderer* pCanvasRenderer = NULL;

		Mix::Scene::IEffectPackage* pSceneEffectPackage = NULL;
		Mix::Scene::IRenderer* pSceneRenderer = NULL;
		Mix::Scene::IViewCamera* pCamera = NULL;

		Utility::ViewCameraHelper viewCamHelper;

		Mix::StringW tempStr;

		////////////////////////////////////////////////////////////////////////////////////////////////////

		pIOMgr->MountDirectory( L"Data" );

		////////////////////////////////////////////////////////////////////////////////////////////////////

		pInputMgr->GetMouse( &pMouse );
		pInputMgr->GetKeyboard( &pKeyboard );

		////////////////////////////////////////////////////////////////////////////////////////////////////

		pGraphicsMgr->GetDevice( &pGraphicsDev );

		if( pGraphicsMgr->CreateCanvasRenderer( &pCanvasRenderer, L"Sample" ) == True )
		{
			Mix::Graphics::Utility::IFont* pFont_16_400 = NULL;

			if( pGraphicsMgr->CreateFontFromFile( L"Data\\Font\\mspg_16_400.fnt", &pFont_16_400 ) == True )
			{
				pCanvasRenderer->SetFont( pFont_16_400 );
			}

			MIX_RELEASE( pFont_16_400 );
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////

		if( pSceneMgr->CreateEffectPackage( L"Data\\", L"effects", &pSceneEffectPackage ) == True )
		{
			Mix::Scene::RENDERER_CONFIG config;

			config.caps = 0;

			if( pSceneMgr->CreateRenderer( pSceneEffectPackage, config, &pSceneRenderer, L"Sample" ) == True )
			{
				Mix::Scene::CAMERA_CONFIG camConfig;
				Mix::Scene::IHemisphereLight* pHSLight = NULL;
				Mix::Scene::IDirectionalLight* pDirLight = NULL;
				Mix::Scene::IPointLight* pPointLight = NULL;
				Mix::Scene::ITerrainModel* pRoomModel = NULL;
				Mix::Scene::IActorModel* pObjectModel = NULL;

				camConfig.targetSize.Set( SCREEN_WIDTH, SCREEN_HEIGHT );
				camConfig.caps = 0;
				camConfig.colorTexFormat = Mix::Graphics::FMT_R8G8B8A8;

				if( pSceneMgr->CreateViewCamera( camConfig, &pCamera ) == True )
				{
					pCamera->SetProjection( MIX_TO_RAD( 60.0f ), ( Float32 )SCREEN_WIDTH / ( Float32 )SCREEN_HEIGHT, 1.0f, 2000.0f );
					pSceneRenderer->AddCamera( pCamera );
				}

				if( pSceneMgr->CreateTerrainModelFromFile( pSceneEffectPackage, L"Data\\Model\\privacy\\room.mtm", &pRoomModel ) == True )
				{
					pSceneRenderer->AddTerrainModel( pRoomModel );
					MIX_RELEASE( pRoomModel );
				}

				if( pSceneMgr->CreateActorModelFromFile( pSceneEffectPackage, L"Data\\Model\\privacy\\light.mam", &pObjectModel ) == True )
				{
					Mix::Matrix4x4 worldMat;

					worldMat.SetTranslation( 0.0f, 11.0f, 0.0f );

					pObjectModel->SetWorldMatrix( worldMat );
					pObjectModel->Reset();

					pSceneRenderer->AddActorModel( pObjectModel );

					MIX_RELEASE( pObjectModel );
				}

				if( pSceneMgr->CreateActorModelFromFile( pSceneEffectPackage, L"Data\\Model\\privacy\\table.mam", &pObjectModel ) == True )
				{
					Mix::Matrix4x4 worldMat;

					worldMat.SetTranslation( 0.0f, 0.0f, 0.0f );

					pObjectModel->SetWorldMatrix( worldMat );
					pObjectModel->Reset();

					pSceneRenderer->AddActorModel( pObjectModel );

					MIX_RELEASE( pObjectModel );
				}

				if( pSceneMgr->CreateActorModelFromFile( pSceneEffectPackage, L"Data\\Model\\privacy\\chair.mam", &pObjectModel ) == True )
				{
					Mix::Matrix4x4 worldMat;

					worldMat.SetRotationY( MIX_PI );
					worldMat.SetRow( 3, Mix::Vector4( 0.0f, 0.0f, -1.0f, 1.0f ) );

					pObjectModel->SetWorldMatrix( worldMat );
					pObjectModel->Reset();

					pSceneRenderer->AddActorModel( pObjectModel );

					MIX_RELEASE( pObjectModel );
				}

				if( pSceneMgr->CreateHemisphereLight( &pHSLight ) == True )
				{
					pHSLight->SetEnabled( True );
					pHSLight->SetSkyColor( Mix::Vector4( 1.0f, 9.0f, 8.0f, 0.25f ) );
					pHSLight->SetGroundColor( Mix::Vector4( 0.4f, 0.6f, 0.7f, 0.15f ) );

					pSceneRenderer->SetHemisphereLight( pHSLight );

					MIX_RELEASE( pHSLight );
				}

				if( pSceneMgr->CreateDirectionalLight( &pDirLight ) == True )
				{
					pDirLight->SetEnabled( False );

					pSceneRenderer->SetDirectionalLight( pDirLight );

					MIX_RELEASE( pDirLight );
				}

				if( pSceneMgr->CreatePointLight( &pPointLight ) == True )
				{
					pPointLight->SetPosition( Mix::Vector3( 0.0f, 5.0f, 0.0f ) );
					pPointLight->SetRadius( 0.2f, 15.0f );

					pSceneRenderer->AddPointLight( pPointLight );

					MIX_RELEASE( pPointLight );
				}
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////

		viewCamHelper.Initialize(	pMouse,
									pKeyboard,
									Mix::Vector3( 0.0f, 3.0f, 0.0f ),
									Mix::Vector2( MIX_TO_RAD( -20.0f ), MIX_TO_RAD( 180.0f ) ),
									7.0f );

		////////////////////////////////////////////////////////////////////////////////////////////////////

		pEngine->ResetFPS();

		while( pEngine->Update() == True )
		{
			////////////////////////////////////////////////////////////////////////////////////////////////////
			// カメラ
			////////////////////////////////////////////////////////////////////////////////////////////////////

			viewCamHelper.Update();

			if( pCamera != NULL )
			{
				pCamera->SetRotation( viewCamHelper.GetRotation() );
				pCamera->SetAt( viewCamHelper.GetAt() );
				pCamera->SetDistance( viewCamHelper.GetDistance() );
			}

			////////////////////////////////////////////////////////////////////////////////////////////////////
			// キャンバス
			////////////////////////////////////////////////////////////////////////////////////////////////////

			if( pCanvasRenderer != NULL )
			{
				tempStr.Sprintf(	L"FPS  [%f]\n"
									L"STPS [%f]\n"
									L"IF   [%d/%d]",	pEngine->GetFPS(),
														pEngine->GetSleepTimePerSec(),
														pEngine->GetInsomniaFrameCountPerSec(), pEngine->GetInsomniaFrameMax() );

				pCanvasRenderer->SetColor(		Mix::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
				pCanvasRenderer->AddString(	16.0f, 16.0f, tempStr.GetConstPtr() );
				pCanvasRenderer->AddString(	16.0f, pGraphicsDev->GetScreenSize().y - 96.0f,
									L"Controls :\n"
									L"  Rotate camera  : Mouse middle button\n"
									L"  Move camera    : Mouse middle button + Shift key\n"
									L"  Distant camera : Mouse middle button + Ctrl key or Mouse wheel\n" );

				Utility::DrawMouseCursor( pCanvasRenderer, pMouse->GetPos() );
			}

			////////////////////////////////////////////////////////////////////////////////////////////////////
			// 更新
			////////////////////////////////////////////////////////////////////////////////////////////////////

			if( pCamera != NULL )
			{
				pCamera->Update();
			}

			if( pSceneRenderer != NULL )
			{
				pSceneRenderer->Update( pEngine->GetDT() );
			}

			if( pCanvasRenderer != NULL )
			{
				pCanvasRenderer->Update();
			}

			////////////////////////////////////////////////////////////////////////////////////////////////////
			// リフレッシュ
			////////////////////////////////////////////////////////////////////////////////////////////////////

			if( pSceneRenderer != NULL )
			{
				pSceneRenderer->Refresh();
			}

			////////////////////////////////////////////////////////////////////////////////////////////////////
			// 描画
			////////////////////////////////////////////////////////////////////////////////////////////////////

			pGraphicsDev->SetViewBounds( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );

			if( pGraphicsDev->Begin() == True )
			{
				if( pCamera != NULL )
				{
					pCamera->Draw();
				}

				if( pCanvasRenderer != NULL )
				{
					pCanvasRenderer->Draw();
				}

				pGraphicsDev->End();
			}

			pGraphicsDev->Present();
		}

		viewCamHelper.Dispose();

		MIX_RELEASE( pCamera );
		MIX_RELEASE( pSceneRenderer );
		MIX_RELEASE( pSceneEffectPackage );
		MIX_RELEASE( pCanvasRenderer );
		MIX_RELEASE( pGraphicsDev );
		MIX_RELEASE( pKeyboard );
		MIX_RELEASE( pMouse );

		Mix::Finalize();
	}

	return 0;
}
