/*************************************************************
 *
 * Description   : Tools files for the weather mode
 *
 * File Name     : Tools_Mode_Weather.cpp
 *
 * Author        : Richard May
 *
 *************************************************************/


/************/
/* Includes.*/
/************/

// main asura header
#include "Core/Asura.h"

// local header
#include "Weather/Tools_Mode_Weather.h"

// asura
#include "Camera/Asura_Camera.h"
#include "Core/Asura_Graph.h"
#include "Core/Asura_LOS.h"
#include "Core/Asura_UserInput.h"
#include "Core/Asura_Maths.h"
#include "Core/Asura_Timers.h"
#include "Core/Asura_TextureManagement.h"
#include "Debugging/Asura_Assert.h"
#include "Entity/Asura_Entity.h"
#include "Interface/Tools_ColourPicker.h"
#include "Interface/Asura_Cursor.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Graph_Dialog.h"
#include "Interface/Asura_Interface.h"
#include "Interface/Asura_Menubar_System.h"
#include "Interface/Asura_Menubar.h"
#include "Interface/Asura_Overlay_System.h"
#include "Interface/Asura_Overlay.h"
#include "Mesh/Asura_Mesh.h"
#include "Rendering/Asura_Colour.h"
#include "Rendering/Asura_Module.h"
#include "Rendering/Asura_Surface.h"
#include "Rendering/Asura_Render.h"
#include "Rendering/Asura_Viewport.h"
#include "Rendering/Asura_Text_Output.h"
#include "Rendering/Asura_Font_System.h"
#include "Rendering/Asura_Fog.h"
#ifdef ASURA_USE_WATER
#include "Rendering/Asura_Water.h"
#endif
#include "Shadows/Asura_CSM.h"
#include "SpecialFX/Asura_Glow_System.h"
#include "SpecialFX/Asura_Weather_System.h"

// tools
#include "Tools_Overlays.h"
#include "Entity/Tools_Entity_Data.h"
#include "Load&Save/Tools_ModeDataFile.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Misc/Tools_Timed_Messages.h"
//#include "Misc/Tools_Help.h"
#include "Misc/Tools_Render.h"
#include "Misc/Tools_Render_Options.h"
#include "Misc/Tools_Modal_Overlay.h"
#include "Misc/Tools_Dialog.h"
#include "Objects/Tools_Object_System.h"
#include "Objects/Tools_Object.h"
#include "PC/FileSystem/Tools_FileSystem.h"
#ifdef ASURA_USE_PSP_BLUR
#include "PSP/Tools_PSP_Blur.h"
#endif
#ifdef ASURA_USE_PSP_FILTER
#include "PSP/Tools_PSP_Filter.h"
#endif
#include "Texturing/Tools_PickTexture.h"
#ifdef ASURA_USE_WATER
#include "Weather/Tools_WaterTemplate.h"
#include "ChunkSystem/Asura_Chunk_Water.h"
#include "Rendering/Asura_PlatformRenderWater.h"
#include "Rendering/Asura_Direct3D_Caps.h"
#endif

/***********/
/* Globals.*/
/***********/

//////////////////
// Help Strings //
//////////////////
//static const char* Weather_ModeHelpStrings[] =
//{
//  NULL
//};

/////////////////////////////
// Static member variables //
/////////////////////////////
Asura_Vector_2  Tools_Mode_Weather::s_xWeatherOverlayPosition = Asura_Vector_2(3.0f,28.0f);
bool            Tools_Mode_Weather::s_bWeatherOverlayOpen = true;
Asura_Handle    Tools_Mode_Weather::s_iMenuHandle;

Tools_Mode_Weather* Tools_Mode_Weather::s_pxThis = NULL;

TOOLS_WEATHER_SUBMODES  Tools_Mode_Weather::s_eSubMode  = TOOLS_WEATHER_SUBMODE_NONE;
Asura_Graph<float>* Tools_Mode_Weather::s_pxFogDensityGraph = NULL;
bool Tools_Mode_Weather::s_bSunGlareEnabled;
bool Tools_Mode_Weather::s_bLensFlareEnabled;
bool Tools_Mode_Weather::s_bHorizonGlareEnabled;
bool Tools_Mode_Weather::s_bHideSunGlareIcon = false;
bool Tools_Mode_Weather::s_bFogEnabled;
bool Tools_Mode_Weather::s_bGraphFogEnabled;
float Tools_Mode_Weather::s_fSkyboxFogBlend;
float Tools_Mode_Weather::s_fFogNearPlane;
float Tools_Mode_Weather::s_fFogFarPlane;
float Tools_Mode_Weather::s_fFogValueAtFarPlane;
float Tools_Mode_Weather::s_fFogRed;
float Tools_Mode_Weather::s_fFogGreen;
float Tools_Mode_Weather::s_fFogBlue;
float Tools_Mode_Weather::s_fGlowRed;
float Tools_Mode_Weather::s_fGlowGreen;
float Tools_Mode_Weather::s_fGlowBlue;
float Tools_Mode_Weather::s_fGlowLevel;
bool Tools_Mode_Weather::s_bChangedMinFog = false;
bool Tools_Mode_Weather::s_bChangedMaxFog = false;
Asura_Tabs_Dialog* Tools_Mode_Weather::s_pxTabsDialog = NULL;

static const float fMIN_VALUE_FOR_FOG_AT_FAR_PLANE = 5.0f;

bool            Tools_Mode_Weather::s_bWaterOverlayOpen = true;
Asura_Vector_2  Tools_Mode_Weather::s_xWaterOverlayPosition = Asura_Vector_2(23.0f,3.0f);

#ifdef ASURA_USE_WATER
bool			Tools_Mode_Weather::s_bWaterModified = false;
bool			Tools_Mode_Weather::s_bWaterPreview = false;
#endif //ASURA_USE_WATER

#ifdef ASURA_USE_CSM
Tools_CSMDirector_Object* Tools_Mode_Weather::s_pxCSMDirector = NULL;
#endif

/***********/
/* Classes */
/***********/

class Tools_CSMDirector_Object : public Tools_Object
{
public:

	Tools_CSMDirector_Object( const int iType = TOT_Anon )
		: Tools_Object( iType )
	{
		SetMesh( "ToolsShape_Arrow" );
	}

	virtual const char* GetName() { return "CSM Director"; }
	virtual const char* GetTypeDescription() { return GetName(); }
};

bool Tools_Mode_Weather::s_bMadeChanges;
bool Tools_Mode_Weather::s_bChangedFogOverlay = false;

/**************/
/* Functions. */
/**************/

/*************************************************************
 *
 * Name          : Tools_Mode_Weather::Initialise
 *
 * Author        : Richard May
 *
 * Description   : Init and setup the NPC mode & overlays/text etc.
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::InitialiseMode ( void )
{
    // Create the menubar
    s_iMenuHandle = Asura_Menubar_System::CreateMenuSection();
    Asura_Menubar_Title* title = Asura_Menubar_System::AddTitle(s_iMenuHandle,"Overlays");

    title->AddItem("Weather", ToggleWeatherOverlay, WeatherOverlayIsOn );
	#ifdef ASURA_USE_WATER
    title->AddItem("Water", ToggleWaterOverlay, WaterOverlayIsOn );
	#endif

    // Load values from .dat file
    TransferModeData( TOOLSMODEDATAFILE_LOAD );

    // No sub mode at the moment
    s_eSubMode  = TOOLS_WEATHER_SUBMODE_NONE;

    // intialise sun glare etc.
	s_bSunGlareEnabled = Asura_Weather_System::IsSunGlareEnabled();
	s_bLensFlareEnabled = Asura_Weather_System::IsLensFlareEnabled();
	s_bHorizonGlareEnabled = Asura_Weather_System::IsHorizonGlareEnabled();

    // fill in the values from Asura_Fog
	s_bFogEnabled = Asura_Fog::IsFogEnabled();
	// express skybox/fog blend as percentage
	s_fSkyboxFogBlend = Asura_Fog::GetInitialSkyboxFogBlendFactor()*100.0f;
	s_fFogNearPlane = Asura_Fog::GetInitialFogNearPlane();
	s_fFogFarPlane = Asura_Fog::GetInitialFogFarPlane();
    s_fFogValueAtFarPlane = Asura_Maths::Max( fMIN_VALUE_FOR_FOG_AT_FAR_PLANE, Asura_Fog::GetInitialFogValueAtFarPlane() * 100.0f );

	// artist friendly colours go 0 to 255
	Asura_RGBA xColour = Asura_Fog::GetInitialFogColour() * 255.0f; 

	s_fFogRed = xColour.m_fR;
	s_fFogGreen = xColour.m_fG;
	s_fFogBlue = xColour.m_fB;

	s_bGraphFogEnabled = Asura_Fog::IsGraphFogEnabled();

	xColour = Asura_Glow_System::GetGlowTint() * 255.0f;
	s_fGlowRed = xColour.m_fR;
	s_fGlowGreen = xColour.m_fG;
	s_fGlowBlue = xColour.m_fB;

	s_fGlowLevel = Asura_Glow_System::GetGlowLevel();

	s_pxFogDensityGraph = new Asura_Graph<float>(2, 0.0f, Asura_Fog::GetInitialFogValueAtFarPlane());
	Asura_Vector_2 xGraphPoint = Asura_Fog::GetGraphFogPoint();
	s_pxFogDensityGraph->AddPoint(xGraphPoint.y, xGraphPoint.x);

    // Create overlays - ensure all data referenced by overlay creation is done already!
    CreateWeatherOverlay();
	#ifdef ASURA_USE_WATER
	CreateWaterOverlay();
	#endif

    Tools_Object_System::EnableAllControls(true);

    s_bMadeChanges = false;

//  // Add help
//  Tools_Help::AddHelpTopic("Weather Mode",Weather_ModeHelpStrings);

    Asura_Fog::SetToDefaultsIfNecessary();

	Tools_Render_Options::SetModeEnableSunGlare(true);

	#ifdef ASURA_USE_CSM
	s_pxCSMDirector = new Tools_CSMDirector_Object;
	if( s_pxCSMDirector )
	{
		s_pxCSMDirector->Position = *Asura_Camera::GetPosition();

		const Asura_Vector_3& xDir = Asura_CSM::GetShadowDir();
		Asura_Maths::OrientationFromDirection( s_pxCSMDirector->Orientation, xDir );
	}
	#endif
}
/* end of function Initialise */    



