////////////////////////////////////////////////////////////////////////////////////////////////////
// インクルード
////////////////////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <vector>

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

#include "Utility/Common.h"
#include "Utility/PlayableCamera.h"
#include "Utility/PlayableCharacter.h"

#ifdef _DEBUG
	#include <crtdbg.h>
#endif //_DEBUG

////////////////////////////////////////////////////////////////////////////////////////////////////
// 定数
////////////////////////////////////////////////////////////////////////////////////////////////////

/*
	スクリーン
*/

#define SCREEN_WIDTH ( 1024 )
#define SCREEN_HEIGHT ( 768 )

/*
	ディレクショナルライト
*/

static const Mix::Vector4 DIR_LIGHT_COLOR( 1.0f, 0.99f, 0.98f, 0.1f );

/*
	スポットライト
*/

static const UInt32 LOCAL_LIGHT_NUM = 3;
static const Mix::Vector4 LOCAL_LIGHT_COLOR( 1.0f, 0.9f, 0.85f, 0.7f );
static const Float32 LOCAL_LIGHT_TIME = 1.0f;
static const Mix::Vector3 LOCAL_LIGHT_POS_TABLE[LOCAL_LIGHT_NUM] =
{
	Mix::Vector3( -25.0f, 13.0f, 0.0f ),
	Mix::Vector3(   0.0f, 13.0f, 0.0f ),
	Mix::Vector3( +25.0f, 13.0f, 0.0f ),
};

/*
	ボックス
*/

static const UInt32 BOX_TYPE_NUM = 2;
static const Float32 BOX_WIDTH = 2.0f;
static const Float32 BOX_GAP = 0.1f;
static const Float32 BOX_HEIGHT_TABLE[BOX_TYPE_NUM] =
{
	0.9f,
	1.0f,
};

#ifdef _DEBUG
	static const UInt32 BOX_H_NUM = 4;
	static const UInt32 BOX_V_NUM = 4;
#else //_DEBUG
	static const UInt32 BOX_H_NUM = 6;
	static const UInt32 BOX_V_NUM = 6;
#endif //_DEBUG

/*
	デバッグ
*/

#ifdef _DEBUG
	static const UInt32 DEBUG_DRAW_FLAGS = Mix::Scene::DDF_ACTORMODEL_MESH | Mix::Scene::DDF_DYNAMICS;
#endif //_DEBUG

////////////////////////////////////////////////////////////////////////////////////////////////////
// クラス
////////////////////////////////////////////////////////////////////////////////////////////////////

/*
	シンプルオブジェクト( ボックス )
*/

class SimpleObject : public Utility::Actor
{
public:
	MIX_DECLARE_ALLOCATOR()

private:
	Mix::Scene::IRenderer* m_pRenderer;
	Mix::Scene::IActorModel* m_pModel;

public:
	SimpleObject( Mix::Scene::IRenderer* pRenderer, Mix::Scene::IActorModel* pModel )
	{
		MIX_ASSERT( pRenderer != NULL );
		MIX_ASSERT( pModel != NULL );

		MIX_ADD_REF( pRenderer );
		m_pRenderer = pRenderer;

		MIX_ADD_REF( pModel );
		m_pModel = pModel;
	}

	virtual ~SimpleObject( void )
	{
		MIX_ASSERT( m_pRenderer != NULL );
		MIX_ASSERT( m_pModel != NULL );

		m_pRenderer->RemoveActorModel( m_pModel );

		MIX_RELEASE( m_pModel );
		MIX_RELEASE( m_pRenderer );
	}

public:
	virtual void OnUpdate( Float32 dt )
	{
		m_pModel->Update();
	}

	virtual Boolean OnRefresh( void )
	{
		m_pModel->Refresh();

		return ( m_pModel->IsIgnored() == False );
	}
};

/*
	スポットライトオブジェクト

	  照明範囲に入ったら点灯
	  照明範囲から出たら、徐々に消灯
*/

class SpotLightObject : public Utility::Actor
{
private:
	class Context : public Mix::Scene::IContactListener
	{
	public:
		MIX_DECLARE_ALLOCATOR()

	public:
		static Context* CreateInstance( void )
		{
			return MIX_NEW_T( SpotLightObject::Context );
		}

	private:
		Float32 m_Ratio;
		Float32 m_Timer;

