//
// Tools_GUIMenu_PreviewOverlay.cpp
//
// Created by Richard Rice - 12/03/2007
// 
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"
#include "GUIMenu/Tools_GUIMenu_PreviewOverlay.h"

#ifdef ASURA_USE_GUI_MENU_SYSTEM


#include "Core/Asura_HashTree.h"
#include "Core/Asura_Timers.h"
#include "GUIMenu/Asura_GUIMenu_System.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Overlay_System.h"
#include "Rendering/Asura_Viewport.h"
#include "Rendering/Asura_Text_Output.h"

#include "Tools_Overlays.h"
#include "GUIMenu/Tools_Mode_GUIMenu.h"
#include "GUIMenu/Tools_GUIMenu_Root.h"
#include "Misc/list_tem.hpp"

Asura_Vector_2 Tools_GUIMenu_PreviewOverlay::s_xOverlayPosition(30.0f,3.0f);
Asura_Vector_2 Tools_GUIMenu_PreviewOverlay::s_xSubwindowSize(0.0f,0.0f);
u_int Tools_GUIMenu_PreviewOverlay::s_uOverlayMinimised = false;
bool Tools_GUIMenu_PreviewOverlay::s_bEnableAutoclick;
Asura_String Tools_GUIMenu_PreviewOverlay::s_xLastAutoclick;
u_int Tools_GUIMenu_PreviewOverlay::s_uLastAutoclickTime;
Asura_String Tools_GUIMenu_PreviewOverlay::s_xPopulationText;
bool Tools_GUIMenu_PreviewOverlay::s_bUseCursor = true;
bool Tools_GUIMenu_PreviewOverlay::s_bShowScreenBorder = false;
bool Tools_GUIMenu_PreviewOverlay::s_bShowSafeArea = false;
bool Tools_GUIMenu_PreviewOverlay::s_bClipToScreen = false;
bool Tools_GUIMenu_PreviewOverlay::s_bCentreScreen = false;
bool Tools_GUIMenu_PreviewOverlay::s_bUseVirtualResolution = true;

Asura_Hash_ID Tools_GUIMenu_PreviewOverlay::s_uCurrentMenu = 0;
Asura_TemplateHashTree<Tools_GUIMenu_ConsoleData> Tools_GUIMenu_PreviewOverlay::s_xConsoleDataTree;
List<Tools_GUIMenu_ConsoleData*> Tools_GUIMenu_PreviewOverlay::s_xConsoleDataList;

List<Asura_Numerical_Dialog*> Tools_GUIMenu_PreviewOverlay::s_xConsoleDialogList;

float Tools_GUIMenu_PreviewOverlay::s_fStepValue = 0.1f;
float Tools_GUIMenu_PreviewOverlay::s_fSpeed= 0.1f;

void Tools_GUIMenu_PreviewOverlay::Initialise()
{
}

void Tools_GUIMenu_PreviewOverlay::Shutdown()
{
	while(s_xConsoleDataList.size()) s_xConsoleDataList.delete_first_entry();
	s_xConsoleDataTree.Reset();
}


void Tools_GUIMenu_PreviewOverlay::StartPreview(const Tools_GUIMenu_Root* pxRootItem)
{
	s_fSpeed = 1.0f;

	//Make sure the full list of all console variables/commands used is up to date.
	s_uCurrentMenu = 0;
	pxRootItem->AddToPreviewOverlayRecursive();	

	ShowOverlay();
}