/*************************************************************
 *
 * Name          : Tools_Mode_Weather::Shutdown
 *
 * Author        : Richard May
 *
 * Description   : Shutdown tools mode gracefully
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::ShutdownMode ( void )
{
	#ifdef ASURA_USE_CSM
	// Object will be deleted by DeleteAllModeSpecific() call below
	s_pxCSMDirector = NULL;
	#endif

    // Exit the sub mode
    ExitMode();

//  // Remove the NPC help text
//  Tools_Help::RemoveHelpTopic("Weather Mode");

    // Delete all the objects
    Tools_Object_System::DeleteAllModeSpecific();

    // Save values to .dat file
    TransferModeData(TOOLSMODEDATAFILE_SAVE);
    
    // Shutdown the menu
    if(s_iMenuHandle != ASURA_INVALID_HANDLE)
    {
        Asura_Menubar_System::DestroyMenuSection(s_iMenuHandle);
        s_iMenuHandle = ASURA_INVALID_HANDLE;
    }

    // Close overlays
    Asura_Overlay_System::CloseOverlays( TOOLS_OVERLAY_WEATHER );
    Asura_Overlay_System::CloseOverlays( TOOLS_OVERLAY_WATER );

    Tools_Object_System::EnableAllControls(false);

	delete s_pxFogDensityGraph;
	s_pxFogDensityGraph = NULL;
	
	Tools_Render_Options::SetModeEnableSunGlare(false);
	    
}
/* end of function Shutdown */


/*************************************************************
 *
 * Name          : Tools_Mode_Weather::TransferModeData
 *
 * Author        : Richard May
 *
 * Description   : 
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::TransferModeData( int mode )
{
    // Open the file
    Tools_ModeDataFile file("WeatherMode.dat",mode);

    // Transfer the data
    // (none of these should be removed , and new data should go on the end, otherwise
    // the files will get screwed up)
    file.Transfer(s_xWeatherOverlayPosition);
    file.Transfer(s_bWeatherOverlayOpen);
    file.Transfer(s_xWaterOverlayPosition);
    file.Transfer(s_bWaterOverlayOpen);
}
/* end of function TransferModeData */


/*************************************************************
 *
 * Name          : Tools_Mode_Weather::Update
 *
 * Author        : Richard May
 *
 * Description   : Standrad update function (handles input)
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::Update( void )
{
// Act upon keyboard input
    HandleKeyboard();

    Asura_Weather_System::SetSunGlareEnabled( s_bSunGlareEnabled );
	Asura_Weather_System::SetLensFlareEnabled( s_bLensFlareEnabled );

	if (s_bChangedFogOverlay)
	{
		s_bChangedFogOverlay = false;
		ToggleWeatherOverlay();
		ToggleWeatherOverlay();
		s_bMadeChanges = true;
	}
	if(s_bChangedMinFog)
	{
		if(s_fFogFarPlane<s_fFogNearPlane) s_fFogFarPlane = s_fFogNearPlane;

		s_bChangedMinFog = false;
		s_bMadeChanges = true;
	}
	if(s_bChangedMaxFog)
	{
		if(s_fFogFarPlane<s_fFogNearPlane) s_fFogNearPlane = s_fFogFarPlane;

		s_bChangedMaxFog = false;
		s_bMadeChanges = true;
	}

    if(s_bMadeChanges)
    {
		bool bHorizonGlareChanged = Asura_Weather_System::IsHorizonGlareEnabled() != s_bHorizonGlareEnabled;
		if (bHorizonGlareChanged)
		{
			Asura_Weather_System::SetHorizonGlareEnabled( s_bHorizonGlareEnabled );
			// recreate overlay with extra options.
			ToggleWeatherOverlay();
			ToggleWeatherOverlay();
		}

		if (1)
		{
			// (AW - 20.08.2004) - Nasty hack to stop user from moving the first graph point.
			s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_xValue = 0.0f;
			// Nasty hack to stop user adding new control points.
			if (s_pxFogDensityGraph->GetNumberOfSplinePoints() > 5)
			{
				while (s_pxFogDensityGraph->GetNumberOfSplinePoints() > 4)
				{
					s_pxFogDensityGraph->RemovePoint(s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext);
				}
			}
			// Nasty hack to stop user removing control points.
			if (s_pxFogDensityGraph->GetNumberOfSplinePoints() < 5)
			{
				Asura_Vector_2 xGraphPoint = Asura_Fog::GetGraphFogPoint();
				s_pxFogDensityGraph->AddPoint(xGraphPoint.y, xGraphPoint.x);
			}
			// Nasty hack to stop user setting final fog value too low.
			if (s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext->m_pxNext->m_xValue < fMIN_VALUE_FOR_FOG_AT_FAR_PLANE * 0.01f)
			{	
				s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext->m_pxNext->m_xValue = fMIN_VALUE_FOR_FOG_AT_FAR_PLANE * 0.01f;
			}
		}

		// update generic fog values
		Asura_Fog::EnableFog(s_bFogEnabled);

		Asura_Fog::SetInitialSkyboxFogBlendFactor( s_fSkyboxFogBlend/100.0f );
		Asura_Fog::SetInitialFogColour( s_fFogRed/255.0f, s_fFogGreen/255.0f, s_fFogBlue/255.0f );
		Asura_Fog::SetInitialFogNearPlane( s_fFogNearPlane );
		Asura_Fog::SetInitialFogFarPlane( s_fFogFarPlane );

		if (s_bGraphFogEnabled)
		{
			Asura_Fog::SetInitialFogValueAtFarPlane( s_pxFogDensityGraph->GetValueAtTime(1.0f) );
		}
		else
		{
			Asura_Fog::SetInitialFogValueAtFarPlane( s_fFogValueAtFarPlane / 100.0f );
		}
		Asura_Fog::EnableGraphFog(s_bGraphFogEnabled);
		Asura_Vector_2 xGraphFogPoint;
		xGraphFogPoint.x = s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext->m_fTime;
		xGraphFogPoint.y = s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext->m_xValue;
		Asura_Fog::SetGraphFogPoint(xGraphFogPoint);

		// update glow values
		Asura_Glow_System::SetGlowTint(s_fGlowRed/255.0f, s_fGlowGreen/255.0f, s_fGlowBlue/255.0f);
		Asura_Glow_System::SetGlowLevel(s_fGlowLevel);

        Tools_SaveAsura::SetSkyboxModified();
        s_bMadeChanges = false;
    }

	#ifdef ASURA_USE_WATER
	if(s_bWaterModified)
	{
        Tools_SaveAsura::SetSkyboxModified();
		s_bWaterModified = false;
	}
	#endif

	#ifdef ASURA_USE_CSM
	if( s_pxCSMDirector )
	{
		const Asura_Matrix_3x3& xOriMat = s_pxCSMDirector->Orientation;
		const Asura_Vector_3 xOrient( xOriMat.e13, xOriMat.e23, xOriMat.e33 );

		if( !Asura_CSM::GetShadowDir().ApproximatelyEquals( xOrient ) )
		{
			Asura_CSM::SetShadowDir( xOrient );
			Tools_SaveAsura::SetSkyboxModified();
		}
	}
	#endif
}
/* end of function Update */


/*************************************************************
 *
 * Name          : Tools_Mode_Weather::Render
 *
 * Author        : Richard May
 *
 * Description   : Display function for NPC mode specific stuff
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::RenderWorld_PostToneMap ( void )
{
    if( Asura_Weather_System::IsSunGlareEnabled() && !s_bHideSunGlareIcon)
    {
        static int iSunIconTexture = ASURA_TEXTURE_NONE;
        if( ASURA_TEXTURE_NONE == iSunIconTexture )
        {
            // Use light bulb texture from lighting mode for now...
            bool bWasNew;
            iSunIconTexture = Asura_Texture_Management::AddTexture( "\\tools\\lightbulb.dds", &bWasNew );
            if( bWasNew )
            {
                Asura_Texture_Management::LoadTextures();
            }
        }

        extern void RenderIcon( const Asura_Vector_3& xPos, int iTexID, float fSize );
        RenderIcon( Asura_Weather_System::GetSunPos(), iSunIconTexture, 10.0f );
    }
}
/* end of function Render */

