#include "spotDialog.h"

#include "Mix/Scene/IManager.h"
#include "Mix/Scene/IRenderer.h"
#include "Mix/Scene/ICamera.h"
#include "Mix/Scene/ISpotLight.h"

SpotDialog::SpotDialog( void ) :
m_pCamera( NULL ),
m_pLight( NULL )
{
}

SpotDialog::~SpotDialog( void )
{
}

void SpotDialog::Initialize( Mix::Scene::IManager* pSceneManager, Mix::Scene::IRenderer* pSceneRenderer, Mix::Scene::ICamera* pCamera )
{
	MIX_ASSERT( pSceneManager != NULL );
	MIX_ASSERT( pSceneRenderer != NULL );
	MIX_ASSERT( pCamera != NULL );

	MIX_ADD_REF( pCamera );
	m_pCamera = pCamera;

	if( pSceneManager->CreateSpotLight( &m_pLight ) == True )
	{
		Mix::Vector3 pos( 0.0f, 5.8f, -7.8f );
		Mix::Vector3 target( 0.0f, 1.0f, 0.0f );

		m_pLight->SetEnabled( True );
		m_pLight->SetPosition( pos );
		m_pLight->SetDirection( ( target - pos ).ToNormalize() );
		m_pLight->SetColor( Mix::Vector4( 0.67f, 0.79f, 1.0f, 0.82f ) );
		m_pLight->SetExponent( 1.0f );
		m_pLight->SetAttenuation( 0.24f, 0.0f, 0.0f );
		m_pLight->SetCone( MIX_TO_RAD( 0.1f ), MIX_TO_RAD( 20.0f ) );
		m_pLight->SetRange( 16.0f );

		pSceneRenderer->AddSpotLight( m_pLight );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 自身の設定
	////////////////////////////////////////////////////////////////////////////////////////////////////

	SetCaption( L"Spot" );
	SetPosition( Mix::Vector2( 256.0f, 128.0f ) );
	SetSize( Mix::Point( SpotDialog::DLG_WIDTH, SpotDialog::DLG_HEIGHT ) );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// コントロールの追加
	////////////////////////////////////////////////////////////////////////////////////////////////////

	UInt32 ddFlags = m_pCamera->Debug_GetDrawFlags();
	Boolean bDisplayCone = ( MIX_TESTBIT( ddFlags, Mix::Scene::DDF_SPOTLIGHT_SHAPE ) == Mix::Scene::DDF_SPOTLIGHT_SHAPE );
	Boolean bDisplayBounds = ( MIX_TESTBIT( ddFlags, Mix::Scene::DDF_SPOTLIGHT_BOUNDS ) == Mix::Scene::DDF_SPOTLIGHT_BOUNDS );

	const Mix::Vector4& color = m_pLight->GetColor();

	Int32 itemY = SpotDialog::ITEM_Y;

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

	m_EnabledCB.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_EnabledCB.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_EnabledCB.SetText( L"Enabled" );
	m_EnabledCB.SetState( m_pLight->IsEnabled() );
	m_EnabledCB.Initialize( this, SpotDialog::CTRL_ENABLED_CB );
	itemY += SpotDialog::ITEM_Y_STEP;

#ifdef _DEBUG

	m_DisplayConeCB.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_DisplayConeCB.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_DisplayConeCB.SetText( L"Display cone" );
	m_DisplayConeCB.SetState( bDisplayCone );
	m_DisplayConeCB.Initialize( this, SpotDialog::CTRL_DISPLAY_CONE_CB );
	itemY += SpotDialog::ITEM_Y_STEP;

	m_DisplayBoundsCB.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_DisplayBoundsCB.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_DisplayBoundsCB.SetText( L"Display bounds" );
	m_DisplayBoundsCB.SetState( bDisplayBounds );
	m_DisplayBoundsCB.Initialize( this, SpotDialog::CTRL_DISPLAY_BOUNDS_CB );
	itemY += SpotDialog::ITEM_Y_STEP;

#endif //_DEBUG

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

	m_ColorC.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_ColorC.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_ColorC.SetText( L"" );
	m_ColorC.SetAlphaEnabled( True );
	m_ColorC.SetValue( color );
	m_ColorC.Initialize( this, SpotDialog::CTRL_COLOR_C );
	itemY += SpotDialog::ITEM_Y_STEP;

	m_RedSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_RedSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_RedSF.SetText( L"R" );
	m_RedSF.SetRange( 0.0f, 1.0f );
	m_RedSF.SetStep( 0.01f );
	m_RedSF.SetValue( color.r );
	m_RedSF.Initialize( this, SpotDialog::CTRL_RED_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

	m_GreenSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_GreenSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_GreenSF.SetText( L"G" );
	m_GreenSF.SetRange( 0.0f, 1.0f );
	m_GreenSF.SetStep( 0.01f );
	m_GreenSF.SetValue( color.g );
	m_GreenSF.Initialize( this, SpotDialog::CTRL_GREEN_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

	m_BlueSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_BlueSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_BlueSF.SetText( L"B" );
	m_BlueSF.SetRange( 0.0f, 1.0f );
	m_BlueSF.SetStep( 0.01f );
	m_BlueSF.SetValue( color.b );
	m_BlueSF.Initialize( this, SpotDialog::CTRL_BLUE_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

	m_AlphaSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_AlphaSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_AlphaSF.SetText( L"A" );
	m_AlphaSF.SetRange( 0.0f, 1.0f );
	m_AlphaSF.SetStep( 0.01f );
	m_AlphaSF.SetValue( color.a );
	m_AlphaSF.Initialize( this, SpotDialog::CTRL_ALPHA_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

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

	m_ExponentSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_ExponentSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_ExponentSF.SetText( L"Exponent" );
	m_ExponentSF.SetRange( 1.0f, 50.0f );
	m_ExponentSF.SetStep( 0.1f );
	m_ExponentSF.SetValue( m_pLight->GetExponent() );
	m_ExponentSF.Initialize( this, SpotDialog::CTRL_EXPONENT_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

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

	m_LAttenSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_LAttenSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_LAttenSF.SetText( L"AttenL" );
	m_LAttenSF.SetRange( 0.0f, 1.0f );
	m_LAttenSF.SetStep( 0.1f );
	m_LAttenSF.SetValue( m_pLight->GetLinearAttenuation() );
	m_LAttenSF.Initialize( this, SpotDialog::CTRL_L_ATTEN_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

	m_QAttenSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_QAttenSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_QAttenSF.SetText( L"AttenQ" );
	m_QAttenSF.SetRange( 0.0f, 1.0f );
	m_QAttenSF.SetStep( 0.01f );
	m_QAttenSF.SetValue( m_pLight->GetQuadraticAttenuation() );
	m_QAttenSF.Initialize( this, SpotDialog::CTRL_Q_ATTEN_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

	m_EAttenSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_EAttenSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_EAttenSF.SetText( L"AttenE" );
	m_EAttenSF.SetRange( 0.0f, 1.0f );
	m_EAttenSF.SetStep( 0.001f );
	m_EAttenSF.SetValue( m_pLight->GetExponentAttenuation() );
	m_EAttenSF.Initialize( this, SpotDialog::CTRL_E_ATTEN_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

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

	m_InnerAngleSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_InnerAngleSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_InnerAngleSF.SetText( L"InnerAngle" );
	m_InnerAngleSF.SetRange( 0.0f, 180.0f );
	m_InnerAngleSF.SetStep( 0.1f );
	m_InnerAngleSF.SetValue( MIX_TO_DEG( m_pLight->GetConeInnerAngle() ) );
	m_InnerAngleSF.Initialize( this, SpotDialog::CTRL_INNER_ANGLE_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

	m_OuterAngleSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_OuterAngleSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_OuterAngleSF.SetText( L"OuterAngle" );
	m_OuterAngleSF.SetRange( 0.0f, 180.0f );
	m_OuterAngleSF.SetStep( 0.1f );
	m_OuterAngleSF.SetValue( MIX_TO_DEG( m_pLight->GetConeOuterAngle() ) );
	m_OuterAngleSF.Initialize( this, SpotDialog::CTRL_OUTER_ANGLE_SF );
	itemY += SpotDialog::ITEM_Y_STEP;

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

	m_RangeSF.SetPosition( Mix::Point( SpotDialog::ITEM_X, itemY ) );
	m_RangeSF.SetSize( Mix::Point( SpotDialog::ITEM_WIDTH, SpotDialog::ITEM_HEIGHT ) );
	m_RangeSF.SetText( L"Range" );
	m_RangeSF.SetRange( 0.0f, 20.0f );
	m_RangeSF.SetStep( 0.1f );
	m_RangeSF.SetValue( m_pLight->GetRange() );
	m_RangeSF.Initialize( this, SpotDialog::CTRL_RANGE_SF );
	itemY += SpotDialog::ITEM_Y_STEP;
}

void SpotDialog::OnDispose( void )
{
	MIX_RELEASE( m_pLight );
	MIX_RELEASE( m_pCamera );
}

void SpotDialog::OnCheckBox_Click( Utility::UI::CheckBox* pCheckBox )
{
	UInt32 ddFlags = m_pCamera->Debug_GetDrawFlags();

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

	switch( pCheckBox->GetID() )
	{
	case SpotDialog::CTRL_ENABLED_CB:
		m_pLight->SetEnabled( pCheckBox->GetState() );
		break;

	case SpotDialog::CTRL_DISPLAY_CONE_CB:
		if( pCheckBox->GetState() == True )
		{
			MIX_SETBIT( ddFlags, Mix::Scene::DDF_SPOTLIGHT_SHAPE );
		}
		else
		{
			MIX_RESETBIT( ddFlags, Mix::Scene::DDF_SPOTLIGHT_SHAPE );
		}
		break;
	case SpotDialog::CTRL_DISPLAY_BOUNDS_CB:
		if( pCheckBox->GetState() == True )
		{
			MIX_SETBIT( ddFlags, Mix::Scene::DDF_SPOTLIGHT_BOUNDS );
		}
		else
		{
			MIX_RESETBIT( ddFlags, Mix::Scene::DDF_SPOTLIGHT_BOUNDS );
		}
		break;
	}

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

	m_pCamera->Debug_SetDrawFlags( ddFlags );
}

void SpotDialog::OnSlider_ValueChanged( Utility::UI::SliderF* pSlider )
{
	Mix::Vector4 color = m_pLight->GetColor();

	switch( pSlider->GetID() )
	{
	case SpotDialog::CTRL_RED_SF:
		color.r = pSlider->GetValue();
		m_ColorC.SetValue( color );
		break;
	case SpotDialog::CTRL_GREEN_SF:
		color.g = pSlider->GetValue();
		m_ColorC.SetValue( color );
		break;
	case SpotDialog::CTRL_BLUE_SF:
		color.b = pSlider->GetValue();
		m_ColorC.SetValue( color );
		break;
	case SpotDialog::CTRL_ALPHA_SF:
		color.a = pSlider->GetValue();
		m_ColorC.SetValue( color );
		break;

	case SpotDialog::CTRL_EXPONENT_SF:
		m_pLight->SetExponent( pSlider->GetValue() );
		break;

	case SpotDialog::CTRL_L_ATTEN_SF:
		m_pLight->SetAttenuation( pSlider->GetValue(), m_pLight->GetQuadraticAttenuation(), m_pLight->GetExponentAttenuation() );
		break;
	case SpotDialog::CTRL_Q_ATTEN_SF:
		m_pLight->SetAttenuation( m_pLight->GetLinearAttenuation(), pSlider->GetValue(), m_pLight->GetExponentAttenuation() );
		break;
	case SpotDialog::CTRL_E_ATTEN_SF:
		m_pLight->SetAttenuation( m_pLight->GetLinearAttenuation(), m_pLight->GetQuadraticAttenuation(), pSlider->GetValue() );
		break;

	case SpotDialog::CTRL_INNER_ANGLE_SF:
		m_pLight->SetCone( MIX_TO_RAD( pSlider->GetValue() ), m_pLight->GetConeOuterAngle() );
		break;
	case SpotDialog::CTRL_OUTER_ANGLE_SF:
		m_pLight->SetCone( m_pLight->GetConeInnerAngle(), MIX_TO_RAD( pSlider->GetValue() ) );
		break;

	case SpotDialog::CTRL_RANGE_SF:
		m_pLight->SetRange( pSlider->GetValue() );
		break;
	}
}

void SpotDialog::OnColor_ValueChanged( Utility::UI::Color* pColor )
{
	switch( pColor->GetID() )
	{
	case SpotDialog::CTRL_COLOR_C:
		m_pLight->SetColor( pColor->GetValue() );
		break;
	}
}