void Tools_GUIMenu_PreviewOverlay::ShowOverlay()
{
	CloseOverlay();

	//Find the current menu
	s_uCurrentMenu = Asura_GUIMenu_System::GetFocusedMenuHashID();

	//Update list of variables/commands for the current menu.
	BuildCurrentVariableList();


	Asura_Overlay* pxOverlay = new Asura_Overlay("Preview",false,&s_xOverlayPosition,&s_uOverlayMinimised);
	Asura_Vector_2 xOffset = Asura_Vector_2(1.0f,3.0f);

	Tools_Mode_GUIMenu::AddPlatformDropDown(pxOverlay, xOffset);

	Asura_Dialog* pxDialog = new Asura_Tickbox_Dialog("Use Mouse",xOffset,&s_bUseCursor);
	pxDialog->SetHelpText("Determines whether mouse support should be enabled.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Show Screen Border",xOffset, &s_bShowScreenBorder);
	pxDialog->SetHelpText("Enables rendering of a rectangle representing the extents of the screen.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Show Safe Area",xOffset, &s_bShowSafeArea);
	pxDialog->SetHelpText("Enables rendering of a rectangle representing the safe area on the screen.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Clip To Screen",xOffset, &s_bClipToScreen);
	pxDialog->SetHelpText("Causes anything outside of the specified screen area to be clipped out");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Centre Screen",xOffset, &s_bCentreScreen);
	pxDialog->SetHelpText("Positions the screen area defined by the extents on the display tab for this mode on the centre of the screen.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Use Virtual Resolution",xOffset, &s_bUseVirtualResolution);
	pxDialog->SetHelpText("Uses the virtual resolution of the target display, to give an indication of how the screen will look on target platform.\nNote this isn't pixel to pixel, so image render quality will be impared");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("enable autoclick",xOffset,&s_bEnableAutoclick);
	pxDialog->SetHelpText("Whether buttons flagged to autoclick will do so in the preview");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

  	pxDialog = new Asura_String_Dialog( "last autoclick", xOffset, &s_xLastAutoclick, 32 );
	((Asura_String_Dialog*)pxDialog)->SetMaxStringLength(1000);
  	pxOverlay->AddDialog(pxDialog);
  	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_String_Dialog( "population function text", xOffset, &s_xPopulationText, 32 );
	((Asura_String_Dialog*)pxDialog)->SetMaxStringLength(1000);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Speed",xOffset,&s_fSpeed,0.001f,2.0f,0.01f,"%.3f");
	pxDialog->SetHelpText("Set the preview playback speed of the GUI Menu system and animations");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Dialog("Commands/Variables :",xOffset);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
	pxDialog = new Asura_Numerical_Dialog("Console Var Step",xOffset,&s_fStepValue,0.001f,1000.0f,0.01f,"%.3f");
	pxDialog->SetHelpText("Set the step value for the console command vars");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	//Create the subwindow control for containing all the other controls
	float fSubwindowWidth = Asura_Maths::Min(30.0f,(Asura_Viewport::GetWidth()-100)/ASURA_TEXT_OUTPUT_FONT_WIDTH);
	float fSubwindowHeight = Asura_Maths::Min(20.0f,(Asura_Viewport::GetHeight()-100)/ASURA_TEXT_OUTPUT_FONT_HEIGHT);
	Asura_Subwindow_Dialog* pxSubwindowDialog = new Asura_Subwindow_Dialog(xOffset,fSubwindowWidth,fSubwindowHeight,true);
	pxOverlay->AddDialog(pxSubwindowDialog);

	//add control for resizing the subwindow dialog
	pxDialog = new Asura_Resize_Dialog(pxSubwindowDialog, &s_xSubwindowSize);
	pxOverlay->AddDialog(pxDialog);

	//Add controls for all used commands/variables
	Asura_Vector_2 xSubOffset(1.0f,pxSubwindowDialog->GetChildMaxY() + 0.5f);

	//Reset the list of numeric controls. Make sure the list is empty
	s_xConsoleDialogList.empty();

	for(LIF<Tools_GUIMenu_ConsoleData*> xDataLIF(&s_xConsoleDataList);!xDataLIF.done();xDataLIF.next())
	{
		Tools_GUIMenu_ConsoleData* pxData = xDataLIF();

		const char* szVarHelp = "Sets the current value of the console variable to use for previewing the menus.\nChanges to this only has immediate effect when used for display conditions at the moment.";
		const char* szCmdHelp = "Sets the current return value to use for this console command.";
		
		//Add overlay control based on variable/command type
		switch(pxData->m_iType)
		{
			case Asura_CommandConsole_VarRepository::Var::TYPE_BOOL :
			{
				pxDialog = new Asura_Tickbox_Dialog(pxData->m_xName.GetString(),xSubOffset,&pxData->m_bData);
				pxDialog->SetHelpText(pxData->m_bCmd ? szCmdHelp : szVarHelp);
				pxSubwindowDialog->AddDialog(pxDialog);
				xSubOffset.y += Asura_Dialog::DefaultSpacing();
				break;
			}

			case Asura_CommandConsole_VarRepository::Var::TYPE_INT :
			case Asura_CommandConsole_VarRepository::Var::TYPE_INVALID ://treat unknown variables as ints
			{
				int iMin = -999999;
				int iMax = 999999;

				//get min/max from variable , if available
				if(pxData->m_pxVar)
				{
					iMin = pxData->m_pxVar->m_xData.iLowerLimit;
					iMax = pxData->m_pxVar->m_xData.iUpperLimit;
				}

				pxDialog = new Asura_Numerical_Dialog(pxData->m_xName.GetString(),xSubOffset,&pxData->m_iData,iMin,iMax,1,"%d");
				pxDialog->SetHelpText(pxData->m_bCmd ? szCmdHelp : szVarHelp);
				pxSubwindowDialog->AddDialog(pxDialog);
				xSubOffset.y += Asura_Dialog::DefaultSpacing();
				break;
			}

			case Asura_CommandConsole_VarRepository::Var::TYPE_FLOAT :
			{
				float fMin = -999999.0f;
				float fMax = 999999.0f;

				//get min/max from variable , if available
				if(pxData->m_pxVar)
				{
					if(pxData->m_pxVar->m_xData.fLowerLimit != -Asura_Maths::LargeFloat)
					{
						fMin = Asura_Maths::Max(fMin,pxData->m_pxVar->m_xData.fLowerLimit);
					}
					if(pxData->m_pxVar->m_xData.fUpperLimit != Asura_Maths::LargeFloat)
					{
						fMax = Asura_Maths::Min(fMax,pxData->m_pxVar->m_xData.fUpperLimit);
					}
				}
				
				pxDialog = new Asura_Numerical_Dialog(pxData->m_xName.GetString(),xSubOffset,&pxData->m_fData,fMin,fMax,s_fStepValue,"%.3f");
				pxDialog->SetHelpText(pxData->m_bCmd ? szCmdHelp : szVarHelp);
				pxSubwindowDialog->AddDialog(pxDialog);
				xSubOffset.y += Asura_Dialog::DefaultSpacing();

				// Add the numeric control so its step value can be changed later.
				s_xConsoleDialogList.add_entry(static_cast<Asura_Numerical_Dialog*>(pxDialog));
				break;
			}

			case Asura_CommandConsole_VarRepository::Var::TYPE_STRING :
			{
				int iMaxLength = 20;

				//get length from variable , if available
				if(pxData->m_pxVar)
				{
					iMaxLength = pxData->m_pxVar->m_xData.uBfrSize;
				}

				int iBoxLength = Asura_Maths::Min(20,iMaxLength);
				pxDialog = new Asura_String_Dialog(pxData->m_xName.GetString(),xSubOffset,&pxData->m_xString,iMaxLength);
				((Asura_String_Dialog*) pxDialog)->SetMaxStringLength(iBoxLength);
				pxDialog->SetHelpText(pxData->m_bCmd ? szCmdHelp : szVarHelp);
				pxSubwindowDialog->AddDialog(pxDialog);
				xSubOffset.y += Asura_Dialog::DefaultSpacing();
				break;
			}

		}
	
	}
	xOffset.y = pxSubwindowDialog->m_xMaxCoord.y + 1.0f;	

	pxOverlay->m_uID = TOOLS_OVERLAY_GUIMENU_PREVIEW;
	Asura_Overlay_System::SubmitNewOverlay(pxOverlay,false);
}