/*************************************************************
 *
 * Name          : Tools_Mode_Weather::QuickSave
 *
 * Author        : Richard May
 *
 * Description   : Obvious
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::QuickSave ( void )
{
    Tools_SaveAsura::SaveSkybox();
    if(!IsModified())
    {
        Tools_Timed_Message_System::AddMessage( 0x00ff00, "Saved weather mode successfully" );
    }
}
/* end of function QuickSave */

/*************************************************************
 *
 * Name          : Tools_Mode_Weather::IsModified
 *
 * Author        : Richard May
 *
 * Description   : 
 *
 * Parameters    : void
 *
 * Return value  : bool - true or false
 *
 *************************************************************/
bool Tools_Mode_Weather::IsModified ( void )
{
    return Tools_SaveAsura::IsSkyboxModified();
}
/* end of function IsModified */



/*************************************************************
 *
 * Name          : Tools_Mode_Weather::HandleKeyboard
 *
 * Author        : Richard May
 *
 * Description   : 
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::HandleKeyboard ( void )
{
    if(Asura_Overlay_System::OverlaysHaveKeyboardFocus()) return;

    if(Asura_UserInput::KeyPressed(ASURA_KEYID_CTRL))
    {
    }
    else if(Asura_UserInput::KeyPressed(ASURA_KEYID_SHIFT))
    {
    }
    else
    {   
        switch( s_eSubMode )
        {
            case TOOLS_WEATHER_SUBMODE_NONE:
            {       
                break;
            }

            default : 
            {
                Asura_Assert( false, "ERROR - Invalid Submode!" );
                break;
            }
        } 
    }

}
/* end of function HandleKeyboard */


/*************************************************************
 *
 * Name          : Tools_Mode_Weather::ToggleWeatherOverlay
 *
 * Author        : Richard May
 *
 * Description   : Toggles the Weather mode overlay on or off 
 *                 (If switched on it creates the overlay)
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::ToggleWeatherOverlay ( void )
{
    s_bWeatherOverlayOpen = !s_bWeatherOverlayOpen;

    if (s_bWeatherOverlayOpen)
    {
        CreateWeatherOverlay();
    }
    else
    {
        Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_WEATHER);
    }
}
/* end of function ToggleWeatherOverlay */


/*************************************************************
 *
 * Name          : Tools_Mode_Weather::WeatherOverlayIsOn
 *
 * Author        : Richard May
 *
 *************************************************************/
bool Tools_Mode_Weather::WeatherOverlayIsOn ( void )
{
    return s_bWeatherOverlayOpen;
}
/* end of function WeatherOverlayIsNo */


/*************************************************************
 *
 * Name          : Tools_Mode_Weather::CreateWeatherOverlay
 *
 * Author        : Richard May
 *
 * Description   : Creates the tools overlay for Dredd's NPC mode
 *
 * Parameters    : void
 *
 * Return value  : void
 *
 *************************************************************/
void Tools_Mode_Weather::CreateWeatherOverlay ( void )
{
    // if the Overlay isn't open, we can't create it!
    if(!s_bWeatherOverlayOpen) return;

    Asura_Overlay* pxNewOverlay;

    switch( s_eSubMode )
    {
        case TOOLS_WEATHER_SUBMODE_NONE:
        {
            pxNewOverlay = new Asura_Overlay("Weather Mode",false,&s_xWeatherOverlayPosition);
            break;
        }

        default :
        {
            Asura_Assert( false, "ERROR - Invalid Submode" );
            break;
        }   
    }
    
    Asura_Vector_2 xOffset = Asura_Vector_2(1.0f,3.0f);

// Add options to overlay
    Asura_Assert(s_pxThis,"");
    s_pxThis->AddWeatherOverlayControls(pxNewOverlay,xOffset);

    
    pxNewOverlay->m_uID = TOOLS_OVERLAY_WEATHER;

    Asura_Overlay_System::SubmitNewOverlay(pxNewOverlay,false);
}
/* end of function CreateWeatherOverlay */