	private:
		Context( void ) :
		m_Ratio( 0.0f ),
		m_Timer( 0.0f )
		{
		}

		virtual ~Context( void ) {}

	public:
		void Update( Float32 dt )
		{
			if( m_Timer > MIX_FLOAT_EPSILON )
			{
				m_Ratio = m_Timer / LOCAL_LIGHT_TIME;
				m_Timer = max( m_Timer - dt, 0.0f );
			}
			else
			{
				m_Ratio = 0.0f;
				m_Timer = 0.0f;
			}
		}

		Boolean IsEnabled( void ) const { return ( m_Timer > MIX_FLOAT_EPSILON ); }
		Float32 GetRatio( void ) const { return m_Ratio; }

		virtual void OnContact( Mix::Scene::IDynamicsObject* pDynamicsObjectA,
								Mix::Scene::IDynamicsObject* pDynamicsObjectB,
								UInt32 pointNum,
								const Mix::Scene::DYNAMICS_CONTACT_POINT* points )
		{
			if( pDynamicsObjectB->GetType() == Mix::Scene::IDynamicsObject::ACTOR_KINEMATIC_CHARACTER )
			{
				m_Timer = LOCAL_LIGHT_TIME;
			}
		}
	};

private:
	Mix::Scene::ISpotLight* m_pLight;
	Mix::Scene::IGhost* m_pSensor;
	SpotLightObject::Context* m_pContext;

public:
	SpotLightObject( Mix::Scene::ISpotLight* pLight, Mix::Scene::IGhost* pSensor ) :
	m_pContext( NULL )
	{
		MIX_ASSERT( pLight != NULL );
		MIX_ASSERT( pSensor != NULL );

		Mix::Scene::IDynamicsObject* pDynObj = NULL;
		Mix::Scene::ISensor* pDynSensor = NULL;
		UInt32 filterMask;

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

		MIX_ADD_REF( pLight );
		m_pLight = pLight;

		MIX_ADD_REF( pSensor );
		m_pSensor = pSensor;

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

		m_pSensor->GetDynamicsObject( &pDynObj );
		MIX_ASSERT( pDynObj != NULL );

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

		/*
			キャラクターだけに反応するセンサーに変更
		*/

		MIX_ASSERT( pDynObj->GetType() == Mix::Scene::IDynamicsObject::SIMPLE_SENSOR );
		pDynSensor = static_cast<Mix::Scene::ISensor*>( pDynObj );

		filterMask = Mix::Dynamics::OF_CHARACTER;
		pDynSensor->SetFilterMask( filterMask );

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

		m_pContext = SpotLightObject::Context::CreateInstance();
		pDynObj->AddContactListener( m_pContext );

		MIX_RELEASE( pDynObj );
	}

	virtual ~SpotLightObject( void )
	{
		MIX_RELEASE( m_pContext );
		MIX_RELEASE( m_pSensor );
		MIX_RELEASE( m_pLight );
	}

public:
	virtual void OnUpdate( Float32 dt )
	{
		Mix::Vector4 color = m_pLight->GetColor();

		color.a = m_pContext->GetRatio();

		m_pLight->SetEnabled( m_pContext->IsEnabled() );
		m_pLight->SetColor( color );

		m_pContext->Update( dt );
	}