void Tools_GUIMenu_PreviewOverlay::CloseOverlay()
{
	Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_GUIMENU_PREVIEW);
}

void Tools_GUIMenu_PreviewOverlay::Update()
{
	//see if the current menu has changed
	if(s_uCurrentMenu != Asura_GUIMenu_System::GetFocusedMenuHashID())
	{
		CloseOverlay();
		ShowOverlay();
	}

	Asura_GUIMenu_System::SetUseCursor(s_bUseCursor);

	// timeout the last autoclick after 2 seconds
	if (s_uLastAutoclickTime + 2000 < Asura_Timers::GetMSecsSinceStart())
	{
		s_xLastAutoclick = "";
	}

	// Change the step value of all numeric console var controls
	for(LIF<Asura_Numerical_Dialog*> xNumericDialogLIF(&s_xConsoleDialogList);
		!xNumericDialogLIF.done();xNumericDialogLIF.next())
	{
		Asura_Numerical_Dialog* pxDialog = xNumericDialogLIF();

		pxDialog->SetDelta(s_fStepValue);
	}
}


void Tools_GUIMenu_PreviewOverlay::BuildCurrentVariableList()
{
	DeleteCurrentVariableList();
	if(!s_uCurrentMenu) return;

	//Find the tools data for the menu
	Tools_GUIMenu_Root* pxMenu = Tools_Mode_GUIMenu::GetInstance()->FindItemByID(s_uCurrentMenu);
	if(!pxMenu) return;

	//Recurse through the tools items , getting the variables used
	pxMenu->AddToPreviewOverlayRecursive();
}