void Tools_Mode_Weather::AddWeatherOverlayControls(class Asura_Overlay* pxOverlay,class Asura_Vector_2& xOffset)
{

// Add options to overlay
    switch( s_eSubMode )
    {
        case TOOLS_WEATHER_SUBMODE_NONE:
        {
            Asura_Dialog* pxDialog;

			// 
			// KJFL - 2004-03-12 11:58:07 - 'generic' fog
			//

			pxDialog = new Asura_Tickbox_Dialog( "Fog", xOffset, &s_bFogEnabled, &s_bChangedFogOverlay );
            pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			if (s_bFogEnabled)
			{
     
				//If supporting PS2 then the near fog plane needs to be at least 11 metres , otherwise it should be okay
				//to go lower. RAR 20/06/2007
     			const float s_fMinAllowedFogDistance = Tools_Level_Export::IsPlatformSupported(Tools_Level_Export::Export_PS2) ? 11.0f : 0.0f;

				pxDialog = new Asura_Numerical_Dialog( "Skybox fogging (%)", xOffset, &s_fSkyboxFogBlend, 0.0f, 100.0f, 1.0f, "%3.0f", &s_bMadeChanges );
				pxOverlay->AddDialog(pxDialog);
				// render colours to one side of previous menu items
				const float fLeftDialogsWidth = 24.0f;
				xOffset.x += fLeftDialogsWidth;

				//insert colour selection box below
				Tools_ColourPicker_Dialog* pxFogColourPickerDialog = new Tools_ColourPicker_Dialog("Fog Colour",xOffset,Asura_Vector_2(4.0f,3.0f),&s_fFogRed,&s_fFogGreen,&s_fFogBlue,255.0f,&s_bMadeChanges);
				pxFogColourPickerDialog->EnableHDR(true);
				pxFogColourPickerDialog->SetHelpText("Fog Colour");
				pxOverlay->AddDialog(pxFogColourPickerDialog);

				// move the offset back to the bottom left for the next items
				xOffset.x -= fLeftDialogsWidth;
				xOffset.y += Asura_Dialog::DefaultSpacing();

				pxDialog = new Asura_Numerical_Dialog( "Near fog plane (m)", xOffset, &s_fFogNearPlane, s_fMinAllowedFogDistance, 2000.0f, 1.0f, "%5.0f", &s_bChangedMinFog );
				pxOverlay->AddDialog(pxDialog);
				xOffset.y+=Asura_Dialog::DefaultSpacing();
            
				pxDialog = new Asura_Numerical_Dialog( "Far fog plane (m)", xOffset, &s_fFogFarPlane, s_fMinAllowedFogDistance, 10000.0f, 1.0f, "%5.0f", &s_bChangedMaxFog );
				pxOverlay->AddDialog(pxDialog);
				xOffset.y+=Asura_Dialog::DefaultSpacing();

				if (!s_bGraphFogEnabled)
				{
					pxDialog = new Asura_Numerical_Dialog( "Fog value at far plane (%)", xOffset, &s_fFogValueAtFarPlane, fMIN_VALUE_FOR_FOG_AT_FAR_PLANE, 100.0f, 1.0f, "%3.0f", &s_bMadeChanges );
					pxOverlay->AddDialog(pxDialog);
				}
				xOffset.y+=Asura_Dialog::DefaultSpacing();
				
				//
				// End of 'generic' fog
				//

				//
				// (AW - 20.08.2004) - 'Graph fog'
				//
		
				pxDialog = new Asura_Tickbox_Dialog("Graph Fog (slightly more costly)", xOffset, &s_bGraphFogEnabled, &s_bChangedFogOverlay);
				pxDialog->SetHelpText("Graph fog allows you to create a non-linear fog density graph. More complex than regular fog and so marginally slower.");
				pxOverlay->AddDialog(pxDialog);
				xOffset.y += Asura_Dialog::DefaultSpacing();

				if (s_bGraphFogEnabled)
				{
					pxDialog = new Asura_Graph_Dialog<float>("Fog density graph", xOffset, s_pxFogDensityGraph, 0.0f, 1.0f, &s_bMadeChanges);
					pxDialog->SetHelpText("This graph defines the relationship between distance and fog density. The X-Axis represents the distance range between the Near and Far fog planes. The Y-Axis represents fog density.");
					pxOverlay->AddDialog(pxDialog);
					xOffset.y = pxDialog->m_xMaxCoord.y;
				}

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

				//
				// End of 'graph' fog
				//
			}

            pxDialog = new Asura_Tickbox_Dialog( "Sun glare enabled", xOffset, &s_bSunGlareEnabled, &s_bMadeChanges );
            pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();
            xOffset.x += 3.0f;

            pxDialog = new Asura_Function_Dialog( "Move sun to camera position", xOffset, MoveSunToCamPos, &s_bMadeChanges, NULL, false );
            pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

            //add colour selection box to side
			xOffset.x += 15.0f;
			pxDialog = new Tools_ColourPicker_Dialog("Sun Colour",xOffset,Asura_Vector_2(4.0f,3.0f),&Asura_Weather_System::s_fSunColourR,&Asura_Weather_System::s_fSunColourG,&Asura_Weather_System::s_fSunColourB,1.0f,&s_bMadeChanges);
			pxDialog->SetHelpText("Sun Colour");
			pxOverlay->AddDialog(pxDialog);
			xOffset.x -= 15.0f;


            
            pxDialog = new Asura_Numerical_Dialog( "Red", xOffset, &Asura_Weather_System::s_fSunColourR, 0.0f, 1.0f, 0.01f, "%5.3f", &s_bMadeChanges );
            pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

            pxDialog = new Asura_Numerical_Dialog( "Green", xOffset, &Asura_Weather_System::s_fSunColourG, 0.0f, 1.0f, 0.01f, "%5.3f", &s_bMadeChanges );
            pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

            pxDialog = new Asura_Numerical_Dialog( "Blue", xOffset, &Asura_Weather_System::s_fSunColourB, 0.0f, 1.0f, 0.01f, "%5.3f", &s_bMadeChanges );
            pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

            pxDialog = new Asura_Tickbox_Dialog( "Lens flare enabled", xOffset, &s_bLensFlareEnabled, &s_bMadeChanges );
            pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

            pxDialog = new Asura_Tickbox_Dialog( "Horizon Glare enabled", xOffset, &s_bHorizonGlareEnabled, &s_bMadeChanges );
			pxDialog->SetHelpText( "Adds glare similar to sun glare all the way around the horizon. You can specify how far above (and below) the horizon the glare extends. The colour used is the same as for the sun glare. The glare fades from full at the bottom to none at the top. Currently only implemented on PS2" );
            pxOverlay->AddDialog( pxDialog );
			
			if (s_bHorizonGlareEnabled)
			{
				xOffset.y+=Asura_Dialog::DefaultSpacing();
				pxDialog = new Asura_Numerical_Dialog( "Horizon glare size up", xOffset, &Asura_Weather_System::s_fHorizonGlareSizeUp, 0.0f, 1.0f, 0.01f, "%5.3f", &s_bMadeChanges );
				pxDialog->SetHelpText( "Distance above the horizon the horizon glare extends to. Specified in screen coordinates so 1.0 makes it just fill the screen when the horizon is at the bottom of the screen." );
				pxOverlay->AddDialog( pxDialog );

				xOffset.y+=Asura_Dialog::DefaultSpacing();
				pxDialog = new Asura_Numerical_Dialog( "Horizon glare size down", xOffset, &Asura_Weather_System::s_fHorizonGlareSizeDown, 0.0f, 1.0f, 0.01f, "%5.3f", &s_bMadeChanges );
				pxDialog->SetHelpText( "Distance below the horizon the horizon glare extends to. Specified in screen coordinates so 1.0 makes it just fill the screen when the horizon is at the top of the screen. Typically you can't see below the horizon so this should be 0.0." );
				pxOverlay->AddDialog( pxDialog );
			}

			xOffset.y+=Asura_Dialog::DefaultSpacing();
			pxDialog = new Asura_Tickbox_Dialog("Hide Icon",xOffset,&s_bHideSunGlareIcon);
			pxDialog->SetHelpText("Hides the light bulb icon used to represent the sun position.");
            pxOverlay->AddDialog( pxDialog );

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


			//Time for some tabs. RAR 11/01/2006
			static char* s_aszTabs[] =
			{
				"Glow",
				#ifdef ASURA_USE_PSP_FILTER
				"PSP Filter",
				#endif
				#ifdef ASURA_USE_PSP_BLUR
				"PSP Blur",
				#endif
				#ifdef ASURA_USE_CSM
				"CSM",
				#endif
			};
			const int iNumTabs = sizeof(s_aszTabs)/sizeof(char*);
			int iCurrentTab = 0;

			Asura_Tabs_Dialog* pxTabsDialog = s_pxTabsDialog = new Asura_Tabs_Dialog(xOffset,s_aszTabs,iNumTabs);
			pxOverlay->AddDialog(pxTabsDialog);
			xOffset.y += Asura_Dialog::LargeSpacing();

#if defined(ASURA_USE_PSP_FILTER) || defined(ASURA_USE_CSM)
			float fTabsStartY = xOffset.y;
#endif	// defined(ASURA_USE_PSP_FILTER)
			float fTabsEndY = xOffset.y;

			pxOverlay->SetCurrentParentDialog(pxTabsDialog);


			// RJF - 15 September 2004 - Glow effect parameters

			pxTabsDialog->SelectTab(iCurrentTab++);

			pxDialog = new Asura_Numerical_Dialog( "Input red", xOffset, &s_fGlowRed, 0.0f, 255.0f, 1.0f, "%3.0f", &s_bMadeChanges);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			pxDialog = new Asura_Numerical_Dialog( "Input green", xOffset, &s_fGlowGreen, 0.0f, 255.0f, 1.0f, "%3.0f", &s_bMadeChanges);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			pxDialog = new Asura_Numerical_Dialog( "Input blue", xOffset, &s_fGlowBlue, 0.0f, 255.0f, 1.0f, "%3.0f", &s_bMadeChanges);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			pxDialog = new Asura_Numerical_Dialog( "Glow level", xOffset, &s_fGlowLevel, 0.0f, 2.0f, 0.01f, "%5.3f", &s_bMadeChanges);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;

			#ifdef ASURA_USE_PSP_FILTER
			//PSP filter tab
			pxTabsDialog->SelectTab(iCurrentTab++);
			xOffset.y = fTabsStartY;

			pxDialog = new Asura_Tickbox_Dialog("Enable",xOffset,&Tools_PSP_Filter::s_bEnabled,&s_bMadeChanges);
			pxDialog->SetHelpText("Enables the filter effect.");
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			xOffset.x = 14.0f;
			Tools_ColourPicker_Dialog* pxColourDialog = new Tools_ColourPicker_Dialog("Filter Colour",xOffset,Asura_Vector_2(4.0f,3.0f),&Tools_PSP_Filter::s_xColour.m_fR,&Tools_PSP_Filter::s_xColour.m_fG,&Tools_PSP_Filter::s_xColour.m_fB,1.0f,&s_bMadeChanges);
			pxColourDialog->EnableAlphaEditing(&Tools_PSP_Filter::s_xColour.m_fA);
			pxColourDialog->SetHelpText("Filter Colour");
			pxColourDialog->SetIsEnabledFunction(IsEnabled_PSPFilter);
			pxOverlay->AddDialog(pxColourDialog);
			xOffset.x = 1.0f;

			pxDialog = new Asura_ColourNumerical_Dialog("Red",xOffset,&Tools_PSP_Filter::s_xColour.m_fR,"%d",&s_bMadeChanges);
			pxDialog->SetHelpText("Sets the colour of the screen tint. (Or something like that).");
			pxDialog->SetIsEnabledFunction(IsEnabled_PSPFilter);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			pxDialog = new Asura_ColourNumerical_Dialog("Green",xOffset,&Tools_PSP_Filter::s_xColour.m_fG,"%d",&s_bMadeChanges);
			pxDialog->SetHelpText("Sets the colour of the screen tint. (Or something like that).");
			pxDialog->SetIsEnabledFunction(IsEnabled_PSPFilter);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			pxDialog = new Asura_ColourNumerical_Dialog("Blue",xOffset,&Tools_PSP_Filter::s_xColour.m_fB,"%d",&s_bMadeChanges);
			pxDialog->SetHelpText("Sets the colour of the screen tint. (Or something like that).");
			pxDialog->SetIsEnabledFunction(IsEnabled_PSPFilter);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			pxDialog = new Asura_ColourNumerical_Dialog("Alpha",xOffset,&Tools_PSP_Filter::s_xColour.m_fA,"%d",&s_bMadeChanges);
			pxDialog->SetHelpText("Determines how much the screen is tinted towards the chosen colour");
			pxDialog->SetIsEnabledFunction(IsEnabled_PSPFilter);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();
			

			if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;
			#endif //ASURA_USE_PSP_FILTER

			#ifdef ASURA_USE_PSP_BLUR
			//PSP blur tab
			pxTabsDialog->SelectTab(iCurrentTab++);
			xOffset.y = fTabsStartY;

			pxDialog = new Asura_Tickbox_Dialog("Enable",xOffset,&Tools_PSP_Blur::s_bEnabled,&s_bMadeChanges);
			pxDialog->SetHelpText("Enables the blur effect.");
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();

			pxDialog = new Asura_Numerical_Dialog("Brightness",xOffset,&Tools_PSP_Blur::s_fBrightness,0.0f,1.0f,0.01f,"%.2f",&s_bMadeChanges);
			pxDialog->SetHelpText("Its a brightness value and it affects the blur in some way.");
			pxDialog->SetIsEnabledFunction(IsEnabled_PSPBlur);
			pxOverlay->AddDialog( pxDialog );
			xOffset.y+=Asura_Dialog::DefaultSpacing();
			

			if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;
			#endif //ASURA_USE_PSP_BLUR

			#ifdef ASURA_USE_CSM
			//Cascaded shadow mapping tab
			pxTabsDialog->SelectTab(iCurrentTab++);
			xOffset.y = fTabsStartY;

			Asura_CSM::AddOverlayControls(pxOverlay,xOffset,s_bMadeChanges);

			if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;
			#endif //ASURA_USE_CSM

			//end of tabs
			xOffset.y = fTabsEndY + 1.0f;
			pxOverlay->SetCurrentParentDialog(0);
			pxTabsDialog->SelectTab(0);


			

            break;
        }

        default :
        {
            Asura_Assert( false, "ERROR - Invalid Submode" );
            break;
        }   
    }
}