	virtual Boolean OnRefresh( void )
	{
		return True;
	}
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// サブ関数
////////////////////////////////////////////////////////////////////////////////////////////////////

/*
	ボックスの配置
*/

void PutBoxes(	Mix::Scene::IRenderer* pRenderer,
				Mix::Scene::IActorModel** ppBoxModels,
				Int32 xn, Int32 yn, Int32 zn,
				const Mix::Vector3& pos,
				std::vector<Utility::Actor*>& actorList )
{
	MIX_ASSERT( pRenderer != NULL );
	MIX_ASSERT( ppBoxModels != NULL );
	MIX_ASSERT( xn > 0 );
	MIX_ASSERT( yn > 0 );
	MIX_ASSERT( zn > 0 );

	Mix::Vector3 basePos;
	Mix::Vector3 putPos;

	basePos.x = pos.x - ( BOX_WIDTH * static_cast<Float32>( xn ) * 0.5f );
	basePos.z = pos.z - ( BOX_WIDTH * static_cast<Float32>( zn ) * 0.5f );
	basePos.y = pos.y;

	for( Int32 x = 0; x < xn; x++ )
	{
		putPos.x = basePos.x + BOX_WIDTH * static_cast<Float32>( x );

		for( Int32 z = 0; z < zn; z++ )
		{
			putPos.z = basePos.z + BOX_WIDTH * static_cast<Float32>( z );
			putPos.y = basePos.y;

			for( Int32 y = 0; y < yn; y++ )
			{
				UInt32 index = Mix::Rand() % 2;
				Mix::Scene::IActorModel* pCloneModel;

				if( ppBoxModels[index]->Clone( &pCloneModel ) == True )
				{
					Float32 height = BOX_HEIGHT_TABLE[index];

					Mix::Scene::IActorDynamicsDirector* pDynDir;

					Mix::Vector3 gap;
					Mix::Matrix4x4 worldMat;

					gap.x = ( Mix::RandF() * 2.0f - 1.0f ) * BOX_GAP;
					gap.z = ( Mix::RandF() * 2.0f - 1.0f ) * BOX_GAP;
					gap.y = 0.0f;

					pCloneModel->GetDynamicsDirector( &pDynDir );
					pDynDir->Deactivate();
					MIX_RELEASE( pDynDir );

					putPos.y += height * 0.5f;

					worldMat.SetTranslation( putPos + gap );
					pCloneModel->SetWorldMatrix( worldMat );
					pCloneModel->Reset();
					pRenderer->AddActorModel( pCloneModel );

					putPos.y += height * 0.5f;

					actorList.push_back( MIX_NEW_T( SimpleObject, pRenderer, pCloneModel ) );
					MIX_RELEASE( pCloneModel );
				}
			}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// メイン
////////////////////////////////////////////////////////////////////////////////////////////////////

int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
{
#ifdef _DEBUG
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif //_DEBUG

	Mix::ENGINE_CONFIG engineConfig;

	engineConfig.flags = Mix::EC_IO_NARROW | Mix::EC_KEYBOARD | Mix::EC_MOUSE | Mix::EC_GAMEPAD | Mix::EC_GRAPHICS | Mix::EC_SCENE | Mix::EC_DYNAMICS | Mix::EC_PARALLEL;
	engineConfig.pRootDirectoryPath = Utility::GetRootDirectoryPath();
	engineConfig.pPluginDirectoryPath = Utility::GetPluginsDirectoryPath();
	engineConfig.pUserDirectoryPath = Utility::GetUserDirectoryPath( L"Scene\\Dynamics\\Basic" );
	engineConfig.pCaption = L"Scene - Dynamics ( 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::HID::IKeyboard* pKeyboard = NULL;
		Mix::HID::IMouse* pMouse = NULL;
		Mix::HID::IGamepad* pGamepad = NULL;

		Mix::Dynamics::IManager* pDynamicsMgr = Mix::Dynamics::GetManagerPtr();

		Mix::Graphics::IManager* pGraphicsMgr = Mix::Graphics::GetManagerPtr();
		Mix::Graphics::IDevice* pGraphicsDev = NULL;
		Mix::Graphics::Utility::ICanvasRenderer* pCanvasRenderer = NULL;
		Mix::Graphics::Utility::IFont* pFont = NULL;

		Mix::Scene::IManager* pSceneMgr = Mix::Scene::GetManagerPtr();
		Mix::Scene::IEffectPackage* pSceneEffectPackage = NULL;
		Mix::Scene::IRenderer* pSceneRenderer = NULL;
		Mix::Scene::IUniversalCamera* pCamera = NULL;

#ifdef _DEBUG
		Mix::Graphics::Utility::IPerspectiveRenderer* pDebDrawer = NULL;
#endif //_DEBUG

		Utility::PlayableCamera* pPlayCam = NULL;
		Utility::PlayableCharacter* pPlayChar = NULL;

		std::vector<Utility::Actor*> actorList;

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

		pIOMgr->MountDirectory( L"Data" );

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

		pInputMgr->GetKeyboard( &pKeyboard );
		pInputMgr->GetMouse( &pMouse );
		pInputMgr->FindGamepad( Mix::HID::GAMEPAD_UNKNOWN, &pGamepad );

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

		pGraphicsMgr->GetDevice( &pGraphicsDev );

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

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

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

			config.caps = Mix::Scene::RCAP_DYNAMICS | Mix::Scene::RCAP_SHADOW_MAPPING;
			config.octree.minAABB.Set( -60.0f,  -1.0f, -35.0f );
			config.octree.maxAABB.Set( +60.0f, +10.0f, +35.0f );
			config.octree.subdivisionLevel = 2;

			if( pSceneMgr->CreateRenderer( pSceneEffectPackage, config, &pSceneRenderer, MIX_DEBUGNAME ) == True )
			{
				Mix::Scene::CAMERA_CONFIG camConfig;
				Float32 camFar;

				Mix::Scene::IDirectionalLight* pDirLight = NULL;
				Mix::Scene::ITerrainModel* pRoomModel = NULL;
				Mix::Scene::IActorModel* pBoxModel[2] = { NULL };
				Mix::Scene::IActorModel* pCharModel = NULL;

				camConfig.targetSize.Set( SCREEN_WIDTH, SCREEN_HEIGHT );

				camConfig.caps = Mix::Scene::RCAP_DYNAMICS | Mix::Scene::RCAP_SHADOW_MAPPING;
				camConfig.depthBuffFormat = Mix::Graphics::FMT_D16;
				camConfig.colorTexFormat = Mix::Graphics::FMT_R8G8B8A8;
				camFar = 100.0f;

				if( pSceneMgr->CreateUniversalCamera( camConfig, &pCamera ) == True )
				{
					Mix::Scene::ICamera::SHADOW_MAPPING_SETTINGS smSettings = pCamera->GetShadowMappingSettings();

					pCamera->SetBackgroundColor( Mix::Vector4( 0.1f, 0.1f, 0.1f, 1.0f ) );
					pCamera->SetProjection( MIX_TO_RAD( 60.0f ), 0.01f, camFar );

					smSettings.depthBias = -0.030099971f;
					pCamera->SetShadowMappingSettings( smSettings );
					pCamera->SetShadowMappingEnabled( True );

					pSceneRenderer->AddCamera( pCamera );
				}

				if( pSceneMgr->CreateDirectionalLight( &pDirLight ) == True )
				{
					Mix::Vector4 dlColor;
					Mix::Vector3 dlDir;

					dlColor = DIR_LIGHT_COLOR;
					dlDir = Mix::Vector3( -1.0f, -1.0f, -1.0f ).ToNormalize();

					pDirLight->SetEnabled( True );
					pDirLight->SetColor( dlColor );
					pDirLight->SetDirection( dlDir );

					pSceneRenderer->SetDirectionalLight( pDirLight );
				}

				for( UInt32 i = 0; i < LOCAL_LIGHT_NUM; i++ )
				{
					const Mix::Vector3& pos = LOCAL_LIGHT_POS_TABLE[i];

					Mix::Scene::ISpotLight* pSpotLight = NULL;

					if( pSceneMgr->CreateSpotLight( &pSpotLight ) == True )
					{
						Mix::Dynamics::ICapsuleShape* pSensorShape = NULL;
						Mix::Scene::IGhost* pSensor = NULL;
						Mix::String sensorName;

						pSpotLight->SetColor( LOCAL_LIGHT_COLOR );
						pSpotLight->SetPosition( pos );
						pSpotLight->SetRange( 30.0f );
						pSpotLight->SetDirection( Mix::Vector3( 0.0f, -1.0f, 0.0f ) );
						pSpotLight->SetCone( MIX_TO_RAD( 10.0f ), MIX_TO_RAD( 80.0f ) );

						sensorName.Sprintf( L"SpotLight%d", i );

						if( pDynamicsMgr->CreateCapsuleShape( Mix::Dynamics::AXIS_Y, 15.0f, 12.0f, &pSensorShape, MIX_DEBUGNAME ) == True )
						{
							if( pSceneMgr->CreateBasisGhost( pSensorShape, False, &pSensor, sensorName.GetConstPtr() ) == True )
							{
								pSensor->SetWorldPosition( Mix::Vector3( pos.x, 7.5f, pos.z ) );

								pSceneRenderer->AddSpotLight( pSpotLight );
								pSceneRenderer->AddGhost( pSensor );

								actorList.push_back( MIX_NEW_T( SpotLightObject, pSpotLight, pSensor ) );
							}
						}


						MIX_RELEASE( pSensor );
						MIX_RELEASE( pSensorShape );
						MIX_RELEASE( pSpotLight );
					}
				}

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

				if( pSceneMgr->CreateActorModelFromFile( pSceneEffectPackage, L"Data\\Model\\warehouse\\box_s.mam", &( pBoxModel[0] ) ) == True )
				{
					if( pSceneMgr->CreateActorModelFromFile( pSceneEffectPackage, L"Data\\Model\\warehouse\\box_m.mam", &( pBoxModel[1] ) ) == True )
					{
						PutBoxes( pSceneRenderer, pBoxModel, BOX_H_NUM, BOX_V_NUM, BOX_H_NUM, Mix::Vector3( 0.0f, 0.0f, 0.0f ), actorList );
						PutBoxes( pSceneRenderer, pBoxModel, BOX_H_NUM, BOX_V_NUM, BOX_H_NUM, Mix::Vector3( -25.0f, 0.0f, 0.0f ), actorList );
						PutBoxes( pSceneRenderer, pBoxModel, BOX_H_NUM, BOX_V_NUM, BOX_H_NUM, Mix::Vector3( +25.0f, 0.0f, 0.0f ), actorList );

						MIX_RELEASE( pBoxModel[1] );
					}

					MIX_RELEASE( pBoxModel[0] );
				}

				if( pSceneMgr->CreateActorModelFromFile( pSceneEffectPackage, L"Data\\Model\\human.mam", &pCharModel ) == True )
				{
					Mix::Scene::IActorKinematicCharacter* pKChar = NULL;
					UInt32 filterMask;
					Mix::Matrix4x4 worldMat;

					pCharModel->GetKinematicCharacter( &pKChar );
					MIX_ASSERT( pKChar != NULL );

					filterMask = pKChar->GetFilterMask( Mix::Scene::DKC_CAST );
					MIX_SETBIT( filterMask, Mix::Dynamics::OF_SENSOR );
					pKChar->SetFilterMask( Mix::Scene::DKC_CAST, filterMask );

					worldMat.SetTranslation( 0.0f, 0.0f, 20.0f );
					pCharModel->SetWorldMatrix( worldMat );
					pCharModel->Reset();

					if( pGamepad != NULL )
					{
						MIX_ASSERT( pCamera != NULL );

						actorList.push_back( MIX_NEW_T( Utility::PlayableCharacter, pCamera, pGamepad, pCharModel ) );
						actorList.push_back( MIX_NEW_T( Utility::PlayableCamera, pCamera, pGamepad, pCharModel ) );
					}

					pSceneRenderer->AddActorModel( pCharModel );

					MIX_RELEASE( pKChar );
					MIX_RELEASE( pCharModel );
				}

				MIX_RELEASE( pDirLight );
			}
		}

#ifdef _DEBUG
		pGraphicsMgr->CreatePerspectiveRenderer( &pDebDrawer, MIX_DEBUGNAME );
		pSceneRenderer->Debug_SetPerspectiveRenderer( pDebDrawer );
#endif //_DEBUG

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

		pEngine->ResetFPS();

		while( pEngine->Update() == True )
		{
			std::vector<Utility::Actor*>::iterator it_a_begin = actorList.begin();
			std::vector<Utility::Actor*>::iterator it_a_end = actorList.end();
			std::vector<Utility::Actor*>::iterator it_a;

			Float32 dt = pEngine->GetDT();
			Float32 baseDt = pEngine->GetBaseDT();

			Mix::String tempStr;
			Mix::Vector2 txtSize;

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

			if( pMouse->GetButtonState( 0 ) & Mix::HID::DOWN )
			{
				pCamera->DragObject( pGraphicsDev->GetScreenSize(), pMouse->GetPos() );
			}

#ifdef _DEBUG
			if( pKeyboard->GetKeyState( Mix::HID::KEY_D ) & Mix::HID::PRESSED )
			{
				UInt32 debdDrawFlags = pCamera->Debug_GetDrawFlags();

				if( MIX_TESTBIT( debdDrawFlags, DEBUG_DRAW_FLAGS ) != DEBUG_DRAW_FLAGS )
				{
					debdDrawFlags ^= DEBUG_DRAW_FLAGS;
				}
				else
				{
					debdDrawFlags |= DEBUG_DRAW_FLAGS;
				}

				pCamera->Debug_SetDrawFlags( debdDrawFlags );
			}
#endif //_DEBUG

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

			/*
				Mouse Cursor
			*/

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

			/*
				FPS
			*/

			tempStr.Sprintf( L"FPS %f", pEngine->GetFPS() );

			pCanvasRenderer->SetColor( Mix::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
			pCanvasRenderer->AddString( 16.0f, 16.0f, tempStr.GetConstPtr() );

			/*
				Desription
			*/

			Float32 txtOffset;

#ifdef _DEBUG
			tempStr.Sprintf( L"%s",	L"Controls :\n"
									L"  Pick object       : Mouse left button\n"
									L"  Control character : Gamepad\n"
									L"  Toggle debug      : Keyboard D key" );

			txtOffset = 32.0f;
#else //_DEBUG
			tempStr.Sprintf( L"%s",	L"Controls :\n"
									L"  Pick object       : Mouse left button\n"
									L"  Control character : Gamepad" );

			txtOffset = 16.0f;
#endif //_DEBUG

			txtSize = Mix::Graphics::Utility::MeasureString( pFont, tempStr.GetConstPtr() );

			pCanvasRenderer->SetColor( Mix::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
			pCanvasRenderer->AddString( 16.0f, static_cast<Float32>( SCREEN_HEIGHT ) - txtSize.y - txtOffset, tempStr.GetConstPtr() );

#ifdef _DEBUG
			Mix::Scene::DEBUG_PROFILE_RENDERER_GENERAL debProfGene;

			if( pSceneRenderer->Debug_GetProfile( Mix::Scene::DPT_GENERAL, &debProfGene, sizeof( debProfGene ) ) > 0 )
			{
				Mix::Rectangle barRect( 0, SCREEN_HEIGHT - 16, SCREEN_WIDTH, 16 );
				Utility::BAR_ELEMENT barElems[4];
				static const UInt32 barElemNum = sizeof( barElems ) / sizeof( Utility::BAR_ELEMENT );

				barElems[0].value = debProfGene.updElapsedTime;
				barElems[1].value = debProfGene.refElapsedTime;
				barElems[2].value = debProfGene.drawElapsedTime;
				barElems[3].value = debProfGene.finElapsedTime;

				Utility::FillBarColor( barElems, barElemNum );
				Utility::DrawBar( pCanvasRenderer, barRect, barElems, barElemNum, dt );
			}
#endif //_DEBUG

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

			for( it_a = it_a_begin; it_a != it_a_end; ++it_a )
			{
				( *it_a )->OnUpdate( dt );
			}

			pSceneRenderer->Update( dt, baseDt );

			pCanvasRenderer->Update();

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

			it_a = actorList.begin();

			while( it_a != actorList.end() )
			{
				Utility::Actor* pActor = ( *it_a );

				if( pActor->OnRefresh() == True )
				{
					it_a++;
				}
				else
				{
					it_a = actorList.erase( it_a );
					MIX_DELETE_T( Actor, pActor );
				}
			}

			pSceneRenderer->Refresh();

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

			pGraphicsDev->SetViewBounds( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
			pGraphicsDev->Clear( True, False, Mix::Vector4( 0.1f, 0.1f, 0.1f, 1.0f ) );

			if( pGraphicsDev->Begin() == True )
			{
				pCamera->Draw();
				pCanvasRenderer->Draw();

				pGraphicsDev->End();
			}

			pGraphicsDev->Present();
		}

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

		for( std::vector<Utility::Actor*>::iterator it_a = actorList.begin(); it_a != actorList.end(); ++it_a )
		{
			Utility::Actor* pActor = ( *it_a );
			MIX_DELETE_T( Actor, pActor );
		}

#ifdef _DEBUG
		MIX_RELEASE( pDebDrawer );
#endif //_DEBUG

		MIX_RELEASE( pCamera );
		MIX_RELEASE( pSceneRenderer );
		MIX_RELEASE( pSceneEffectPackage );

		MIX_RELEASE( pFont );
		MIX_RELEASE( pCanvasRenderer );
		MIX_RELEASE( pGraphicsDev );
		MIX_RELEASE( pGamepad );
		MIX_RELEASE( pMouse );
		MIX_RELEASE( pKeyboard );

		Mix::Finalize();
	}

	return 0;
}