void Tools_GUIMenu_PreviewOverlay::DeleteCurrentVariableList()
{
	while(s_xConsoleDataList.size()) s_xConsoleDataList.delete_first_entry();
}

void Tools_GUIMenu_PreviewOverlay::RegisterConsoleVariable(const char* szName,int iType)
{
	//ignore console vars that don't get handled by the tools system. RAR 19/04/2007
	if(!Asura_GUIMenu_ConsoleVar::ShouldBeHandledByTools(szName))
	{
		return;
	}

	Tools_GUIMenu_ConsoleData* pxData = AddConsoleVariable(szName,iType);
	if(!pxData) return;

	if(s_uCurrentMenu)
	{
		//add to sorted list of variables used by current menu
		AddConsoleDataForCurrentMenu(pxData);
	}
}

void Tools_GUIMenu_PreviewOverlay::RegisterConsoleCommand(const char* szName)
{
	Tools_GUIMenu_ConsoleData* pxData = AddConsoleCommand(szName);
	if(!pxData) return;

	if(s_uCurrentMenu)
	{
		//add to sorted list of variables used by current menu
		AddConsoleDataForCurrentMenu(pxData);
	}
}


Tools_GUIMenu_ConsoleData* Tools_GUIMenu_PreviewOverlay::AddConsoleVariable(const char* szName,int iType)
{
	if(!szName || !*szName) return 0;
	
	//Search for an existing entry in the hash tree
	Asura_Hash_ID uHash = Asura_GetHashID(szName);
	Tools_GUIMenu_ConsoleData* pxData = s_xConsoleDataTree.GetDataByHash(uHash);

	if(!pxData)
	{
		//Create a new entry for this variable
		pxData = s_xConsoleDataTree.AddNode(uHash);
		pxData->m_xName = szName;

		//See if the console variable exists
		Asura_CommandConsole_VarRepository::Var* pxVar = Asura_CommandConsole_VarRepository::Find(szName);

		if(pxVar)
		{
			pxData->m_iType = pxVar->m_eType;
			pxData->m_pxVar = pxVar;

			//initialise from the current value for the console var
			switch(pxVar->m_eType)
			{
				case Asura_CommandConsole_VarRepository::Var::TYPE_BOOL :
					pxData->m_bData = *pxVar->m_xData.pbData;
					break;

				case Asura_CommandConsole_VarRepository::Var::TYPE_INT :
					pxData->m_iData = *pxVar->m_xData.piData;
					break;

				case Asura_CommandConsole_VarRepository::Var::TYPE_FLOAT :
					pxData->m_fData = *pxVar->m_xData.pfData;
					break;

				case Asura_CommandConsole_VarRepository::Var::TYPE_STRING :
				{
					char szBuffer[100];
					Asura_PrintfToBfr(szBuffer,"%S",sizeof(szBuffer),true,pxVar->m_xData.wszData);
					pxData->m_xString = szBuffer;
					break;
				}

				default :
					Asura_Assert(0,"Unexpected console variable type");
					break;
			}
		}
		else
		{
			Asura_Assertf(0,("Failed to find console variable %s",szName));
			//variable doesn't exist , so assume the passed type will be appropriate
			pxData->m_iType = iType;
		}
	}
	
	
	
	
	

	//hopefully the name matches
	if(stricmp(pxData->m_xName.GetString(),szName))
	{
		Asura_Assertf(0,("Variable %s has the same hash ID as %s",szName,pxData->m_xName.GetString()));
		return 0;
	}

	//shouldn't be a console command
	if(pxData->m_bCmd)
	{
		Asura_Assertf(0,("Found entry for a console command when adding variable %s",szName));
		return 0;
	}


	//and its of the same type
	if(iType != Asura_CommandConsole_VarRepository::Var::TYPE_INVALID && iType != pxData->m_iType)
	{
		Asura_Assertf(0,("Variable type for %s doesn't match previous record for it.",szName));
		return 0;
	}

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_INVALID)
	{
		//Type not set yet , so go with the type passed in ,if any
		if(iType != Asura_CommandConsole_VarRepository::Var::TYPE_INVALID)
		{
			pxData->m_iType = iType;
		}
	}

	return pxData;		
}