void Tools_Mode_Weather::Undo()
{
}
void Tools_Mode_Weather::Redo()
{
}


void Tools_Mode_Weather::PrepareUndo()
{
}


/////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION     Tools_Mode_Weather::EnterSubMode
// PARAMETERS   New mode to enter
// RETURNS      None
// DESCRIPTION  
// AUTHOR       Richard M. Smith (20 August 2002)
/////////////////////////////////////////////////////////////////////////////////////////
void Tools_Mode_Weather::EnterSubMode( const TOOLS_WEATHER_SUBMODES eSubMode )
{
    if( eSubMode == s_eSubMode )
    {
    // Already in that mode!
        return;
    }

// Exit the old mode
    switch( s_eSubMode )
    {
        case TOOLS_WEATHER_SUBMODE_NONE:
        {
            break;
        }

        default :
        {
            Asura_Assert( false, "ERROR - Unrecognised submode!" );
            break;
        }
    }

    // Close the old overlay
    Asura_Overlay_System::CloseOverlays( TOOLS_OVERLAY_WEATHER );

    // But make sure that the overlay is visible!
    s_bWeatherOverlayOpen = true;
    s_eSubMode = eSubMode;

    switch( eSubMode )
    {
        case TOOLS_WEATHER_SUBMODE_NONE:
        {
        
            break;
        }

        default:
        {
            Asura_Assert(0,"Unknown mode");
            break;
        }
    }

    // Recreate the overlay for this sub mode...
    CreateWeatherOverlay();


} // End Function 'Tools_Mode_Weather::EnterSubMode'





/////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION     Tools_Mode_Weather::ExitMode
// PARAMETERS   None
// RETURNS      None
// DESCRIPTION  
// AUTHOR       Richard M. Smith (21 August 2002)
/////////////////////////////////////////////////////////////////////////////////////////
void Tools_Mode_Weather::ExitMode( void )
{
    EnterSubMode( TOOLS_WEATHER_SUBMODE_NONE );

} // End Function 'Tools_Mode_Weather::ExitMode'



void Tools_Mode_Weather::MoveSunToCamPos( void )
{
    const Asura_Vector_3* pxCamPos = Asura_Camera::GetPosition();
    Asura_Weather_System::s_xSunPos = *pxCamPos;
    Tools_Timed_Message_System::AddMessage( 0xFFFFFF, "Moved sun to (%.1f, %.1f, %.1f).", pxCamPos->x, pxCamPos->y, pxCamPos->z );
}


#ifdef ASURA_USE_WATER
void Tools_Mode_Weather::ToggleWaterOverlay()
{
    s_bWaterOverlayOpen = !s_bWaterOverlayOpen;

    if (s_bWaterOverlayOpen)
    {
        CreateWaterOverlay();
    }
    else
    {
        Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_WATER);
    }
}

bool Tools_Mode_Weather::WaterOverlayIsOn()
{
	return s_bWaterOverlayOpen;
}

