//
// Tools_Mode_FSFX_Template.cpp
//
// Created by JGP 03/02/06
// 
// Copyright (C) 2006 Rebellion (Derby), All Rights Reserved.
//

#include "Core/Asura.h"

#ifdef ASURA_USE_FSFX

#include "Tools_Mode_FSFX_Template.h"

// Asura
#include "Core/Asura_NameTree.h"
#include "Core/Asura_TextureFlags.h"
#include "Core/Asura_TextureManagement.h"
#include "FSFX/Asura_FSFX_Component.h"
#include "FSFX/Asura_FSFX_Template.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Overlay_System.h"
#include "Interface/Asura_TexturePicker_Dialog.h"

// Tools
#include "Tools_Overlays.h"
#include "FSFX/Tools_Mode_FSFX.h"
#include "FSFX/Tools_FSFX_System.h"
#include "Misc/Tools_Modal_Overlay.h"
#include "Interface/Tools_ColourPicker.h"
#include "Texturing/Tools_PickTexture.h"


///////////////////////////////////////////////////////////////////////////////////////
// Static Data
///////////////////////////////////////////////////////////////////////////////////////


Asura_Vector_2 Tools_Mode_FSFX_Template::s_xOverlayPosition( 36.0f, 20.0f );
Asura_Dialog* Tools_Mode_FSFX_Template::s_pxChooseTextureDialog = NULL;


///////////////////////////////////////////////////////////////////////////////////////
// Data type for passing to callbacks
///////////////////////////////////////////////////////////////////////////////////////


/*
	Callbacks take a single argument. We
	need one for buttons like "delete component"
	which we can pass in, so this structure 
	contains a "this" pointer to the editor
	object, the component itself and the index
	of the component.
*/
struct Tools_Mode_FSFX_Template_Callback
{
	Tools_Mode_FSFX_Template* m_pxInstance;
	Asura_FSFX_Component* m_pxComponent;
	int m_iIndex;
};


///////////////////////////////////////////////////////////////////////////////////////
// Construct / destruct
///////////////////////////////////////////////////////////////////////////////////////


/*
	Constructor. Uses the passed in read only
	field to construct either a viewer (read only)
	or editor (read / write) of the given template
*/
Tools_Mode_FSFX_Template::Tools_Mode_FSFX_Template( Asura_FSFX_Template* pxTemplate, const bool bReadOnly )
{

	// store whether this is read only
	// otherwise we will want to put 
	// it in the system...
	m_bReadOnly = bReadOnly;

	// we make a copy of the effect first
	// rather than editing it direct
	m_pxOldTemplate = pxTemplate;
	m_pxTemplate = m_pxOldTemplate->CreateCopy();

	Asura_Assert( m_pxTemplate, "Cant open template editor without a template. Internal Error. See JGP" );

	// set expanded to false at construct time
	for ( Asura_FSFX_ComponentList* pxComponentList = m_pxTemplate->GetComponentList(); pxComponentList; pxComponentList = pxComponentList->Next() )
	{
		pxComponentList->Data()->m_bExpanded = false;
	}
	m_pxCallbackData = NULL;

	// open the overlay...
	InitialiseOverlay();
}


/*
	Destructor. Also does save on the template if
	the template isn't read only
*/
Tools_Mode_FSFX_Template::~Tools_Mode_FSFX_Template()
{

	// first close the overlay
	CloseOverlay();

	// if this is a read only edit then we made a copy at construct
	// time so we can delete it safely here.
	if ( m_bReadOnly )
	{
		delete m_pxTemplate;
	}
	// otherwise we put this new one in the system replacing the old one
	// and we save the current one if we can...
	else
	{
		if ( Tools_Mode_FSFX::GetInstance()->SaveTemplateFile( m_pxTemplate ) )
		{
			Asura_FSFX_System::DeleteTemplate( m_pxOldTemplate->GetNameHash() );	// Replace old template with new one.
			Asura_FSFX_System::AddTemplate( m_pxTemplate );							// Replace old template with new one.
		}
		else
		{
			Asura_Assert( 0, "Can't save template. Discarding changes" );
			delete m_pxTemplate;
		}
	}

	// for now don't display anything in the editor just
	// in case we were displaying this info...
	Tools_FSFX_System::SetOverrideFSFX( NULL );
}


///////////////////////////////////////////////////////////////////////////////////////
// Overlay open and close
///////////////////////////////////////////////////////////////////////////////////////