Tools_GUIMenu_ConsoleData* Tools_GUIMenu_PreviewOverlay::AddConsoleCommand(const char* szName)
{
	if(!szName || !*szName) return 0;
	
	//Search for an existing entry in the hash tree
	Asura_Hash_ID uHash = Asura_GetHashID(szName);
	Tools_GUIMenu_ConsoleData* pxData = s_xConsoleDataTree.GetDataByHash(uHash);

	if(!pxData)
	{
		//Create a new entry for this command
		pxData = s_xConsoleDataTree.AddNode(uHash);
		pxData->m_xName = szName;

		//just interested in the return type for console commands , which is bool for everything at the moment
		pxData->m_iType = Asura_CommandConsole_VarRepository::Var::TYPE_BOOL;
		pxData->m_bCmd = true;		

	}
	
	
	

	//hopefully the name matches
	if(stricmp(pxData->m_xName.GetString(),szName))
	{
		Asura_Assertf(0,("Command %s has the same hash ID as %s",szName,pxData->m_xName.GetString()));
		return 0;
	}

	//shouldn't be a console variable
	if(!pxData->m_bCmd)
	{
		Asura_Assertf(0,("Found entry for a console variable when adding command %s",szName));
		return 0;
	}


	//Type should be bool
	if(Asura_CommandConsole_VarRepository::Var::TYPE_BOOL != pxData->m_iType)
	{
		Asura_Assertf(0,("Not expecting console command entries that aren't bools."));
		return 0;
	}

	return pxData;		
}


void Tools_GUIMenu_PreviewOverlay::AddConsoleDataForCurrentMenu(Tools_GUIMenu_ConsoleData* pxData)
{
	//Add to alphabetically sorted list.
	//Shouldn't be so many used by any given menu that it matters doing it this way

	LIF<Tools_GUIMenu_ConsoleData*>  xDataLIF(&s_xConsoleDataList);

	for(;!xDataLIF.done();xDataLIF.next())
	{
		//alrady in list?
		if(xDataLIF() == pxData) return;
		
		if( pxData->m_xName.Compare(xDataLIF()->m_xName, true) <= 0 )
		{
			s_xConsoleDataList.add_entry_before( pxData, xDataLIF());
			return;
		}
	}

	s_xConsoleDataList.add_entry( pxData );
	

}

Tools_GUIMenu_ConsoleData* Tools_GUIMenu_PreviewOverlay::GetConsoleVarData(const char* szVarName)
{
	return s_xConsoleDataTree.GetDataByName(szVarName);
}

bool Tools_GUIMenu_PreviewOverlay::GetBoolValue(const char* szVarName)
{
	const Tools_GUIMenu_ConsoleData* pxData = GetConsoleVarData(szVarName);
	
	Asura_Assertf(pxData,("Failed to get data for console variable %s from Tools_GUIMenu_PreviewOverlay",szVarName));
	if(!pxData) return false;

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_BOOL)
	{
		return pxData->m_bData;
	}
	else
	{
		Asura_Assertf(0,("Variable %s isn't listed as a bool in Tools_GUIMenu_PreviewOverlay",szVarName));
		return false;
	}
}

int Tools_GUIMenu_PreviewOverlay::GetIntValue(const char* szVarName)
{
	const Tools_GUIMenu_ConsoleData* pxData = GetConsoleVarData(szVarName);
	
	Asura_Assertf(pxData,("Failed to get data for console variable %s from Tools_GUIMenu_PreviewOverlay",szVarName));
	if(!pxData) return 0;

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_INT || pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_INVALID)
	{
		return pxData->m_iData;
	}
	else
	{
		Asura_Assertf(0,("Variable %s isn't listed as an integer in Tools_GUIMenu_PreviewOverlay",szVarName));
		return 0;
	}
}

float Tools_GUIMenu_PreviewOverlay::GetFloatValue(const char* szVarName)
{
	const Tools_GUIMenu_ConsoleData* pxData = GetConsoleVarData(szVarName);
	
	Asura_Assertf(pxData,("Failed to get data for console variable %s from Tools_GUIMenu_PreviewOverlay",szVarName));
	if(!pxData) return 0.0f;

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_FLOAT)
	{
		return pxData->m_fData;
	}
	else
	{
		Asura_Assertf(0,("Variable %s isn't listed as a float in Tools_GUIMenu_PreviewOverlay",szVarName));
		return 0.0f;
	}
}