void Tools_Mode_Weather::CreateWaterOverlay()
{
	if(!s_bWaterOverlayOpen) return;
	
    Asura_Water_System::Env_Water_Controls& xControl = Asura_Water_System::GetEnvController();

	Asura_Overlay* pxOverlay = new Asura_Overlay("Water",false,&s_xWaterOverlayPosition);
	
	Asura_Dialog* pxDialog;
	Asura_Vector_2 xOffset = Asura_Vector_2(1.0f,3.0f);

	//get a default controller for setting up the help text
	Asura_Water_System::Env_Water_Controls xDefaultControl;
	Asura_Water_System::SetDefaults(&xDefaultControl);

	//macro for setting up the help text with defaults
	char szHelpText[1024];
	#define SET_HELPTEXT(__text,__param)\
	{\
		Asura_PrintfToBfr(szHelpText,"%s%sDefault : %f",1024,true,__text,*__text ? "\n" : "",xDefaultControl.__param);\
		char* pcLastChar = &szHelpText[strlen(szHelpText)-1];\
		while(*pcLastChar == '0') *pcLastChar-- = 0;\
		if(*pcLastChar == '.') *pcLastChar = 0;\
		pxDialog->SetHelpText(szHelpText);\
	}

	#define SET_HELPTEXTFLAG(__text,__flag)\
	{\
		Asura_PrintfToBfr(szHelpText,"%s%sDefault : %s",1024,true,__text,*__text ? "\n" : "",(xDefaultControl.m_uFlags & __flag) ? "On" : "Off");\
		pxDialog->SetHelpText(szHelpText);\
	}

	
	pxDialog = new Asura_Function_Dialog("Template",xOffset,SelectWaterTemplate);
	pxDialog->SetControlID( DialogID_Water_SelectTemplate );
	pxDialog->SetHelpText("Select the template to use");
	xOffset.y+= Asura_Dialog::DefaultSpacing();
	pxOverlay->AddDialog(pxDialog);

	pxDialog = new Asura_Function_Dialog("Reset To Defaults",xOffset,ResetWaterToDefaults);
	pxDialog->SetHelpText("Resets the water settings to their default values.\nThe textures , and any settings controlled by the current template won't be changed.");
	xOffset.y+= Asura_Dialog::LargeSpacing();
	pxOverlay->AddDialog(pxDialog);

	//Add tab control
	static char* s_apszTabs[4] = {"Waves","Sun","Horizon","Other"};
	Asura_Tabs_Dialog* pxTabsDialog = new Asura_Tabs_Dialog(xOffset,s_apszTabs,4);
	pxOverlay->AddDialog(pxTabsDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();

	float fTabsStartY = xOffset.y;
	float fTabsEndY = xOffset.y;

	//Waves tab	
	pxTabsDialog->SelectTab(0);
	const float fCol0 = 1.0f;
	const float fCol1 = 8.0f;
	const float fCol2 = 20.0f;
	const float fCol3 = 32.0f;

	//add column headings
	xOffset.x = fCol1+3.0f;
	pxDialog = new Asura_Dialog("Wave 1",xOffset);
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol2+3.0f;
	pxDialog = new Asura_Dialog("Wave 2",xOffset);
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol3+3.0f;
	pxDialog = new Asura_Dialog("Wave 3",xOffset);
	pxDialog->SetHelpText("Wave 3 - only used for normals, not vertex positions");
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.y+= Asura_Dialog::DefaultSpacing();
	
	//water cycle scale
	xOffset.x = fCol0;
	pxDialog = new Asura_Dialog("Cycle Scale",xOffset);
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol1;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fWaterCycleScale1,0,999.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave speed for waveform 1",m_fWaterCycleScale1);
	pxDialog->SetControlID( DialogID_Water_WaterCycleScale1 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol2;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fWaterCycleScale2,0,999.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave speed for waveform 2",m_fWaterCycleScale2);
	pxDialog->SetControlID( DialogID_Water_WaterCycleScale2 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol3;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fWaterCycleScale3,0,999.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave speed for waveform 3",m_fWaterCycleScale3);
	pxDialog->SetControlID( DialogID_Water_WaterCycleScale3 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.y+= Asura_Dialog::DefaultSpacing();

	//X scale
	xOffset.x = fCol0;
	pxDialog = new Asura_Dialog("X Scale",xOffset);
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol1;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fXScale1,-5.0f,5.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 1 frequency in X direction (small value = longer wave)",m_fXScale1);
	pxDialog->SetControlID( DialogID_Water_XScale1 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol2;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fXScale2,-5.0f,5.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 2 frequency in X direction (small value = longer wave)",m_fXScale2);
	pxDialog->SetControlID( DialogID_Water_XScale2 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol3;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fXScale3,-5.0f,5.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 3 frequency in X direction (small value = longer wave)",m_fXScale3);
	pxDialog->SetControlID( DialogID_Water_XScale3 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.y+= Asura_Dialog::DefaultSpacing();

	//Y scale
	xOffset.x = fCol0;
	pxDialog = new Asura_Dialog("Y Scale",xOffset);
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol1;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fYScale1,-99.0f,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 1 height at peak",m_fYScale1);
	pxDialog->SetControlID( DialogID_Water_YScale1 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol2;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fYScale2,-99.0f,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 2 height at peak",m_fYScale2);
	pxDialog->SetControlID( DialogID_Water_YScale2 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol3;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fYScale3,-99.0f,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 3 height at peak",m_fYScale3);
	pxDialog->SetControlID( DialogID_Water_YScale3 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.y+= Asura_Dialog::DefaultSpacing();

	//Z scale
	xOffset.x = fCol0;
	pxDialog = new Asura_Dialog("Z Scale",xOffset);
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol1;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fZScale1,-5.0f,5.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 1 frequency in Z direction (small value = longer wave)",m_fZScale1);
	pxDialog->SetControlID( DialogID_Water_ZScale1 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol2;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fZScale2,-5.0f,5.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 2 frequency in Z direction (small value = longer wave)",m_fZScale2);
	pxDialog->SetControlID( DialogID_Water_ZScale2 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol3;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fZScale3,-5.0f,5.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Wave 3 frequency in Z direction (small value = longer wave)",m_fZScale3);
	pxDialog->SetControlID( DialogID_Water_ZScale3 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.y+= Asura_Dialog::DefaultSpacing();

	//Falloff
	xOffset.x = fCol0;
	pxDialog = new Asura_Dialog("Falloff",xOffset);
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol1;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fFalloff1,0,99999.0f,100.0f,"%.1f",&s_bWaterModified);
	SET_HELPTEXT("Distance at which wave 1 starts to fade out",m_fFalloff1);
	pxDialog->SetControlID( DialogID_Water_Falloff1 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol2;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fFalloff2,0,99999.0f,100.0f,"%.1f",&s_bWaterModified);
	SET_HELPTEXT("Distance at which wave 1 starts to fade out",m_fFalloff2);
	pxDialog->SetControlID( DialogID_Water_Falloff2 );
	pxTabsDialog->AddDialog(pxDialog);

	xOffset.x = fCol3;
	pxDialog = new Asura_Numerical_Dialog("",xOffset,&xControl.m_fFalloff3,0,99999.0f,100.0f,"%.1f",&s_bWaterModified);
	SET_HELPTEXT("Distance at which wave 1 starts to fade out",m_fFalloff3);
	pxDialog->SetControlID( DialogID_Water_Falloff3 );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();
	xOffset.x = 1.0f;

	if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;

	//Sun tab
	pxTabsDialog->SelectTab(1);
	xOffset.y = fTabsStartY;

	pxDialog = new Asura_Numerical_Dialog("Sun Texture Offset U", xOffset, &xControl.m_afTexOffset[0], 0, 1.0f, 0.1f, "%.3f", &s_bWaterModified);
	SET_HELPTEXT("",m_afTexOffset[0]);
	pxDialog->SetControlID( DialogID_Water_SunTextureOffsetU );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Sun Texture Offset V", xOffset, &xControl.m_afTexOffset[1], 0, 1.0f, 0.1f, "%.3f", &s_bWaterModified);
	SET_HELPTEXT("",m_afTexOffset[1]);
	pxDialog->SetControlID( DialogID_Water_SunTextureOffsetV );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Sun Texture Scale U", xOffset, &xControl.m_afTexScale[0], -99999.0, 99999.0f, 0.1f, "%.2f", &s_bWaterModified);
	SET_HELPTEXT("",m_afTexScale[0]);
	pxDialog->SetControlID( DialogID_Water_SunTextureScaleU );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Sun Texture Scale V", xOffset, &xControl.m_afTexScale[1], -99999.0, 99999.0f, 0.1f, "%.2f", &s_bWaterModified);
	SET_HELPTEXT("",m_afTexScale[1]);
	pxDialog->SetControlID( DialogID_Water_SunTextureScaleV );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Sun Y Scale",xOffset,&xControl.m_fSunYScale,0.0f,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Controls sun reflection normal scaling - use higher value for flatter waves",m_fSunYScale);
	pxDialog->SetControlID( DialogID_Water_SunYScale );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Sunlight Falloff Near",xOffset,&xControl.m_fSunlightFalloffNear,0.0f,999.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("",m_fSunlightFalloffNear);
	pxDialog->SetControlID( DialogID_Water_SunlightFalloffNear );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Sunlight Falloff Far",xOffset,&xControl.m_fSunlightFalloffFar,0.0f,999.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("",m_fSunlightFalloffFar);
	pxDialog->SetControlID( DialogID_Water_SunlightFalloffFar );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

    pxDialog = new Asura_Tickbox_Dialog("Use Level Sun",xOffset,&xControl.m_bUseLevelSun);
	pxDialog->SetHelpText("If activated then the water uses the sun position defined in weather mode for determining the sun direction.\nOtherwise the direction set by 'Set Sun Direction' is used.");
    pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog("Set Sun Direction",xOffset,SetWaterSunDirection);
	pxDialog->SetHelpText("Sets the sun dirction to be the current facing of the camera.");
    pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

    pxDialog = new Asura_FlagTickbox_Dialog("Sun Reflect",xOffset,&xControl.m_uFlags,AsuraWaterFlag_SunReflect);
	SET_HELPTEXTFLAG("",AsuraWaterFlag_SunReflect);
	pxDialog->SetControlID( DialogID_Water_SunReflect );
    pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();



	if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;

	//Horizon tab
	pxTabsDialog->SelectTab(2);
	xOffset.y = fTabsStartY;

	pxDialog = new Asura_Numerical_Dialog("Horizon V Scale",xOffset,&xControl.m_fHorizonVScale,-99.0f,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Controls V texture co-ordinate scale for horizon reflection",m_fHorizonVScale);
	pxDialog->SetControlID( DialogID_Water_HorizonVScale );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Horizon V Offset",xOffset,&xControl.m_fHorizonVOffset,-99.0f,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Controls V texture co-ordinate offset for horizon reflection",m_fHorizonVOffset);
	pxDialog->SetControlID( DialogID_Water_HorizonVOffset );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Horizon Y Scale",xOffset,&xControl.m_fHorizonYScale,-99.0f,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Controls horizon effect normal scaling - use higher value for flatter waves",m_fHorizonYScale);
	pxDialog->SetControlID( DialogID_Water_HorizonYScale );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Horizon Brightness",xOffset,&xControl.m_fHorizonBrightness,0.0f,255.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT( "Controls brightness or contribution of horizon reflection",m_fHorizonBrightness);
	pxDialog->SetControlID( DialogID_Water_HorizonBrightness );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Horizon Fresnel Scale",xOffset,&xControl.m_fHorizonFresnelScale,0.0f,1.0f,0.01f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT( "Controls strength of fresnel factor - useful for blended horizon (lower to make more transparent)",m_fHorizonFresnelScale );
	pxDialog->SetControlID( DialogID_Water_HorizonFresnelScale );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

    pxDialog = new Asura_FlagTickbox_Dialog("Horizon Reflect",xOffset,&xControl.m_uFlags,AsuraWaterFlag_HorizonReflect);
	SET_HELPTEXTFLAG("",AsuraWaterFlag_HorizonReflect);
	pxDialog->SetControlID( DialogID_Water_HorizonReflect );
    pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

    pxDialog = new Asura_FlagTickbox_Dialog("Blend Horizon",xOffset,&xControl.m_uFlags,AsuraWaterFlag_BlendHorizon);
	SET_HELPTEXTFLAG("",AsuraWaterFlag_BlendHorizon);
	pxDialog->SetControlID( DialogID_Water_BlendHorizon );
    pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;

	//Other tab
	pxTabsDialog->SelectTab(3);
	xOffset.y = fTabsStartY;

	pxDialog = new Asura_Numerical_Dialog("Subdivision Threshold",xOffset,&xControl.m_fThreshold,0,99999.0f,100.0f,"%.0f",&s_bWaterModified);
	SET_HELPTEXT("This controls the subdivision level - bigger numbers make bigger polygons",m_fThreshold);
	pxDialog->SetControlID( DialogID_Water_Threshold );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Subdivision Y Scale",xOffset,&xControl.m_fSubdivisionYScale,0.0f,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Modifies the subdivision so that vertical subdivision is more or less than horizontal",m_fSubdivisionYScale);
	pxDialog->SetControlID( DialogID_Water_SubdivisionYScale );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Light Offset",xOffset,&xControl.m_fLightOffset,0,1.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Limits how dark the dark bits go",m_fLightOffset);
	pxDialog->SetControlID( DialogID_Water_LightOffset );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Light Scale",xOffset,&xControl.m_fLightScale,0,99.0f,0.1f,"%.3f",&s_bWaterModified);
	SET_HELPTEXT("Determines how bright it goes at the top",m_fLightScale);
	pxDialog->SetControlID( DialogID_Water_LightScale );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Alpha Level",xOffset,&xControl.m_fAlphaLevel,0,128.0f,1.0f,"%.1f",&s_bWaterModified);
	SET_HELPTEXT("Controls transparency for base water texture (128 is solid)",m_fAlphaLevel);
	pxDialog->SetControlID( DialogID_Water_AlphaLevel );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Reflection Strength",xOffset,&xControl.m_fSunBrightness,0,99999.0f,1.0f,"%.0f",&s_bWaterModified);
	SET_HELPTEXT("Determines how bright the sun reflection is",m_fSunBrightness);
	pxDialog->SetControlID( DialogID_Water_Reflection );
	pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+= Asura_Dialog::DefaultSpacing();


    pxDialog = new Asura_Numerical_Dialog( "U scroll speed", xOffset, &xControl.m_afUVSpeeds[0], -1.0f, 1.0f, 0.001f, "%.3f", &s_bWaterModified );
	SET_HELPTEXT("",m_afUVSpeeds[0]);
    pxDialog->SetControlID( DialogID_Water_UScrollSpeed );
    pxTabsDialog->AddDialog( pxDialog );
    xOffset.y += Asura_Dialog::DefaultSpacing();

    pxDialog = new Asura_Numerical_Dialog( "V scroll speed", xOffset, &xControl.m_afUVSpeeds[1], -1.0f, 1.0f, 0.001f, "%.3f", &s_bWaterModified );
	SET_HELPTEXT("",m_afUVSpeeds[1]);
    pxDialog->SetControlID( DialogID_Water_VScrollSpeed );
    pxTabsDialog->AddDialog( pxDialog );
    xOffset.y += Asura_Dialog::DefaultSpacing();

    pxDialog = new Asura_FlagTickbox_Dialog("Transparent",xOffset,&xControl.m_uFlags,AsuraWaterFlag_Transparent);
	SET_HELPTEXTFLAG("",AsuraWaterFlag_Transparent);
	pxDialog->SetControlID( DialogID_Water_Transparent );
    pxTabsDialog->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;

	//Non tabbed stuff
	pxTabsDialog->SelectTab(0);
	xOffset.y = fTabsEndY + 1.0f;



	xOffset.x = 0.5f;
	Asura_Icon_Dialog* pxIcon = new Asura_Icon_Dialog(xOffset,Tools_Dialog::GetIconTexture(),TOOLS_ICON_DELETE);
	pxIcon->SetClickedFunction(ClearWaterTexture,0);
	pxIcon->SetHelpText("Clear texture 1");
	pxOverlay->AddDialog(pxIcon);
	
	xOffset.x += 2.0f;
	pxDialog = new Asura_Function_Dialog("Texture 1",xOffset,SelectWaterTexture,0);
	pxDialog->SetHelpText("This texture is for the surface of the water, the UVs from the original mesh will be used");
	pxDialog->SetControlID( DialogID_Water_Texture0 );
    pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	xOffset.x -= 2.0f;

	pxIcon = new Asura_Icon_Dialog(xOffset,Tools_Dialog::GetIconTexture(),TOOLS_ICON_DELETE);
	pxIcon->SetClickedFunction(ClearWaterTexture,1);
	pxIcon->SetHelpText("Clear texture 2");
	pxOverlay->AddDialog(pxIcon);

	xOffset.x += 2.0f;
	pxDialog = new Asura_Function_Dialog("Texture 2",xOffset,SelectWaterTexture,1);
	pxDialog->SetHelpText("This texture is horizon reflection effect.");
	pxDialog->SetControlID( DialogID_Water_Texture1 );
    pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	xOffset.x -= 2.0f;

	pxIcon = new Asura_Icon_Dialog(xOffset,Tools_Dialog::GetIconTexture(),TOOLS_ICON_DELETE);
	pxIcon->SetClickedFunction(ClearWaterTexture,2);
	pxIcon->SetHelpText("Clear texture 3");
	pxOverlay->AddDialog(pxIcon);

	xOffset.x += 2.0f;
	pxDialog = new Asura_Function_Dialog("Texture 3",xOffset,SelectWaterTexture,2);
	pxDialog->SetHelpText("This texture is sun reflection effect.");
	pxDialog->SetControlID( DialogID_Water_Texture2 );
    pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::LargeSpacing();
	xOffset.x -= 2.0f;

	xOffset.x = 1.0f;

	pxDialog = new Asura_Function_Dialog("Start preview", xOffset, StartWaterPreview);
	pxDialog->SetHelpText("Preview the water effect.");
	pxDialog->SetControlID( DialogID_Water_Preview_Start );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog("Stop preview", xOffset, StopWaterPreview);
	pxDialog->SetHelpText("Stop previewing the water effect.");
	pxDialog->SetControlID( DialogID_Water_Preview_Stop );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxOverlay->ID = TOOLS_OVERLAY_WATER;
	Asura_Overlay_System::SubmitNewOverlay(pxOverlay,false);

	UpdateWaterOverlay();


	#undef SET_HELPTEXT
	#undef SET_HELPTEXTFLAG

}


void Tools_Mode_Weather::UpdateWaterOverlay()
{
	const Asura_Water_System::Env_Water_Controls& xControl = Asura_Water_System::GetEnvController();

	//find the overlay
	Asura_Overlay* pxOverlay = Asura_Overlay_System::GetOverlay(TOOLS_OVERLAY_WATER);
	if(!pxOverlay) return;

	char szText[200];
	//update template name
	if(xControl.m_xTemplateName.IsBlank())
	{
		Asura_PrintfToBfr(szText,"Template : *None*",200,true);
	}
	else
	{
		Asura_PrintfToBfr(szText,"Template : %s",200,true,xControl.m_xTemplateName.GetString());
	}
	pxOverlay->UpdateDialogLabel(DialogID_Water_SelectTemplate,szText);
			

	//update the texture names
	for(int i=0;i<3;i++)
	{
		if(xControl.m_axToolsTextureNames[i].IsBlank())
		{
			Asura_PrintfToBfr(szText,"Texture %d : *None*",200,true,i+1);
		}
		else
		{
			Asura_PrintfToBfr(szText,"Texture %d : %s",200,true,i+1,Tools_FileSystem::StripPath(xControl.m_axToolsTextureNames[i].GetString()));
		}
		pxOverlay->UpdateDialogLabel(DialogID_Water_Texture0+i,szText);
	}

	const Tools_WaterTemplate* pxTemplate = Tools_WaterTemplate_System::GetTemplate(xControl.m_xTemplateName.GetString());

	//update enabled states
	#define UPDATE_ENABLED(__ID,__Valid)\
	{\
		Asura_Dialog* pxDialog = pxOverlay->GetDialog(__ID);\
		if(pxDialog)\
		{\
			bool bEnable = pxTemplate ? !pxTemplate->__Valid : true;\
			pxDialog->SetEnabled(bEnable);\
		}\
	}

	UPDATE_ENABLED(DialogID_Water_WaterCycleScale1,m_bWaterCycleScale1_Valid)
	UPDATE_ENABLED(DialogID_Water_WaterCycleScale2,m_bWaterCycleScale2_Valid)
	UPDATE_ENABLED(DialogID_Water_WaterCycleScale3,m_bWaterCycleScale3_Valid)

	UPDATE_ENABLED(DialogID_Water_XScale1,m_bXScale1_Valid)
	UPDATE_ENABLED(DialogID_Water_XScale2,m_bXScale2_Valid)
	UPDATE_ENABLED(DialogID_Water_XScale3,m_bXScale3_Valid)

	UPDATE_ENABLED(DialogID_Water_YScale1,m_bYScale1_Valid)
	UPDATE_ENABLED(DialogID_Water_YScale2,m_bYScale2_Valid)
	UPDATE_ENABLED(DialogID_Water_YScale3,m_bYScale3_Valid)

	UPDATE_ENABLED(DialogID_Water_ZScale1,m_bZScale1_Valid)
	UPDATE_ENABLED(DialogID_Water_ZScale2,m_bZScale2_Valid)
	UPDATE_ENABLED(DialogID_Water_ZScale3,m_bZScale3_Valid)

	UPDATE_ENABLED(DialogID_Water_Falloff1,m_bFalloff1_Valid)
	UPDATE_ENABLED(DialogID_Water_Falloff2,m_bFalloff2_Valid)
	UPDATE_ENABLED(DialogID_Water_Falloff3,m_bFalloff3_Valid)

	UPDATE_ENABLED(DialogID_Water_Threshold,m_bThreshold_Valid)
	UPDATE_ENABLED(DialogID_Water_LightOffset,m_bLightOffset_Valid)
	UPDATE_ENABLED(DialogID_Water_LightScale,m_bLightScale_Valid)
	UPDATE_ENABLED(DialogID_Water_AlphaLevel,m_bAlphaLevel_Valid)
	UPDATE_ENABLED(DialogID_Water_Reflection,m_bReflection_Valid)
	UPDATE_ENABLED(DialogID_Water_SunTextureOffsetU,m_bSunTextureOffsetU_Valid)
	UPDATE_ENABLED(DialogID_Water_SunTextureOffsetV,m_bSunTextureOffsetV_Valid)
	UPDATE_ENABLED(DialogID_Water_SunTextureScaleU,m_bSunTextureScaleU_Valid)
	UPDATE_ENABLED(DialogID_Water_SunTextureScaleV,m_bSunTextureScaleV_Valid)
	UPDATE_ENABLED(DialogID_Water_HorizonVScale,m_bHorizonVScale_Valid)
	UPDATE_ENABLED(DialogID_Water_HorizonVOffset,m_bHorizonVOffset_Valid)
	UPDATE_ENABLED(DialogID_Water_HorizonYScale,m_bHorizonYScale_Valid)
	UPDATE_ENABLED(DialogID_Water_HorizonBrightness,m_bHorizonBrightness_Valid)
	UPDATE_ENABLED(DialogID_Water_Transparent,m_bTransparent_Valid)
	UPDATE_ENABLED(DialogID_Water_HorizonReflect,m_bHorizonReflect_Valid)
	UPDATE_ENABLED(DialogID_Water_SunReflect,m_bSunReflect_Valid)
	UPDATE_ENABLED(DialogID_Water_BlendHorizon,m_bBlendHorizon_Valid)
	UPDATE_ENABLED(DialogID_Water_SubdivisionYScale,m_bSubdivisionYScale_Valid)
	UPDATE_ENABLED(DialogID_Water_SunlightFalloffNear,m_bSunlightFalloffNear_Valid)
	UPDATE_ENABLED(DialogID_Water_SunlightFalloffFar,m_bSunlightFalloffFar_Valid)
	UPDATE_ENABLED(DialogID_Water_UScrollSpeed,m_bUScrollSpeed_Valid)
	UPDATE_ENABLED(DialogID_Water_VScrollSpeed,m_bVScrollSpeed_Valid)

	#undef UPDATE_ENABLED
}


void Tools_Mode_Weather::SetWaterSunDirection()
{
	Asura_Water_System::Env_Water_Controls& xControl = Asura_Water_System::GetEnvController();

	const Asura_Matrix_3x3* pxCamMat = Asura_Camera::GetOrientation();

	xControl.m_bUseLevelSun = false;
	xControl.m_afSunDir[0] = -pxCamMat->e13;
	xControl.m_afSunDir[1] = -pxCamMat->e23;
	xControl.m_afSunDir[2] = -pxCamMat->e33;
	s_bWaterModified = true;

    Tools_Timed_Message_System::AddMessage( 0xFFFFFF, "Set sun direction to current camera direction");
}

void Tools_Mode_Weather::SelectWaterTexture(int iIndex)
{
	Asura_Water_System::Env_Water_Controls& xControl = Asura_Water_System::GetEnvController();
	int iTextureID = xControl.m_aiTextureID[iIndex];

	//ask for new texture
	iTextureID = Tools_PickTexture::PickTexture("Select Water Texture",iTextureID,PICKTEXTURE_ALLTEXTURES);

	if(iTextureID == ASURA_TEXTURE_NONE) return;

	//update the stored texture ID
	xControl.m_aiTextureID[iIndex] = iTextureID;
	//and get its name
	const Asura_String* pxName = Asura_Texture_Management::GetTextureName(iTextureID);
	Asura_Assert(pxName,"");
	xControl.m_axToolsTextureNames[iIndex] = *pxName;

	s_bWaterModified = true;
	UpdateWaterOverlay();
}

void Tools_Mode_Weather::ClearWaterTexture(int iIndex)
{
	Asura_Water_System::Env_Water_Controls& xControl = Asura_Water_System::GetEnvController();

	xControl.m_aiTextureID[iIndex] = ASURA_TEXTURE_NONE;
	xControl.m_axToolsTextureNames[iIndex].MakeBlank();

 	s_bWaterModified = true;
	UpdateWaterOverlay();
}

void Tools_Mode_Weather::StartWaterPreview()
{
	// build water packets. We do this by building a saveblock (as if we were exporting) and then reading it back in.
	Asura_SaveBlock xSaveBlock;

	Asura_Water_System::BuildWaterPackets(xSaveBlock, true); // PC renderer needs presubdivided mesh

	// now, parse it back out
	const Asura_Chunk_WaterPacket* pxWaterPacket = reinterpret_cast<const Asura_Chunk_WaterPacket*>(xSaveBlock.GetStartPtr() + ASURA_FILE_ID_NUM_CHARS);
	u_int uBytesProcessed = ASURA_FILE_ID_NUM_CHARS;
	while(uBytesProcessed < xSaveBlock.GetSize())
	{
		u_int uThisPacketSize = sizeof(Asura_Chunk_WaterPacket) + sizeof(Asura_Chunk_WaterPacket_Vertex) * pxWaterPacket->m_iNumberOfVertices;

		Asura_Water_Packet* pxPacket = Asura_Water_System::AllocateWaterPacket();
		if(!pxPacket) return;

		pxPacket->m_iModuleIndex = pxWaterPacket->m_iModuleIndex;

		//allocate , and fill in the platform packet data
		pxPacket->m_pxPlatformPacket = new Asura_Platform_Water_Packet;
		pxPacket->m_pxPlatformPacket->SetVertexCount(pxWaterPacket->m_iNumberOfVertices);

		for(int i=0;i<pxWaterPacket->m_iNumberOfVertices;i++)
		{
			const Asura_Chunk_WaterPacket_Vertex* xVert = &reinterpret_cast<const Asura_Chunk_WaterPacket_Vertex*>(&pxWaterPacket[1])[i];

			pxPacket->m_pxPlatformPacket->AddVertex(xVert->m_xPosition.x,xVert->m_xPosition.y,xVert->m_xPosition.z,
													xVert->m_fRed,xVert->m_fGreen,xVert->m_fBlue,
													xVert->m_fU,xVert->m_fV);
		}

		pxPacket->m_pxPlatformPacket->Close();	// You MUST close packets to flush any left over vertices !

		// move to the next packet
		uBytesProcessed += uThisPacketSize;
		const char* pxNextPacket = reinterpret_cast<const char*>(pxWaterPacket) + uThisPacketSize;
		pxWaterPacket = reinterpret_cast<const Asura_Chunk_WaterPacket*>(pxNextPacket);
	}

	// display a warning message if the hardware is below spec
	if(Asura_Direct3D_Caps::GetHardwarePixelShaderVersion() < fWATER_SYSTEM_REQUIRED_PIXEL_SHADER)
	{
		Tools_Timed_Message_System::AddMessage(Tools_Timed_Message_System::COLOUR_ERROR, "Your hardware only supports pixel shader %.1f (%.1f required). Reflections and transparency will not be visible.", Asura_Direct3D_Caps::GetHardwarePixelShaderVersion(), fWATER_SYSTEM_REQUIRED_PIXEL_SHADER);
	}

	Tools_Render_Options::SetPolygonFlagToHide(AsuraPolygonFlag_Water,true);
	Tools_Render_Options::UpdateAllPolygonVisibilities();

	s_bWaterPreview = true;
}

void Tools_Mode_Weather::StopWaterPreview()
{
	// drop all water packets
	Asura_Water_System::Reset();
	Tools_Render_Options::SetPolygonFlagToHide(AsuraPolygonFlag_Water,false);
	Tools_Render_Options::UpdateAllPolygonVisibilities();
	s_bWaterPreview = false;
}

void Tools_Mode_Weather::SelectWaterTemplate()
{
	Asura_Water_System::Env_Water_Controls& xControl = Asura_Water_System::GetEnvController();

	ListSelection_Overlay xOverlay("Select Template");

	const List<Tools_WaterTemplate*>* pxTemplateList = Tools_WaterTemplate_System::GetTemplateList();
	//add the names of the templates to the overlay
	for(CLIF<Tools_WaterTemplate*> xTempLIF(pxTemplateList);!xTempLIF.done();xTempLIF.next())
	{
		const Tools_WaterTemplate* pxTemplate = xTempLIF();
		
		bool bSelected = !stricmp(pxTemplate->m_xTemplateName.GetString(),xControl.m_xTemplateName.GetString());
		xOverlay.AddItem(pxTemplate->m_xTemplateName.GetString(),(int)pxTemplate,bSelected);
	}
	//add entry for no template
	xOverlay.AddItem("*None*",0,xControl.m_xTemplateName.IsBlank());

	if(!xOverlay.DoModal()) return;

	//get the selection
	const Tools_WaterTemplate* pxTemplate = (Tools_WaterTemplate*) xOverlay.GetSelectionData();
	if(pxTemplate)
	{
		xControl.m_xTemplateName = pxTemplate->m_xTemplateName;
		Tools_WaterTemplate_System::UpdateFromTemplate();
	}
	else
	{
		xControl.m_xTemplateName = "";
	}

 	s_bWaterModified = true;
	UpdateWaterOverlay();
}

void Tools_Mode_Weather::ResetWaterToDefaults()
{
	bool bOkay = ShowYesNoOverlay("This will reset the water settings to their default values ,except for textures , and settings controlled by the current template.\nOkay to reset?");
	if(!bOkay) return;

    Asura_Water_System::Env_Water_Controls& xControl = Asura_Water_System::GetEnvController();

	//take a copy of the current settings , in order to preserve some stuff that shouldn't be reset
	Asura_Water_System::Env_Water_Controls xCopy = xControl;

	//reset the main controller
	Asura_Water_System::SetDefaults(&xControl);

	//Want to keep the textures and template name
	for(int i=0;i<3;i++)
	{
		xControl.m_aiTextureID[i] = xCopy.m_aiTextureID[i];
		xControl.m_axToolsTextureNames[i] = xCopy.m_axToolsTextureNames[i];
	}

	//update from the template again
	Tools_WaterTemplate_System::UpdateFromTemplate();

	
 	s_bWaterModified = true;
	UpdateWaterOverlay();

}

#endif //ASURA_USE_WATER


#ifdef ASURA_USE_PSP_BLUR
bool Tools_Mode_Weather::IsEnabled_PSPBlur()
{
	return Tools_PSP_Blur::s_bEnabled;
}
#endif //ASURA_USE_PSP_BLUR

#ifdef ASURA_USE_PSP_FILTER
bool Tools_Mode_Weather::IsEnabled_PSPFilter()
{
	return Tools_PSP_Filter::s_bEnabled;
}
#endif //ASURA_USE_PSP_BLUR

void Tools_Mode_Weather::RefreshWeatherOverlay()
{
	Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_WEATHER);
	CreateWeatherOverlay();
}

/****************/
/* End of file. */
/****************/