/*
	Create an overlay with all the components 
	in the template and controls for adding new
	components.
*/
void Tools_Mode_FSFX_Template::InitialiseOverlay()
{

	// first close it if it's open
	CloseOverlay();

	// create an overlay
	Asura_String xName = "FSFX Template: ";
	xName += m_pxTemplate->GetName();
	if ( m_bReadOnly )
	{
		xName += "(RO)";
	}

	Asura_Overlay* pxOverlay = new Asura_Overlay( xName.GetString(), false, &s_xOverlayPosition );
	pxOverlay->m_uID = TOOLS_OVERLAY_FSFX_TEMPLATE_EDIT;
	Asura_Assert( pxOverlay != NULL, "Cant create FSFX template edit overlay" );

	Asura_Vector_2 xOffset( 1.0f, 3.0f );
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Tickbox_Dialog( "Environmental Effect", xOffset, &m_pxTemplate->m_bIsEnvironmentalEffect );
	pxDialog->SetHelpText( "Only one environmental template will be active at any time." );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Priority (1->10)", xOffset, &m_pxTemplate->m_iPriority, 1, 10, 1, "%d" );
	pxDialog->SetHelpText( "Priority is used for sorting multiple FSFX" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog( "New Component", xOffset, _OnCreateComponent, (int)this );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();

	// count parts

	m_iNumComponents = 0;
	for ( Asura_FSFX_ComponentList* pxComponentList = m_pxTemplate->GetComponentList(); pxComponentList; pxComponentList = pxComponentList->Next() )
	{
		m_iNumComponents++;
	}
	m_pxCallbackData = new Tools_Mode_FSFX_Template_Callback[ m_iNumComponents ];

	// add each part

	int iIndex = 0;
	for ( Asura_FSFX_ComponentList* pxComponentList = m_pxTemplate->GetComponentList(); pxComponentList; pxComponentList = pxComponentList->Next() )
	{
		Asura_FSFX_Component* pxComponent = pxComponentList->Data();

		// setup callback data - for re-order / delete / expand buttons
		m_pxCallbackData[ iIndex ].m_pxInstance = this;
		m_pxCallbackData[ iIndex ].m_pxComponent = pxComponent;
		m_pxCallbackData[ iIndex ].m_iIndex = iIndex;

		// add any reorder buttons...
		float fTemp = xOffset.x;

		pxDialog = new Asura_Function_Dialog( ( pxComponent->m_bExpanded ) ? "-" : "+", xOffset, _OnExpandCollapse, (int)&m_pxCallbackData[ iIndex ] );
		pxOverlay->AddDialog( pxDialog );
		xOffset.x += 4.0f;

		pxDialog = new Asura_StringDisplay_Dialog( pxComponent->GetTypeDesc(), xOffset ); 
		pxOverlay->AddDialog( pxDialog );
		xOffset.x += 16.0f;

		pxDialog = new Asura_Function_Dialog( "Del", xOffset, _OnDelete, (int)&m_pxCallbackData[ iIndex ] );
		pxOverlay->AddDialog( pxDialog );
		xOffset.x += 5.0f;

		pxDialog = new Asura_Function_Dialog( "Up", xOffset, _OnMoveUp, (int)&m_pxCallbackData[ iIndex ] );
		pxDialog->SetEnabled( iIndex > 0 ); 
		pxOverlay->AddDialog( pxDialog );
		xOffset.x += 5.0f;

		pxDialog = new Asura_Function_Dialog( "Down", xOffset, _OnMoveDown, (int)&m_pxCallbackData[ iIndex ] );
		pxDialog->SetEnabled( iIndex < ( m_iNumComponents - 1 ) ); 
		pxOverlay->AddDialog( pxDialog );
		xOffset.x += 5.0f;

		xOffset.x = fTemp;
		xOffset.y += Asura_Dialog::LargeSpacing();

		// add a label

		if ( pxComponent->m_bExpanded )
		{
			xOffset.x += 4.0f;
			AddInterfaceForComponent( pxComponent, pxOverlay, xOffset );
			xOffset.x -= 4.0f;
		}

		iIndex++;
	}

	if ( m_iNumComponents == 0 )
	{
		pxDialog = new Asura_StringDisplay_Dialog( "<No Components>", xOffset ); 
		pxOverlay->AddDialog( pxDialog );
		xOffset.y += Asura_Dialog::LargeSpacing();
	}

	// close button...

	if ( m_bReadOnly )
	{
		pxDialog = new Asura_Function_Dialog( "Close (No Save)", xOffset, _OnCloseAndDiscard, (int)this );
		pxOverlay->AddDialog( pxDialog );
	}
	else
	{
		pxDialog = new Asura_Function_Dialog( "Save and Close", xOffset, _OnCloseAndSave, (int)this );
		pxOverlay->AddDialog( pxDialog );
		xOffset.x += 16.0f;
		pxDialog = new Asura_Function_Dialog( "Discard Changes", xOffset, _OnCloseAndDiscard, (int)this );
		pxOverlay->AddDialog( pxDialog );
		xOffset.x -= 16.0f;
	}
	xOffset.y += Asura_Dialog::DefaultSpacing();

	// submit the overlay
	Asura_Overlay_System::SubmitNewOverlay( pxOverlay, false );	
}


/*
	Close the overlay
*/
void Tools_Mode_FSFX_Template::CloseOverlay()
{
	// if it exists already, shut it down
	if ( Asura_Overlay_System::DoesOverlayExist( TOOLS_OVERLAY_FSFX_TEMPLATE_EDIT ) )
	{
		Asura_Overlay_System::CloseOverlays( TOOLS_OVERLAY_FSFX_TEMPLATE_EDIT );
	}

	// if we have callback data delete it
	if ( m_pxCallbackData )
	{
		delete [] m_pxCallbackData;
	}

}


/*
	Rebuild the overlay
*/
void Tools_Mode_FSFX_Template::InvalidateOverlay()
{
	
	// if the template has been renamed then rename it here
	if ( strcmp( m_pxOldTemplate->GetName(), m_pxTemplate->GetName() ) != 0 )
	{
		m_pxTemplate->SetName( m_pxOldTemplate->GetName() );
	}

	InitialiseOverlay();
}


///////////////////////////////////////////////////////////////////////////////////////
// Component interfaces
///////////////////////////////////////////////////////////////////////////////////////


/*
	Add an entry here for each component
	type
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponent( Asura_FSFX_Component* const pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{

	// platform support

	const float tempX = xOffset.x;
	for ( int i = 0; i < Asura_FSFX_Component::NUM_PLATFORMS; i++ )
	{
		// space every 3 platforms
		if ( ( i > 0 ) && ( ( i % 3 ) == 0 ) )
		{
			xOffset.x = tempX;
			xOffset.y += Asura_Dialog::DefaultSpacing();
		}

		Asura_Dialog* pxDialog = new Asura_FlagTickbox_Dialog( Asura_FSFX_Component::GetPlatformName( i ), xOffset, &pxComponent->m_iPlatformsActive, 1 << i );
		pxDialog->SetEnabled( ( pxComponent->GetPlatformsSupported() & ( 1 << i ) ) != 0 );
		pxOverlay->AddDialog( pxDialog );
		xOffset.x += 8.0f;
	}
	xOffset.x = tempX;
	xOffset.y += Asura_Dialog::LargeSpacing();

	// component specific interface

	switch ( pxComponent->GetType() )
	{
		case Asura_FSFX_Component::FSFX_TEST:
		{
			AddInterfaceForComponentTest( static_cast<Asura_FSFX_Component_Test*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_BRIGHTNESS_AND_CONTRAST:
		{
			AddInterfaceForComponentBrightnessAndContrast( static_cast<Asura_FSFX_Component_BrightnessAndContrast*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_NOISE:
		{
			AddInterfaceForComponentNoise( static_cast<Asura_FSFX_Component_Noise*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_GAUSSIAN_BLUR:
		{
			AddInterfaceForComponentGaussianBlur( static_cast<Asura_FSFX_Component_GaussianBlur*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_RADIAL_BLUR:
		{
			AddInterfaceForComponentRadialBlur( static_cast<Asura_FSFX_Component_RadialBlur*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_DEPTH_OF_FIELD:
		{
			AddInterfaceForComponentDepthOfField( static_cast<Asura_FSFX_Component_DepthOfField*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_BLOOM:
		{
			AddInterfaceForComponentBloom( static_cast<Asura_FSFX_Component_Bloom*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_GAMMA:
		{
			AddInterfaceForComponentGamma( static_cast<Asura_FSFX_Component_Gamma*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_RGB_GAMMA:
		{
			AddInterfaceForComponentRGBGamma( static_cast<Asura_FSFX_Component_RGBGamma*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_DESATURATE_AND_TINT:
		{
			AddInterfaceForComponentDesaturateAndTint( static_cast<Asura_FSFX_Component_DesaturateAndTint*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_SM30_BLOOM:
		{
			AddInterfaceForComponentSM30Bloom( static_cast<Asura_FSFX_Component_SM30_Bloom*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_COLOUR_MAP:
		{
			AddInterfaceForComponentColourMap( static_cast<Asura_FSFX_Component_ColourMap*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_SM30_DEPTH_OF_FIELD:
		{
			AddInterfaceForComponentSM30DepthOfField( static_cast<Asura_FSFX_Component_SM30_DepthOfField*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		case Asura_FSFX_Component::FSFX_SM30_FISHEYE:
			{
				AddInterfaceForComponentSM30FishEye( static_cast<Asura_FSFX_Component_SM30_FishEye*>(pxComponent), pxOverlay, xOffset );
				break;
			}
		case Asura_FSFX_Component::FSFX_SM30_DOUBLEVISION:
			{
				AddInterfaceForComponentSM30DoubleVision( static_cast<Asura_FSFX_Component_SM30_DoubleVision*>(pxComponent), pxOverlay, xOffset );
				break;
			}
		case Asura_FSFX_Component::FSFX_SM30_MOTION_BLUR:
		{
			AddInterfaceForComponentSM30MotionBlur( static_cast<Asura_FSFX_Component_SM30_MotionBlur*>(pxComponent), pxOverlay, xOffset );
			break;
		}
		default:
		{
			if( !Project_AddInterfaceForComponent( pxComponent, pxOverlay, xOffset ) )
			{
				Asura_Assert( 0, "Interface not defined for this component type in Tools_Mode_FSFX_Template::AddInterfaceForComponent" );
			}
			break;
		}
	}
}


/*
	Overlay for test component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentTest( Asura_FSFX_Component_Test* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Tickbox_Dialog( "Subtractive", xOffset, &pxComponent->m_bSubtractive );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();

	AddColourOverlay( &pxComponent->m_fRed, &pxComponent->m_fGreen, &pxComponent->m_fBlue, pxOverlay, xOffset );
}


/*
	Overlay for brightness and contrast component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentBrightnessAndContrast( Asura_FSFX_Component_BrightnessAndContrast* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Brightness (-100->100)", xOffset, &pxComponent->m_fBrightness, -100.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Contrast (-100->100)", xOffset, &pxComponent->m_fContrast, -100.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();
}


/*
	Overlay for desaturate and tint component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentDesaturateAndTint( Asura_FSFX_Component_DesaturateAndTint* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Strength (0->200)", xOffset, &pxComponent->m_fStrength, 0.0f, 200.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Red (0->400)", xOffset, &pxComponent->m_fIntensityR, 0.0f, 400.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Green (0->400)", xOffset, &pxComponent->m_fIntensityG, 0.0f, 400.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Blue (0->400)", xOffset, &pxComponent->m_fIntensityB, 0.0f, 400.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();
}


/*
	Overlay for noise component
*/
void Tools_Mode_FSFX_Template::ComponentNoiseChooseTexture( int iUserData )
{
	Asura_FSFX_Component_Noise* pxComponent = reinterpret_cast< Asura_FSFX_Component_Noise* >( iUserData );
	
	const int iNewTexture = Tools_PickTexture::PickTextureFromDisk();

	pxComponent->m_iTextureID = iNewTexture;

	if ( iNewTexture != ASURA_TEXTURE_NONE )
	{
		const Asura_String *pxTextureName = Asura_Texture_Management::GetTextureName( iNewTexture );
		pxComponent->m_xTextureFilename = *pxTextureName;
		pxComponent->m_uTextureHash = Asura_GetHashID_IgnoreExtension( pxComponent->m_xTextureFilename.GetString() );
	}
	else
	{
		pxComponent->m_xTextureFilename = "";
		pxComponent->m_uTextureHash =  ASURA_HASH_ID_UNSET;
	}

	char szStr[ 256 ];
	sprintf( szStr, "Choose Texture : %s", pxComponent->m_xTextureFilename.GetString() );
	s_pxChooseTextureDialog->UpdateLabel( szStr );

}


void Tools_Mode_FSFX_Template::AddInterfaceForComponentNoise( Asura_FSFX_Component_Noise* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Noise (0->100)", xOffset, &pxComponent->m_fAmount, 0.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Tile X (1->512)", xOffset, &pxComponent->m_uTextureTileX, 1, 512, 1, "%d" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Tile Y (1->512)", xOffset, &pxComponent->m_uTextureTileY, 1, 512, 1, "%d" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	char szStr[ 256 ];
	sprintf( szStr, "Choose Texture : %s", pxComponent->m_xTextureFilename.GetString() );
	
	pxDialog = new Asura_Function_Dialog( szStr, xOffset, ComponentNoiseChooseTexture, reinterpret_cast< int32>( pxComponent ) );
	pxOverlay->AddDialog( pxDialog );
	s_pxChooseTextureDialog = pxDialog;

	xOffset.y += Asura_Dialog::LargeSpacing();
}


/*
	Overlay for gaussian blur component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentGaussianBlur( Asura_FSFX_Component_GaussianBlur* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Size (1->16)", xOffset, &pxComponent->m_fSize, 1.0f, 16.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 25.0f;	
	pxDialog = new Asura_Numerical_Dialog( "Strength (0->100)", xOffset, &pxComponent->m_fStrength, 0.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;	
	xOffset.y += Asura_Dialog::LargeSpacing();
}



/*
	Overlay for radial blur component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentRadialBlur( Asura_FSFX_Component_RadialBlur* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Size (1->16)", xOffset, &pxComponent->m_fSize, 1.0f, 16.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 25.0f;	
	pxDialog = new Asura_Numerical_Dialog( "Strength (0->100)", xOffset, &pxComponent->m_fStrength, 0.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;	
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
#if 0
	pxDialog = new Asura_AngleNumerical_Dialog( "Angle (0->360)", xOffset, &pxComponent->m_fAngle, 0.0f, 360.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();
#endif
	
	pxDialog = new Asura_Numerical_Dialog( "CentreX (-100->100)", xOffset, &pxComponent->m_fCentreX, -100.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 25.0f;
	pxDialog = new Asura_Numerical_Dialog( "CentreY (-100->100)", xOffset, &pxComponent->m_fCentreY, -100.0f, 100.0f, 1.01f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;
	xOffset.y += Asura_Dialog::LargeSpacing();
}


/*
	Overlay for depth of field component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentDepthOfField( Asura_FSFX_Component_DepthOfField* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Size (1->16)", xOffset, &pxComponent->m_fSize, 1.0f, 16.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 25.0f;	
	pxDialog = new Asura_Numerical_Dialog( "Strength (0->100)", xOffset, &pxComponent->m_fStrength, 0.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;	
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
	pxDialog = new Asura_Numerical_Dialog( "Near Blur Z (0->1000)", xOffset, &pxComponent->m_fNearBlurZ, 0.0f, 1000.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
	pxDialog = new Asura_Numerical_Dialog( "Far Blur Z (0->1000)", xOffset, &pxComponent->m_fFarBlurZ, 0.0f, 1000.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	
	xOffset.y += Asura_Dialog::LargeSpacing();
}


/*
	Overlay for bloom component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentBloom( Asura_FSFX_Component_Bloom* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Threshhold (0->100)", xOffset, &pxComponent->m_fThreshold, 0.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Red (0->100)", xOffset, &pxComponent->m_fIntensityR, 0.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
	pxDialog = new Asura_Numerical_Dialog( "Green (0->100)", xOffset, &pxComponent->m_fIntensityG, 0.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
	pxDialog = new Asura_Numerical_Dialog( "Blue (0->100)", xOffset, &pxComponent->m_fIntensityB, 0.0f, 100.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();
}


/*
	Overlay for gamma component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentGamma( Asura_FSFX_Component_Gamma* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Amount (0.1->5)", xOffset, &pxComponent->m_fAmount, 0.1f, 5.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();
}


/*
	Overlay for RGB gamma component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentRGBGamma( Asura_FSFX_Component_RGBGamma* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Red (0.1->5)", xOffset, &pxComponent->m_fAmountR, 0.1f, 5.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Green (0.1->5)", xOffset, &pxComponent->m_fAmountG, 0.1f, 5.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
	pxDialog = new Asura_Numerical_Dialog( "Blue (0.1->5)", xOffset, &pxComponent->m_fAmountB, 0.1f, 5.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();
}


void Tools_Mode_FSFX_Template::AddInterfaceForComponentSM30Bloom( Asura_FSFX_Component_SM30_Bloom* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Dialog("Bloom Threshold (Input)",xOffset);
	xOffset.y += Asura_Dialog::DefaultSpacing();
	pxOverlay->AddDialog( pxDialog );

	pxDialog = new Asura_Numerical_Dialog( "R", xOffset, &pxComponent->m_fRBloomThreshold, 0.0f, 1.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 10.0f;

	pxDialog = new Asura_Numerical_Dialog( "G", xOffset, &pxComponent->m_fGBloomThreshold, 0.0f, 1.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 10.0f;

	pxDialog = new Asura_Numerical_Dialog( "B", xOffset, &pxComponent->m_fBBloomThreshold, 0.0f, 1.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 20.0f;
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Saturation", xOffset, &pxComponent->m_fSaturation, 0.0f, 1.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Input Scale", xOffset, &pxComponent->m_fInputScale, 0.0f, 8.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Blur Radius", xOffset, &pxComponent->m_fBlurRadius, 0.0f, 3.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Blur Passes (lower is faster!)", xOffset, &pxComponent->m_iBlurPasses, 1, 4, 1, "%d" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Show Blur Buffer (for debugging)", xOffset, &pxComponent->m_bShowBlurBuffer);
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();


	pxDialog = new Asura_Dialog("Glow Colour (Output)",xOffset);
	xOffset.y += Asura_Dialog::DefaultSpacing();
	pxOverlay->AddDialog( pxDialog );

	pxDialog = new Asura_Numerical_Dialog( "R", xOffset, &pxComponent->m_fROutputCol, 0.0f, 1.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 10.0f;

	pxDialog = new Asura_Numerical_Dialog( "G", xOffset, &pxComponent->m_fGOutputCol, 0.0f, 1.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 10.0f;

	pxDialog = new Asura_Numerical_Dialog( "B", xOffset, &pxComponent->m_fBOutputCol, 0.0f, 1.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 20.0f;
	xOffset.y += Asura_Dialog::LargeSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Accumulate", xOffset, &pxComponent->m_bAccumulate);
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 15.0f;

	pxDialog = new Asura_Numerical_Dialog( "Accum Fade Rate", xOffset, &pxComponent->m_fAccumFade, 0.0f, 1.0f, 0.01f, "%3.2f" );	
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	xOffset.x -= 15.0f;

}


/*
	Overlay for colour map component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentColourMap( Asura_FSFX_Component_ColourMap* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_TexturePicker_Dialog( "Colour map", xOffset,
		&pxComponent->m_iColourMapIndex, NULL, &pxComponent->m_xColourMapName, 64.0f, 48.0f );

	pxDialog->SetHelpText( "Picks the colour map. This should be 1 texel high." );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += 6.0f;
}



/*
Overlay for SM3.0 DOF component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentSM30DepthOfField( Asura_FSFX_Component_SM30_DepthOfField* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Dialog("Bloom Threshold (Input)",xOffset);
	xOffset.y += Asura_Dialog::DefaultSpacing();
	pxOverlay->AddDialog( pxDialog );

	pxDialog = new Asura_Numerical_Dialog( "Near Out-of-focus Dist", xOffset, &pxComponent->m_afDistances[0], 0.0f, 1000.0f, 0.1f, "%4.1f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 25.0f;

	pxDialog = new Asura_Numerical_Dialog( "Near In-focus Dist", xOffset, &pxComponent->m_afDistances[1], 0.0f, 1000.0f, 0.1f, "%4.1f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Far In-focus Dist", xOffset, &pxComponent->m_afDistances[2], 0.0f, 1000.0f, 0.1f, "%4.1f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 25.0f;

	pxDialog = new Asura_Numerical_Dialog( "Far Out-of-focus Dist", xOffset, &pxComponent->m_afDistances[3], 0.0f, 1000.0f, 0.1f, "%4.1f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;
	xOffset.y += Asura_Dialog::LargeSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Blur Radius", xOffset, &pxComponent->m_fBlurRadius, 0.0f, 3.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Blur Passes (lower is faster!)", xOffset, &pxComponent->m_iBlurPasses, 1, 4, 1, "%d" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Blur Desaturation", xOffset, &pxComponent->m_fBlurDesaturate, 0.0f, 1.0f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Near blur 'bleed' scale", xOffset, &pxComponent->m_fBleedScale, 0.0f, 1.8f, 0.01f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Show Blur Buffer (for debugging)", xOffset, &pxComponent->m_bShowBlurBuffer);
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();


}

/*
Overlay for SM3.0 DOF component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentSM30MotionBlur( Asura_FSFX_Component_SM30_MotionBlur* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_FSFX_Component_SM30_MotionBlur* const pxMBComponent = static_cast< Asura_FSFX_Component_SM30_MotionBlur* >( pxComponent );

	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Numerical_Dialog( "Blur amount (0->1)", xOffset, &pxMBComponent->m_fBlurAmount, 0.0f, 1.0f, 0.1f, "%0.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	//pxDialog = new Asura_Numerical_Dialog( "Ignore movement blur (0->1)", xOffset, &pxMBComponent->m_fIgnoreMovementBlur, 0.0f, 1.0f, 0.1f, "%0.2f" );
	//pxOverlay->AddDialog( pxDialog );
	//xOffset.y += Asura_Dialog::DefaultSpacing();
}

/*
Overlay for SM3.0 FishEye component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentSM30FishEye( Asura_FSFX_Component_SM30_FishEye* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	static const char * FishEyeModes[] = 
	{
		"Gnomonical",
		"Linear",
		"EqualArea",
		"Stereographic"
	};


	pxDialog = new Asura_List_Dialog(xOffset, FishEyeModes, &pxComponent->m_eType, 2, 4, NULL);
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing() * 2.0f;

	pxDialog = new Asura_Numerical_Dialog( "X Scale", xOffset, &pxComponent->m_fXScale, 0.0f, 5.0f, 0.1f, "%4.1f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 25.0f;

	pxDialog = new Asura_Numerical_Dialog( "Y Scale", xOffset, &pxComponent->m_fYScale, 0.0f, 5.0f, 0.1f, "%4.1f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_AngleNumerical_Dialog( "FOV", xOffset, &pxComponent->m_fFov, 0.0f, 180.0f, 0.1f, "%4.1f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 25.0f;

	pxDialog = new Asura_Numerical_Dialog( "fMultiplier", xOffset, &pxComponent->m_fMultiplier, 0.0f, 5.0f, 0.1f, "%4.1f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_FlagTickbox_Dialog( "Dynamic (Sine)", xOffset, &pxComponent->m_uFlags, 1 );
	pxDialog->SetHelpText( "FishEye multiplier changes over time based on a sine wave." );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::SmallSpacing();

	xOffset.x += 5.0f;
	pxDialog = new Asura_AngleNumerical_Dialog( "Min Scale", xOffset, &pxComponent->m_fMinMultiplier, 0.0f, 10.0f, 0.1f, "%2.2f" );
	pxDialog->SetHelpText( "Minimum multiplier for dynamic fisheye effects." );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 25.0f;

	pxDialog = new Asura_Numerical_Dialog( "Max Scale", xOffset, &pxComponent->m_fMaxMultiplier, 0.0f, 10.0f, 0.1f, "%2.2f" );
	pxDialog->SetHelpText( "Maximum multiplier for dynamic fisheye effects." );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 25.0f;
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Speed", xOffset, &pxComponent->m_fSpeed, 0.0f, 100.0f, 0.1f, "%2.2f" );
	pxDialog->SetHelpText( "Speed of dynamic effects." );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 25.0f;

	pxDialog = new Asura_Numerical_Dialog( "Sine clip", xOffset, &pxComponent->m_fSineClip, 0.0f, 1.0f, 0.1f, "%2.2f" );
	pxDialog->SetHelpText( "Clipping value for sine wave - used to create a rhythmic beating effect - set to 0 for no effect." );
	pxOverlay->AddDialog( pxDialog );

	xOffset.x -= 5.0f;
	xOffset.y += Asura_Dialog::LargeSpacing();

}

/*
Overlay for SM3.0 DoubleVision component
*/
void Tools_Mode_FSFX_Template::AddInterfaceForComponentSM30DoubleVision( Asura_FSFX_Component_SM30_DoubleVision* pxComponent, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	Asura_Dialog* pxDialog;

	const float fXMargin = xOffset.x;

	pxDialog = new Asura_Numerical_Dialog( "X Offset 1", xOffset, &pxComponent->m_fOrigXOffset1, -10.0f, 10.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );	
	xOffset.x += 20.0f;
	pxDialog = new Asura_Numerical_Dialog( "X Offset 2", xOffset, &pxComponent->m_fOrigXOffset2, -10.0f, 10.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );	
	//xOffset.x += 20.0f;

	xOffset.x = fXMargin;
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Y Offset 1", xOffset, &pxComponent->m_fOrigYOffset1, -10.0f, 10.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 20.0f;
	pxDialog = new Asura_Numerical_Dialog( "Y Offset 2", xOffset, &pxComponent->m_fOrigYOffset2, -10.0f, 10.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	//xOffset.x += 20.0f;

	xOffset.x = fXMargin;
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_Numerical_Dialog( "X Scale 1", xOffset, &pxComponent->m_fOrigXScale1, -10.0f, 10.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 20.0f;
	pxDialog = new Asura_Numerical_Dialog( "X Scale 2", xOffset, &pxComponent->m_fOrigXScale2, -10.0f, 10.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	//xOffset.x += 20.0f;

	xOffset.x = fXMargin;
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Y Scale 1", xOffset, &pxComponent->m_fOrigYScale1, -10.0f, 10.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 20.0f;
	pxDialog = new Asura_Numerical_Dialog( "Y Scale 2", xOffset, &pxComponent->m_fOrigYScale2, -10.0f, 10.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	//xOffset.x += 20.0f;

	xOffset.x = fXMargin;
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Speed 1", xOffset, &pxComponent->m_fSpeed1, 0.0f, 100.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 20.0f;
	pxDialog = new Asura_Numerical_Dialog( "Speed 2", xOffset, &pxComponent->m_fSpeed2, 0.0f, 100.0f, 0.1f, "%3.2f" );
	pxOverlay->AddDialog( pxDialog );
	//xOffset.x += 20.0f;

	xOffset.x = fXMargin;
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Phase 1", xOffset, &pxComponent->m_fPhase1, -4.0f, 4.0f, 0.01f, "%1.3f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 20.0f;
	pxDialog = new Asura_Numerical_Dialog( "Phase 2", xOffset, &pxComponent->m_fPhase2, -4.0f, 4.0f, 0.01f, "%1.3f" );
	pxOverlay->AddDialog( pxDialog );
	//xOffset.x += 20.0f;

	xOffset.x = fXMargin;
	xOffset.y += Asura_Dialog::LargeSpacing();
}

///////////////////////////////////////////////////////////////////////////////////////
// Editor Widgets
///////////////////////////////////////////////////////////////////////////////////////


/*
	Adds a colour overlay with the given R G and B
	pointers
*/
void Tools_Mode_FSFX_Template::AddColourOverlay( float* const pfRed, float* const pfGreen, float* const pfBlue, Asura_Overlay* const pxOverlay, Asura_Vector_2& xOffset )
{
	xOffset.x += 13.0f;
	Asura_Dialog* pxDialog = new Tools_ColourPicker_Dialog( "Colour", xOffset, Asura_Vector_2( 4.0f, 3.0f ), pfRed, pfGreen, pfBlue, 255.0f, NULL );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x -= 13.0f;

	pxDialog = new Asura_Numerical_Dialog( "Red (0->255)",xOffset, pfRed, 0.0f, 255.0f,1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Green (0->255)",xOffset, pfGreen, 0.0f, 255.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Blue (0->255)",xOffset, pfBlue, 0.0f, 255.0f, 1.0f, "%0.0f" );
	pxOverlay->AddDialog( pxDialog );

	xOffset.y += Asura_Dialog::LargeSpacing();
}


///////////////////////////////////////////////////////////////////////////////////////
// Callbacks
///////////////////////////////////////////////////////////////////////////////////////


/*
	special define for this file only that takes the int
	given to the static function _func and casts it to a
	callback structure. Then takes the "this" ptr from that
	structure and calls func with the index parameter also
	from the callback structure.
*/
#define SPECIAL_CALLBACK( _name_ ) \
	void Tools_Mode_FSFX_Template::_ ## _name_( int iParam ) \
	{ \
		Tools_Mode_FSFX_Template_Callback* pxCallback = reinterpret_cast<Tools_Mode_FSFX_Template_Callback*>(iParam); \
		pxCallback->m_pxInstance->_name_( pxCallback->m_iIndex ); \
	} \


/*
	OnCloseAndDiscard does close and 
	doesn't save (so sets read only so
	changes will be discarded
*/
void Tools_Mode_FSFX_Template::OnCloseAndDiscard()
{
	if ( !m_bReadOnly )
	{
		YesNo_Overlay xYesNo( "Are you sure you want to discard changes?" );
		bool bOkay = xYesNo.DoModal();

		if ( !bOkay )
		{
			return;
		}

		m_bReadOnly = true;
	}

	Tools_Mode_FSFX::GetInstance()->CloseEditTemplateOverlay();
}


/*
	OnCloseAndSave just calls close. Read only
	will be set to false (otherwise this function
	wouldn't happen) so save will be done in the
	destructor
*/
void Tools_Mode_FSFX_Template::OnCloseAndSave()
{
	Tools_Mode_FSFX::GetInstance()->CloseEditTemplateOverlay();
}


/*
	Do a list of component types (when adding new component
	types need to add an entry here)
*/
void Tools_Mode_FSFX_Template::OnCreateComponent()
{
	
	// select type of component to add

	ListSelection_Overlay xOverlay( "Select type of component to add to this template" );
	
	// add all types here
	
	xOverlay.AddItem( Asura_FSFX_Component_Test::GetTypeDescID(), Asura_FSFX_Component_Test::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_BrightnessAndContrast::GetTypeDescID(), Asura_FSFX_Component_BrightnessAndContrast::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_Noise::GetTypeDescID(), Asura_FSFX_Component_Noise::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_GaussianBlur::GetTypeDescID(), Asura_FSFX_Component_GaussianBlur::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_RadialBlur::GetTypeDescID(), Asura_FSFX_Component_RadialBlur::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_DepthOfField::GetTypeDescID(), Asura_FSFX_Component_DepthOfField::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_Bloom::GetTypeDescID(), Asura_FSFX_Component_Bloom::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_Gamma::GetTypeDescID(), Asura_FSFX_Component_Gamma::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_RGBGamma::GetTypeDescID(), Asura_FSFX_Component_RGBGamma::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_DesaturateAndTint::GetTypeDescID(), Asura_FSFX_Component_DesaturateAndTint::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_SM30_Bloom::GetTypeDescID(), Asura_FSFX_Component_SM30_Bloom::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_ColourMap::GetTypeDescID(), Asura_FSFX_Component_ColourMap::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_SM30_DepthOfField::GetTypeDescID(), Asura_FSFX_Component_SM30_DepthOfField::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_SM30_FishEye::GetTypeDescID(), Asura_FSFX_Component_SM30_FishEye::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_SM30_DoubleVision::GetTypeDescID(), Asura_FSFX_Component_SM30_DoubleVision::GetTypeID() );
	xOverlay.AddItem( Asura_FSFX_Component_SM30_MotionBlur::GetTypeDescID(), Asura_FSFX_Component_SM30_MotionBlur::GetTypeID() );

	Project_AddComponentsToCreationList( xOverlay );
	
	// now do dialog

	bool bDone = xOverlay.DoModal();
	if ( !bDone )
	{
		return;
	}

	const int iSelectedType = xOverlay.GetSelectionData();

	// create selected component

	Asura_FSFX_Component* pxComponent = Asura_FSFX_Component::CreateOfType( (Asura_FSFX_Component::Type)iSelectedType );
	
	// not expanded at creation

	pxComponent->m_bExpanded = false;

	// add to list

	m_pxTemplate->AddComponent( pxComponent );
	
	// rebuild overlay
	InitialiseOverlay();
}


/*
	Sets the expand / collapse flag to it's oposite
	for the referenced component with the template
*/
SPECIAL_CALLBACK( OnExpandCollapse )
void Tools_Mode_FSFX_Template::OnExpandCollapse( const int iIndex )
{
	m_pxCallbackData[ iIndex ].m_pxComponent->m_bExpanded = !m_pxCallbackData[ iIndex ].m_pxComponent->m_bExpanded;
	
	// rebuild overlay
	InitialiseOverlay();
}


/*
	Called on deleting a component in the template.
	Checks the user is sure and then removes the component
*/
SPECIAL_CALLBACK( OnDelete )
void Tools_Mode_FSFX_Template::OnDelete( const int iIndex )
{

	// check if we are sure
	YesNo_Overlay xYesNo( "Are you sure you want to delete the selected component?" );
	bool bOkay = xYesNo.DoModal();

	if ( !bOkay )
	{
		return;
	}

	// delete the component
	m_pxTemplate->DeleteComponent( m_pxCallbackData[ iIndex ].m_pxComponent );

	// rebuild overlay
	InitialiseOverlay();
}


/*
	Called on moving up a component. For re-ordering the list
*/
SPECIAL_CALLBACK( OnMoveUp )
void Tools_Mode_FSFX_Template::OnMoveUp( const int iIndex )
{

	// swap this and iIndex-1 so check we arn't first
	Asura_Assert( iIndex > 0, "Cant move up the first index. JGP internal error" );

	m_pxTemplate->SwapComponents( m_pxCallbackData[ iIndex - 1 ].m_pxComponent, m_pxCallbackData[ iIndex ].m_pxComponent );

	// rebuild overlay
	InitialiseOverlay();
}


/*
	Called on moving down a component. For re-ordering the list
*/
SPECIAL_CALLBACK( OnMoveDown )
void Tools_Mode_FSFX_Template::OnMoveDown( const int iIndex )
{

	// swap this and iIndex+1 so check we arn't last
	Asura_Assert( iIndex < ( m_iNumComponents - 1 ), "Cant move down the last index. JGP internal error" );

	m_pxTemplate->SwapComponents( m_pxCallbackData[ iIndex ].m_pxComponent, m_pxCallbackData[ iIndex + 1 ].m_pxComponent );

	// rebuild overlay
	InitialiseOverlay();
}


#endif // ASURA_USE_FSFX