const Asura_UnicodeChar* Tools_GUIMenu_PreviewOverlay::GetUnicodeStringValue( const char* szVarName )
{
	Tools_GUIMenu_ConsoleData* pxData = GetConsoleVarData(szVarName);
	
	Asura_Assertf(pxData,("Failed to get data for console variable %s from Tools_GUIMenu_PreviewOverlay",szVarName));
	if(!pxData) return L"";

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_STRING)
	{
		pxData->UpdateUnicodeString();
		return pxData->m_wszData;
	}
	else
	{
		Asura_Assertf(0,("Variable %s isn't listed as a string in Tools_GUIMenu_PreviewOverlay",szVarName));
		return L"";
	}
}

bool Tools_GUIMenu_PreviewOverlay::SetBoolValue(const char* szVarName,bool bValue)
{
	Tools_GUIMenu_ConsoleData* pxData = GetConsoleVarData(szVarName);
	
	Asura_Assertf(pxData,("Failed to get data for console variable %s from Tools_GUIMenu_PreviewOverlay",szVarName));
	if(!pxData) return false;

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_BOOL)
	{
		pxData->m_bData = bValue;
		return true;
	}
	else
	{
		Asura_Assertf(0,("Variable %s isn't listed as a bool in Tools_GUIMenu_PreviewOverlay",szVarName));
		return false;
	}
}

bool Tools_GUIMenu_PreviewOverlay::SetIntValue(const char* szVarName,int iValue)
{
	Tools_GUIMenu_ConsoleData* pxData = GetConsoleVarData(szVarName);
	
	Asura_Assertf(pxData,("Failed to get data for console variable %s from Tools_GUIMenu_PreviewOverlay",szVarName));
	if(!pxData) return false;

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_INT || pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_INVALID)
	{
		pxData->m_iData = iValue;
		return true;
	}
	else
	{
		Asura_Assertf(0,("Variable %s isn't listed as an integer in Tools_GUIMenu_PreviewOverlay",szVarName));
		return false;
	}
}

bool Tools_GUIMenu_PreviewOverlay::SetFloatValue(const char* szVarName,float fValue)
{
	Tools_GUIMenu_ConsoleData* pxData = GetConsoleVarData(szVarName);
	
	Asura_Assertf(pxData,("Failed to get data for console variable %s from Tools_GUIMenu_PreviewOverlay",szVarName));
	if(!pxData) return false;

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_FLOAT)
	{
		pxData->m_fData = fValue;
		return true;
	}
	else
	{
		Asura_Assertf(0,("Variable %s isn't listed as a float in Tools_GUIMenu_PreviewOverlay",szVarName));
		return false;
	}
}

bool Tools_GUIMenu_PreviewOverlay::SetUnicodeStringValue( const char* szVarName, const Asura_UnicodeChar* wszValue )
{
	Tools_GUIMenu_ConsoleData* pxData = GetConsoleVarData(szVarName);
	
	Asura_Assertf(pxData,("Failed to get data for console variable %s from Tools_GUIMenu_PreviewOverlay",szVarName));
	if(!pxData) return false;

	if(pxData->m_iType == Asura_CommandConsole_VarRepository::Var::TYPE_STRING)
	{
		char szTemp[100];
		Asura_PrintfToBfr(szTemp,"%S",sizeof(szTemp),true,wszValue);
		pxData->m_xString = szTemp;

		return true;
	}
	else
	{
		Asura_Assertf(0,("Variable %s isn't listed as a string in Tools_GUIMenu_PreviewOverlay",szVarName));
		return false;
	}
}


void Tools_GUIMenu_PreviewOverlay::NotifyAutoclick( const char* szWidgetName )
{
	s_uLastAutoclickTime = Asura_Timers::GetMSecsSinceStart();
	if (s_xLastAutoclick != szWidgetName)
	{
		s_xLastAutoclick = szWidgetName;
	}
}


//////////////////////////////////////////////////////////////////////////////////////////////
Tools_GUIMenu_ConsoleData::Tools_GUIMenu_ConsoleData()
{
	m_iType = Asura_CommandConsole_VarRepository::Var::TYPE_INVALID;
	m_iData = 0;
	m_pxVar = 0;
	m_xString = "";
	m_wszData = 0;
	m_bCmd = false;
}

Tools_GUIMenu_ConsoleData::~Tools_GUIMenu_ConsoleData()
{
	delete [] m_wszData;	
}

void Tools_GUIMenu_ConsoleData::UpdateUnicodeString()
{
	delete [] m_wszData;
	m_wszData = 0;

	m_wszData = new Asura_UnicodeChar[m_xString.GetLength()+1];
	Asura_PrintfToBfr(m_wszData,L"%S",m_xString.GetLength()+1,true,m_xString.GetString());
}


#endif // ASURA_USE_GUI_MENU_SYSTEM




