//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements all the functions exported by the GameUI dll
//
// $NoKeywords: $
//===========================================================================//


#include "client_pch.h"

#include "tier0/platform.h"

#ifdef IS_WINDOWS_PC
#include "winlite.h"
#endif
#include "appframework/ilaunchermgr.h"
#include <vgui_controls/Panel.h>
#include <vgui_controls/EditablePanel.h>
#include <matsys_controls/matsyscontrols.h>
#include <vgui/Cursor.h>
#include <vgui_controls/PHandle.h>
#include "keys.h"
#include "console.h"
#include "gl_matsysiface.h"
#include "cdll_engine_int.h"
#include "demo.h"
#include "sys_dll.h"
#include "sound.h"
#include "soundflags.h"
#include "filesystem_engine.h"
#include "igame.h"
#include "con_nprint.h"
#include "vgui_DebugSystemPanel.h"
#include "tier0/vprof.h"
#include "cl_demoactionmanager.h"
#include "enginebugreporter.h"
#include "engineperftools.h"
#include "icolorcorrectiontools.h"
#include "tier0/icommandline.h"
#include "client.h"
#include "server.h"
#include "sys.h" // Sys_GetRegKeyValue()
#include "vgui_drawtreepanel.h"
#include "vgui_vprofpanel.h"
#include "vgui/VGUI.h"
#include "vgui/IInput.h"
#include <vgui/IInputInternal.h>
#include "vgui_controls/AnimationController.h"
#include "vgui_vprofgraphpanel.h"
#include "vgui_texturebudgetpanel.h"
#include "vgui_budgetpanel.h"
#include "ivideomode.h"
#include "sourcevr/isourcevirtualreality.h"
#include "cl_pluginhelpers.h"
#include "cl_main.h" // CL_IsHL2Demo()
#include "cl_steamauth.h"

// interface to gameui dll
#include <GameUI/IGameUI.h>
#include <GameUI/IGameConsole.h>

// interface to expose vgui root panels
#include <ienginevgui.h>
#include "VGuiMatSurface/IMatSystemSurface.h"

#include "cl_texturelistpanel.h"
#include "cl_demouipanel.h"
#include "cl_foguipanel.h"
#include "cl_txviewpanel.h"

// vgui2 interface
// note that GameUI project uses ..\public\vgui and ..\public\vgui_controls, not ..\utils\vgui\include
#include <vgui/VGUI.h>
#include <vgui/Cursor.h>
#include <KeyValues.h>
#include <vgui/ILocalize.h>
#include <vgui/IPanel.h>
#include <vgui/IScheme.h>
#include <vgui/IVGui.h>
#include <vgui/ISystem.h>
#include <vgui/ISurface.h>
#include <vgui_controls/EditablePanel.h>

#include <vgui_controls/MenuButton.h>
#include <vgui_controls/Menu.h>
#include <vgui_controls/PHandle.h>

#include "IVguiModule.h"
#include "vgui_baseui_interface.h"
#include "vgui_DebugSystemPanel.h"
#include "toolframework/itoolframework.h"
#include "filesystem/IQueuedLoader.h"

#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif

#include "vgui_askconnectpanel.h"

#if defined( REPLAY_ENABLED )
#include "replay_internal.h"
#endif

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

#ifndef USE_SDL
extern HWND *pmainwindow;
#endif

extern IVEngineClient *engineClient;
extern bool g_bTextMode;
static int g_syncReportLevel = -1;

void VGui_ActivateMouse();

extern CreateInterfaceFn g_AppSystemFactory;

// functions to reference GameUI and GameConsole functions, from GameUI.dll
IGameUI *staticGameUIFuncs = NULL;
IGameConsole *staticGameConsole = NULL;

// cache some of the state we pass through to matsystemsurface, for visibility
bool s_bWindowsInputEnabled = true;

ConVar r_drawvgui( "r_drawvgui", "1", FCVAR_CHEAT, "Enable the rendering of vgui panels" );
ConVar gameui_xbox( "gameui_xbox", "0", 0 );

void Con_CreateConsolePanel( vgui::Panel *parent );
void CL_CreateEntityReportPanel( vgui::Panel *parent );
void ClearIOStates( void );

// turn this on if you're tuning progress bars
//#define ENABLE_LOADING_PROGRESS_PROFILING

//-----------------------------------------------------------------------------
// Purpose: Console command to hide the gameUI, most commonly called from gameUI.dll
//-----------------------------------------------------------------------------
CON_COMMAND( gameui_hide, "Hides the game UI" )
{
	EngineVGui()->HideGameUI();
}

//-----------------------------------------------------------------------------
// Purpose: Console command to activate the gameUI, most commonly called from gameUI.dll
//-----------------------------------------------------------------------------
CON_COMMAND( gameui_activate, "Shows the game UI" )
{
	EngineVGui()->ActivateGameUI();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CON_COMMAND( gameui_preventescape, "Escape key doesn't hide game UI" )
{
	EngineVGui()->SetNotAllowedToHideGameUI( true );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CON_COMMAND( gameui_allowescapetoshow, "Escape key allowed to show game UI" )
{
	EngineVGui()->SetNotAllowedToShowGameUI( false );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CON_COMMAND( gameui_preventescapetoshow, "Escape key doesn't show game UI" )
{
	EngineVGui()->SetNotAllowedToShowGameUI( true );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CON_COMMAND( gameui_allowescape, "Escape key allowed to hide game UI" )
{
	EngineVGui()->SetNotAllowedToHideGameUI( false );
}

//-----------------------------------------------------------------------------
// Purpose: Console command to enable progress bar for next load
//-----------------------------------------------------------------------------
void BaseUI_ProgressEnabled_f()
{
	EngineVGui()->EnabledProgressBarForNextLoad();
}
static ConCommand progress_enable("progress_enable", &BaseUI_ProgressEnabled_f );

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
class CEnginePanel : public vgui::EditablePanel
{
	typedef vgui::EditablePanel BaseClass;
public:
	CEnginePanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
	{
		//m_bCanFocus = true;
		SetMouseInputEnabled( true );
		SetKeyBoardInputEnabled( true );
	}

	void EnableMouseFocus( bool state )
	{
		//m_bCanFocus = state;
		SetMouseInputEnabled( state );
		SetKeyBoardInputEnabled( state );
	}

/*	virtual vgui::VPANEL IsWithinTraverse(int x, int y, bool traversePopups)
	{
		if ( !m_bCanFocus )
			return NULL;

		vgui::VPANEL retval = BaseClass::IsWithinTraverse( x, y, traversePopups );
		if ( retval == GetVPanel() )
			return NULL;
		return retval;
	}*/

//private:
//	bool		m_bCanFocus;
};


//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
class CStaticPanel : public vgui::Panel
{
	typedef vgui::Panel BaseClass;

public:
	CStaticPanel( vgui::Panel *pParent, const char *pName ) : vgui::Panel( pParent, pName )
	{
		SetCursor( vgui::dc_none );
		SetKeyBoardInputEnabled( false );
		SetMouseInputEnabled( false );
	}
};

vgui::VPanelHandle g_DrawTreeSelectedPanel;

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
class CFocusOverlayPanel : public vgui::Panel
{
	typedef vgui::Panel BaseClass;

public:
	CFocusOverlayPanel( vgui::Panel *pParent, const char *pName );

	virtual void PostChildPaint( void );
	static void GetColorForSlot( int slot, int& r, int& g, int& b )
	{
		r = (int)( 124.0 + slot * 47.3 ) & 255;
		g = (int)( 63.78 - slot * 71.4 ) & 255;
		b = (int)( 188.42 + slot * 13.57 ) & 255;
	}

	bool DrawTitleSafeOverlay( void );
	bool DrawFocusPanelList( void );
};

//-----------------------------------------------------------------------------
//
// Purpose: Centerpoint for handling all user interface in the engine
//
//-----------------------------------------------------------------------------
class CEngineVGui : public IEngineVGuiInternal
{
public:
	CEngineVGui();
	~CEngineVGui();

	// Methods of IEngineVGui
	virtual vgui::VPANEL GetPanel( VGuiPanel_t type );

	// Methods of IEngineVGuiInternal
	virtual void Init();
	virtual void Connect();
	virtual void Shutdown();
	virtual bool SetVGUIDirectories();
	virtual bool IsInitialized() const;
	virtual bool Key_Event( const InputEvent_t &event );
	virtual void UpdateButtonState( const InputEvent_t &event );
	virtual void BackwardCompatibility_Paint();
	virtual void Paint( PaintMode_t mode );
	virtual void PostInit();

	CreateInterfaceFn GetGameUIFactory()
	{
		return m_GameUIFactory;
	}
	
	// handlers for game UI (main menu)
	virtual void ActivateGameUI();
	virtual bool HideGameUI();
	virtual bool IsGameUIVisible();

	// console
	virtual void ShowConsole();
	virtual void HideConsole();
	virtual bool IsConsoleVisible();
	virtual void ClearConsole();

	// level loading
	virtual void OnLevelLoadingStarted();
	virtual void OnLevelLoadingFinished();
	virtual void NotifyOfServerConnect(const char *game, int IP, int connectionPort, int queryPort);
	virtual void NotifyOfServerDisconnect();
	virtual void UpdateProgressBar(LevelLoadingProgress_e progress);
	virtual void UpdateCustomProgressBar( float progress, const wchar_t *desc );
	virtual void StartCustomProgress();
	virtual void FinishCustomProgress();

	virtual void EnabledProgressBarForNextLoad()
	{
		m_bShowProgressDialog = true;
	}

	// Should pause?
	virtual bool ShouldPause();
	virtual void ShowErrorMessage();

	virtual void SetNotAllowedToHideGameUI( bool bNotAllowedToHide )
	{
		m_bNotAllowedToHideGameUI = bNotAllowedToHide;
	}

	virtual void SetNotAllowedToShowGameUI( bool bNotAllowedToShow )
	{
		m_bNotAllowedToShowGameUI = bNotAllowedToShow;
	}

	void SetGameDLLPanelsVisible( bool show )
	{
		if ( !staticGameDLLPanel )
		{
			return;
		}

		staticGameDLLPanel->SetVisible( show );
	}

	virtual void ShowNewGameDialog( int chapter = -1 ); // -1 means just keep the currently select chapter

	// Xbox 360
	virtual void SessionNotification( const int notification, const int param = 0 );
	virtual void SystemNotification( const int notification );
	virtual void ShowMessageDialog( const uint nType, vgui::Panel *pOwner = NULL );
	virtual void UpdatePlayerInfo( uint64 nPlayerId, const char *pName, int nTeam, byte cVoiceState, int nPlayersNeeded, bool bHost );
	virtual void SessionSearchResult( int searchIdx, void *pHostData, XSESSION_SEARCHRESULT *pResult, int ping );
	virtual void OnCreditsFinished( void );

	// Storage device validation:
	//		returns true right away if storage device has been previously selected.
	//		otherwise returns false and will set the variable pointed by pStorageDeviceValidated to 1
	//				  once the storage device is selected by user.
	virtual bool ValidateStorageDevice( int *pStorageDeviceValidated );

	void SetProgressBias( float bias );
	void UpdateProgressBar( float progress );

	virtual void ConfirmQuit( void );

private:
	vgui::Panel *GetRootPanel( VGuiPanel_t type );
	void SetEngineVisible( bool state );
	void DrawMouseFocus( void );
	void CreateVProfPanels( vgui::Panel *pParent );
	void DestroyVProfPanels( );

	virtual void Simulate();

	// debug overlays
	bool IsDebugSystemVisible();
	void HideDebugSystem();

	bool IsShiftKeyDown();
	bool IsAltKeyDown();
	bool IsCtrlKeyDown();

	CON_COMMAND_MEMBER_F( CEngineVGui, "debugsystemui", ToggleDebugSystemUI, "Show/hide the debug system UI.", FCVAR_CHEAT );

private:
	enum { MAX_NUM_FACTORIES = 5 };
	CreateInterfaceFn m_FactoryList[MAX_NUM_FACTORIES];
	int m_iNumFactories;

	CSysModule *m_hStaticGameUIModule;
	CreateInterfaceFn m_GameUIFactory;

	// top level VGUI2 panel
	CStaticPanel *staticPanel;

	// base level panels for other subsystems, rooted on staticPanel
	CEnginePanel *staticClientDLLPanel;
	CEnginePanel *staticClientDLLToolsPanel;
	CEnginePanel *staticGameUIPanel;
	CEnginePanel *staticGameDLLPanel;

	// Want engine tools to be on top of other engine panels
	CEnginePanel *staticEngineToolsPanel;
	CDebugSystemPanel *staticDebugSystemPanel;
	CFocusOverlayPanel *staticFocusOverlayPanel;

#ifdef VPROF_ENABLED
	CVProfPanel *m_pVProfPanel;
	CBudgetPanelEngine *m_pBudgetPanel;
	CTextureBudgetPanel *m_pTextureBudgetPanel;
#endif

	// progress bar
	bool m_bShowProgressDialog;
	LevelLoadingProgress_e m_eLastProgressPoint;

	// progress bar debugging
	int m_nLastProgressPointRepeatCount;
	double m_flLoadingStartTime;
	struct LoadingProgressEntry_t
	{
		double flTime;
		LevelLoadingProgress_e eProgress;
	};
	CUtlVector<LoadingProgressEntry_t> m_LoadingProgress;

	bool					m_bSaveProgress : 1;
	bool					m_bNoShaderAPI : 1;
	// game ui hiding control
	bool					m_bNotAllowedToHideGameUI : 1;
	bool					m_bNotAllowedToShowGameUI : 1;

	vgui::IInputInternal *m_pInputInternal;

	// used to start the progress from an arbitrary position
	float					m_ProgressBias;
};


//-----------------------------------------------------------------------------
// Purpose: singleton accessor
//-----------------------------------------------------------------------------
static CEngineVGui g_EngineVGuiImp;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineVGui, IEngineVGui, VENGINE_VGUI_VERSION, g_EngineVGuiImp );

IEngineVGuiInternal *EngineVGui()
{
	return &g_EngineVGuiImp;
}

//-----------------------------------------------------------------------------
// The loader progress is updated by the queued loader. It uses an initial
// reserved portion of the bar.
//-----------------------------------------------------------------------------
#define PROGRESS_RESERVE 0.50f
class CLoaderProgress : public ILoaderProgress
{
public:
	CLoaderProgress()
	{ 
		// initialize to disabled state
		m_SnappedProgress = -1;
	}

	void BeginProgress()
	{
		g_EngineVGuiImp.SetProgressBias( 0 );
		m_SnappedProgress = 0;
	}

	void UpdateProgress( float progress )
	{
		if ( m_SnappedProgress == - 1 )
		{
			// not enabled
			return;
		}	

		int snappedProgress = progress * 15;

		// Need excessive updates on the 360 to keep the XBox slider inny bar active
		if ( !IsX360() && ( snappedProgress <= m_SnappedProgress ) )
		{
			// prevent excessive updates
			return;
		}
		m_SnappedProgress = snappedProgress;

		// up to reserved
		g_EngineVGuiImp.UpdateProgressBar( PROGRESS_RESERVE * progress );
	}

	void EndProgress()
	{
		// the normal legacy bar now picks up after reserved region
		g_EngineVGuiImp.SetProgressBias( PROGRESS_RESERVE );
		m_SnappedProgress = -1;
	}

private:
	int m_SnappedProgress;
};
static CLoaderProgress s_LoaderProgress;

	
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CEngineVGui::CEngineVGui()
{
	staticPanel = NULL;
	staticClientDLLToolsPanel = NULL;
	staticClientDLLPanel = NULL;
	staticGameDLLPanel = NULL;
	staticGameUIPanel = NULL;
	staticEngineToolsPanel = NULL;
	staticDebugSystemPanel = NULL;
	staticFocusOverlayPanel = NULL;

	m_hStaticGameUIModule = NULL;
	m_GameUIFactory = NULL;

#ifdef VPROF_ENABLED
	m_pVProfPanel = NULL;
#endif

	m_bShowProgressDialog = false;
	m_bSaveProgress = false;
	m_bNoShaderAPI = false;
	m_bNotAllowedToHideGameUI = false;
	m_bNotAllowedToShowGameUI = false;
	m_pInputInternal = NULL;
	m_ProgressBias = 0;
}


//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CEngineVGui::~CEngineVGui()
{
}


//-----------------------------------------------------------------------------
// add all the base search paths used by VGUI (platform, skins directory, language dirs)
//-----------------------------------------------------------------------------
bool CEngineVGui::SetVGUIDirectories()
{
	// Legacy, not supported anymore
	return true;
}

//-----------------------------------------------------------------------------
// Setup the base vgui panels
//-----------------------------------------------------------------------------
void CEngineVGui::Init()
{
	COM_TimestampedLog( "Loading gameui.dll" );

	// load the GameUI dll
	const char *szDllName = "GameUI";
	m_hStaticGameUIModule = g_pFileSystem->LoadModule(szDllName, "EXECUTABLE_PATH", true); // LoadModule() does a GetLocalCopy() call
	m_GameUIFactory = Sys_GetFactory(m_hStaticGameUIModule);
	if ( !m_GameUIFactory )
	{
		Error( "Could not load: %s\n", szDllName );
	}
	
	// get the initialization func
	staticGameUIFuncs = (IGameUI *)m_GameUIFactory(GAMEUI_INTERFACE_VERSION, NULL);
	if (!staticGameUIFuncs )
	{
		Error( "Could not get IGameUI interface %s from %s\n", GAMEUI_INTERFACE_VERSION, szDllName );
	}

	if ( IsPC() )
	{
		staticGameConsole = (IGameConsole *)m_GameUIFactory(GAMECONSOLE_INTERFACE_VERSION, NULL);
		if ( !staticGameConsole )
		{
			Sys_Error( "Could not get IGameConsole interface %s from %s\n", GAMECONSOLE_INTERFACE_VERSION, szDllName );
		}
	}

	vgui::VGui_InitMatSysInterfacesList( "BaseUI", &g_AppSystemFactory, 1 );

	// Get our langauge string
	char lang[ 64 ];
	lang[0] = 0;
	engineClient->GetUILanguage( lang, sizeof( lang ) );
	if ( lang[0] )
		vgui::system()->SetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Source\\Language", lang );

	COM_TimestampedLog( "AttachToWindow" );

	// Need to be able to play sounds through vgui
	g_pMatSystemSurface->InstallPlaySoundFunc( VGui_PlaySound );

	COM_TimestampedLog( "Load Scheme File" );

	// load scheme
	const char *pStr = "Resource/SourceScheme.res";
	if ( !vgui::scheme()->LoadSchemeFromFile( pStr, "Tracker" ))
	{
		Sys_Error( "Error loading file %s\n", pStr );
		return;
	}

	if ( IsX360() || IsSteamDeck() )
	{
		CCommand ccommand;
		if ( CL_ShouldLoadBackgroundLevel( ccommand ) )
		{
			// Must be before the game ui base panel starts up
			// This is a hint to avoid the menu pop due to the impending background map
			// that the game ui is not aware of until 1 frame later.
			staticGameUIFuncs->SetProgressOnStart();
		}
	}

	COM_TimestampedLog( "vgui::ivgui()->Start()" );

	// Start the App running
	vgui::ivgui()->Start();
	vgui::ivgui()->SetSleep(false);

	// setup base panel for the whole VGUI System
	// The root panel for everything ( NULL parent makes it a child of the embedded panel )

	// Ideal hierarchy:

	COM_TimestampedLog( "Building Panels (staticPanel)" );

	// Root -- staticPanel
	//		staticBackgroundImagePanel (from gamui) zpos == 0
	//      staticClientDLLPanel ( zpos == 25 )
	//		staticClientDLLToolsPanel ( zpos == 28
	//		staticGameDLLPanel ( zpos == 30 )
	//		staticEngineToolsPanel ( zpos == 75 )
	//		staticGameUIPanel ( GameUI stuff ) ( zpos == 100 )
	//		staticDebugSystemPanel ( Engine debug stuff ) zpos == 125 )

	staticPanel = new CStaticPanel( NULL, "staticPanel" );	
	staticPanel->SetBounds( 0, 0, videomode->GetModeUIWidth(), videomode->GetModeUIHeight() );
	staticPanel->SetPaintBorderEnabled(false);
	staticPanel->SetPaintBackgroundEnabled(false);
	staticPanel->SetPaintEnabled(false);
	staticPanel->SetVisible(true);
	staticPanel->SetCursor( vgui::dc_none );
	staticPanel->SetZPos(0);
	staticPanel->SetVisible(true);
	staticPanel->SetParent( vgui::surface()->GetEmbeddedPanel() );

	COM_TimestampedLog( "Building Panels (staticClientDLLPanel)" );

	staticClientDLLPanel = new CEnginePanel( staticPanel, "staticClientDLLPanel" );
	staticClientDLLPanel->SetBounds( 0, 0, videomode->GetModeUIWidth(), videomode->GetModeUIHeight() );
	staticClientDLLPanel->SetPaintBorderEnabled(false);
	staticClientDLLPanel->SetPaintBackgroundEnabled(false);
	staticClientDLLPanel->SetKeyBoardInputEnabled( false );	// popups in the client DLL can enable this.
	staticClientDLLPanel->SetPaintEnabled(false);
	staticClientDLLPanel->SetVisible( false );
	staticClientDLLPanel->SetCursor( vgui::dc_none );
	staticClientDLLPanel->SetZPos( 25 );

	CreateAskConnectPanel( staticPanel->GetVPanel() );

	COM_TimestampedLog( "Building Panels (staticClientDLLToolsPanel)" );

	staticClientDLLToolsPanel = new CEnginePanel( staticPanel, "staticClientDLLToolsPanel" );
	staticClientDLLToolsPanel->SetBounds( 0, 0, videomode->GetModeUIWidth(), videomode->GetModeUIHeight() );
	staticClientDLLToolsPanel->SetPaintBorderEnabled(false);
	staticClientDLLToolsPanel->SetPaintBackgroundEnabled(false);
	staticClientDLLToolsPanel->SetKeyBoardInputEnabled( false );	// popups in the client DLL can enable this.
	staticClientDLLToolsPanel->SetPaintEnabled(false);
	staticClientDLLToolsPanel->SetVisible( true );
	staticClientDLLToolsPanel->SetCursor( vgui::dc_none );
	staticClientDLLToolsPanel->SetZPos( 28 );

	staticEngineToolsPanel = new CEnginePanel( staticPanel, "Engine Tools" );
	staticEngineToolsPanel->SetBounds( 0, 0, videomode->GetModeUIWidth(), videomode->GetModeUIHeight() );
	staticEngineToolsPanel->SetPaintBorderEnabled(false);
	staticEngineToolsPanel->SetPaintBackgroundEnabled(false);
	staticEngineToolsPanel->SetPaintEnabled(false);
	staticEngineToolsPanel->SetVisible( true );
	staticEngineToolsPanel->SetCursor( vgui::dc_none );
	staticEngineToolsPanel->SetZPos( 75 );

	COM_TimestampedLog( "Building Panels (staticGameUIPanel)" );

	staticGameUIPanel = new CEnginePanel( staticPanel, "GameUI Panel" );

	if(NeedProportional())
		staticGameUIPanel->SetProportional(true);

	staticGameUIPanel->SetBounds( 0, 0, videomode->GetModeUIWidth(), videomode->GetModeUIHeight() );
	staticGameUIPanel->SetPaintBorderEnabled(false);
	staticGameUIPanel->SetPaintBackgroundEnabled(false);
	staticGameUIPanel->SetPaintEnabled(false);
	staticGameUIPanel->SetVisible( true );
	staticGameUIPanel->SetCursor( vgui::dc_none );
	staticGameUIPanel->SetZPos( 100 );

	staticGameDLLPanel = new CEnginePanel( staticPanel, "staticGameDLLPanel" );
	staticGameDLLPanel->SetBounds( 0, 0, videomode->GetModeUIWidth(), videomode->GetModeUIHeight() );
	staticGameDLLPanel->SetPaintBorderEnabled(false);
	staticGameDLLPanel->SetPaintBackgroundEnabled(false);
	staticGameDLLPanel->SetKeyBoardInputEnabled( false );	// popups in the game DLL can enable this.
	staticGameDLLPanel->SetPaintEnabled(false);
	staticGameDLLPanel->SetCursor( vgui::dc_none );
	staticGameDLLPanel->SetZPos( 135 );

	if ( CommandLine()->CheckParm( "-tools" ) != NULL )
	{
		staticGameDLLPanel->SetVisible( true );
	}
	else
	{
		staticGameDLLPanel->SetVisible( false );
	}

	if ( IsPC() )
	{
		COM_TimestampedLog( "Building Panels (staticDebugSystemPanel)" );

		staticDebugSystemPanel = new CDebugSystemPanel( staticPanel, "Engine Debug System" );
		staticDebugSystemPanel->SetZPos( 125 );

		// Install demo playback/editing UI
		CDemoUIPanel::InstallDemoUI( staticEngineToolsPanel );
		CDemoUIPanel2::Install( staticClientDLLPanel, staticEngineToolsPanel, true );

		// Install fog control panel UI
		CFogUIPanel::InstallFogUI( staticEngineToolsPanel );

		// Install texture view panel
		TxViewPanel::Install( staticEngineToolsPanel );

		COM_TimestampedLog( "Install bug reporter" );

		// Create and initialize bug reporting system
		bugreporter->InstallBugReportingUI( staticGameUIPanel, IEngineBugReporter::BR_AUTOSELECT );
		bugreporter->Init();

		COM_TimestampedLog( "Install perf tools" );

		// Create a performance toolkit system
		perftools->InstallPerformanceToolsUI( staticEngineToolsPanel );
		perftools->Init();

		// Create a color correction UI
		colorcorrectiontools->InstallColorCorrectionUI( staticEngineToolsPanel );
		colorcorrectiontools->Init();
	}

	// Make sure this is on top of everything
	staticFocusOverlayPanel = new CFocusOverlayPanel( staticPanel, "FocusOverlayPanel" );
	staticFocusOverlayPanel->SetBounds( 0, 0, videomode->GetModeUIWidth(), videomode->GetModeUIHeight() );
	staticFocusOverlayPanel->SetZPos( 150 );
	staticFocusOverlayPanel->MoveToFront();

	// Create engine vgui panels
	if ( IsPC() )
	{
		Con_CreateConsolePanel( staticEngineToolsPanel );
		CL_CreateEntityReportPanel( staticEngineToolsPanel );
		VGui_CreateDrawTreePanel( staticEngineToolsPanel );
		CL_CreateTextureListPanel( staticEngineToolsPanel );
		CreateVProfPanels( staticEngineToolsPanel );
	}
	staticEngineToolsPanel->LoadControlSettings( "scripts/EngineVGuiLayout.res" );

	COM_TimestampedLog( "materials->CacheUsedMaterials()" );

	// Make sure that these materials are in the materials cache
	materials->CacheUsedMaterials();

	COM_TimestampedLog( "g_pVGuiLocalize->AddFile" );

	// load the base localization file
	g_pVGuiLocalize->AddFile( "Resource/valve_%language%.txt" );

	COM_TimestampedLog( "staticGameUIFuncs->Initialize" );

	staticGameUIFuncs->Initialize( g_AppSystemFactory );

	COM_TimestampedLog( "staticGameUIFuncs->Start" );
	staticGameUIFuncs->Start();

	// don't need to load the "valve" localization file twice
	// Each mod acn have its own language.txt in addition to the valve_%%langauge%%.txt file under defaultgamedir.
	// load mod-specific localization file for kb_act.lst, user.scr, settings.scr, etc.
	char szFileName[MAX_PATH];
	Q_snprintf( szFileName, sizeof( szFileName ) - 1, "resource/%s_%%language%%.txt", GetCurrentMod() );
	szFileName[ sizeof( szFileName ) - 1 ] = '\0';
	g_pVGuiLocalize->AddFile( szFileName );

	// setup console
	if ( staticGameConsole )
	{
		staticGameConsole->Initialize();
		staticGameConsole->SetParent(staticGameUIPanel->GetVPanel());
	}

	if ( IsX360() )
	{
		// provide an interface for loader to send progress notifications
		g_pQueuedLoader->InstallProgress( &s_LoaderProgress ); 
	}

	// show the game UI
	COM_TimestampedLog( "ActivateGameUI()" );
	ActivateGameUI();

	if ( staticGameConsole && 
		!CommandLine()->CheckParm( "-forcestartupmenu" ) && 
		!CommandLine()->CheckParm( "-hideconsole" ) &&
		( CommandLine()->FindParm( "-toconsole" ) || CommandLine()->FindParm( "-console" ) || CommandLine()->FindParm( "-rpt" ) || CommandLine()->FindParm( "-allowdebug" ) ) )
	{
		// activate the console
		staticGameConsole->Activate();
	}

	m_bNoShaderAPI = CommandLine()->FindParm( "-noshaderapi" );
}

void CEngineVGui::PostInit()
{
	staticGameUIFuncs->PostInit();
#if defined( _X360 )
	g_pMatSystemSurface->ClearTemporaryFontCache();
#endif
}

//-----------------------------------------------------------------------------
// Purpose: connects interfaces in gameui
//-----------------------------------------------------------------------------
void CEngineVGui::Connect()
{
	m_pInputInternal = (vgui::IInputInternal *)g_GameSystemFactory( VGUI_INPUTINTERNAL_INTERFACE_VERSION,  NULL );
	staticGameUIFuncs->Connect( g_GameSystemFactory );

}

//-----------------------------------------------------------------------------
// Create/destroy the vprof panels
//-----------------------------------------------------------------------------
void CEngineVGui::CreateVProfPanels( vgui::Panel *pParent )
{
	if ( IsX360() )
		return;

#ifdef VPROF_ENABLED
	m_pVProfPanel = new CVProfPanel( pParent, "VProfPanel" );
	m_pBudgetPanel = new CBudgetPanelEngine( pParent, "BudgetPanel" );
	CreateVProfGraphPanel( pParent );
	m_pTextureBudgetPanel = new CTextureBudgetPanel( pParent, "TextureBudgetPanel" );
#endif
}

void CEngineVGui::DestroyVProfPanels( )
{
	if ( IsX360() )
		return;

#ifdef VPROF_ENABLED
	if ( m_pVProfPanel )
	{
		delete m_pVProfPanel;
		m_pVProfPanel = NULL;
	}
	if ( m_pBudgetPanel )
	{
		delete m_pBudgetPanel;
		m_pBudgetPanel = NULL;
	}
	DestroyVProfGraphPanel();

	if ( m_pTextureBudgetPanel )
	{
		delete m_pTextureBudgetPanel;
		m_pTextureBudgetPanel = NULL;
	}
#endif
}


//-----------------------------------------------------------------------------
// Are we initialized?
//-----------------------------------------------------------------------------
bool CEngineVGui::IsInitialized() const
{
	return staticPanel != NULL;
}

extern bool g_bUsingLegacyAppSystems;
//-----------------------------------------------------------------------------
// Purpose: Called to Shutdown the game UI system
//-----------------------------------------------------------------------------
void CEngineVGui::Shutdown()
{
	if ( IsPC() && CL_IsHL2Demo() ) // if they are playing the demo then open the storefront on shutdown
	{
		vgui::system()->ShellExecute("open", "steam://store_demo/220");
	}

	if ( IsPC() && CL_IsPortalDemo() ) // if they are playing the demo then open the storefront on shutdown
	{
		vgui::system()->ShellExecute("open", "steam://store_demo/400");
	}

	DestroyVProfPanels();
	bugreporter->Shutdown();
	colorcorrectiontools->Shutdown();
	perftools->Shutdown();

	demoaction->Shutdown();

	if ( g_PluginManager )
	{
		g_PluginManager->Shutdown();
	}

	// HACK HACK: There was a bug in the old versions of the viewport which would crash in the case where the client .dll hadn't been fully unloaded, so
	//  we'll leak this panel here instead!!!
	if ( g_bUsingLegacyAppSystems )
	{
		staticClientDLLPanel->SetParent( (vgui::VPANEL)0 );
	}

	// This will delete the engine subpanel since it's a child
	delete staticPanel;
	staticPanel = NULL;
	staticClientDLLToolsPanel = NULL;
	staticClientDLLPanel	= NULL;
	staticEngineToolsPanel = NULL;
	staticDebugSystemPanel = NULL;
	staticFocusOverlayPanel = NULL;
	staticGameDLLPanel = NULL;

	// Give panels a chance to settle so things
	//  Marked for deletion will actually get deleted
	vgui::ivgui()->RunFrame();

	// unload the gameUI
	staticGameUIFuncs->Shutdown();

	staticGameUIFuncs = NULL;
	staticGameConsole = NULL;
	staticGameUIPanel = NULL;

	// stop the App running
	vgui::ivgui()->Stop();
	
	// unload the dll
	Sys_UnloadModule(m_hStaticGameUIModule);
	m_hStaticGameUIModule = NULL;
	m_GameUIFactory = NULL;
	m_pInputInternal = NULL;
}


//-----------------------------------------------------------------------------
// Purpose: Retrieve specified root panel
//-----------------------------------------------------------------------------
inline vgui::Panel *CEngineVGui::GetRootPanel( VGuiPanel_t type )
{
	if ( sv.IsDedicated() )
	{
		return NULL;
	}

	switch ( type )
	{
	default:
	case PANEL_ROOT:
		return staticPanel;
	case PANEL_CLIENTDLL:
		return staticClientDLLPanel;
	case PANEL_GAMEUIDLL:
		return staticGameUIPanel;
	case PANEL_TOOLS:
		return staticEngineToolsPanel;
	case PANEL_GAMEDLL:
		return staticGameDLLPanel;
	case PANEL_CLIENTDLL_TOOLS:
		return staticClientDLLToolsPanel;
	}
}

vgui::VPANEL CEngineVGui::GetPanel( VGuiPanel_t type )
{
	return GetRootPanel( type )->GetVPanel();
}

//-----------------------------------------------------------------------------
// Purpose: Toggle engine panel active/inactive
//-----------------------------------------------------------------------------
void CEngineVGui::SetEngineVisible( bool state )
{
	if ( staticClientDLLPanel )
	{
		staticClientDLLPanel->SetVisible( state );
	}
}


//-----------------------------------------------------------------------------
// Should pause?
//-----------------------------------------------------------------------------
bool CEngineVGui::ShouldPause()
{
	if ( IsPC() )
	{
		return bugreporter->ShouldPause() || perftools->ShouldPause();
	}
	return false;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CEngineVGui::ConfirmQuit()
{
	ActivateGameUI();
	staticGameUIFuncs->OnConfirmQuit();
}
	
//-----------------------------------------------------------------------------
// Purpose: Shows any GameUI related panels
//-----------------------------------------------------------------------------
void CEngineVGui::ActivateGameUI()
{
	if ( m_bNotAllowedToShowGameUI )
		return;

	if (!staticGameUIFuncs)
		return;

#if defined( REPLAY_ENABLED )
	// Don't allow the game UI to be activated when a replay is being rendered
	if ( g_pReplayMovieManager && g_pReplayMovieManager->IsRendering() )
		return;
#endif

	// clear any keys that might be stuck down
	ClearIOStates();

	staticGameUIPanel->SetVisible(true);
	staticGameUIPanel->MoveToFront();	

	staticClientDLLPanel->SetVisible(false);
	staticClientDLLPanel->SetMouseInputEnabled(false);

	vgui::surface()->SetCursor( vgui::dc_arrow );

	//staticGameDLLPanel->SetVisible( true );
	//staticGameDLLPanel->SetMouseInputEnabled( true );

	SetEngineVisible( false );

	staticGameUIFuncs->OnGameUIActivated();
}

//-----------------------------------------------------------------------------
// Purpose: Hides an Game UI related features (not client UI stuff tho!)
//-----------------------------------------------------------------------------
bool CEngineVGui::HideGameUI()
{
	if ( m_bNotAllowedToHideGameUI )
		return false;

	const char *levelName = engineClient->GetLevelName();
	bool bInNonBgLevel = levelName && levelName[0] && !engineClient->IsLevelMainMenuBackground();
	if ( bInNonBgLevel )
	{
		staticGameUIPanel->SetVisible(false);
		staticGameUIPanel->SetPaintBackgroundEnabled(false);
	
		staticClientDLLPanel->SetVisible(true);
		staticClientDLLPanel->MoveToFront();
		staticClientDLLPanel->SetMouseInputEnabled(true);

		//staticGameDLLPanel->SetVisible( false );
		//staticGameDLLPanel->SetMouseInputEnabled(false);

		SetEngineVisible( true );

		staticGameUIFuncs->OnGameUIHidden();
	}
	else
	{
		// Tracker 18820:  Pulling up options/console was perma-pausing the background levels, now we
		//  unpause them when you hit the Esc key even though the UI remains...
		if ( levelName && 
			 levelName[0] && 
			 ( engineClient->GetMaxClients() <= 1 ) && 
			 engineClient->IsPaused() )
		{
			Cbuf_AddText("unpause\n");
		}
	}

	VGui_MoveDrawTreePanelToFront();

	return true;
}

//-----------------------------------------------------------------------------
// Purpose: Hides the game console (but not the complete GameUI!)
//-----------------------------------------------------------------------------
void CEngineVGui::HideConsole()
{
	if ( IsX360() )
		return;

	if ( staticGameConsole )
	{
		staticGameConsole->Hide();
	}
}

//-----------------------------------------------------------------------------
// Purpose: shows the console
//-----------------------------------------------------------------------------
void CEngineVGui::ShowConsole()
{
	if ( IsX360() )
		return;

	ActivateGameUI();

	if ( staticGameConsole )
	{
		staticGameConsole->Activate();
	}
}

//-----------------------------------------------------------------------------
// Purpose: returns true if the console is currently open
//-----------------------------------------------------------------------------
bool CEngineVGui::IsConsoleVisible()
{
	if ( IsPC() )
	{
		return IsGameUIVisible() && staticGameConsole && staticGameConsole->IsConsoleVisible();
	}
	else
	{
		// xbox has no drop down console
		return false;
	}
}

//-----------------------------------------------------------------------------
// Purpose: clears all text from the console
//-----------------------------------------------------------------------------
void CEngineVGui::ClearConsole()
{
	if ( staticGameConsole )
	{
		staticGameConsole->Clear();
	}
}

//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CEngineVGui::IsGameUIVisible() 
{
	return staticGameUIPanel && staticGameUIPanel->IsVisible();
}


// list of progress bar strings
struct LoadingProgressDescription_t
{
	LevelLoadingProgress_e eProgress;	// current progress
	int nPercent;						// % of the total time this is at
	int nRepeat;						// number of times this is expected to repeat (usually 0)
	const char *pszDesc;				// user description of progress
};

LoadingProgressDescription_t g_ListenServerLoadingProgressDescriptions[] =
{	
	{ PROGRESS_NONE,						0,		0,		NULL },
	{ PROGRESS_SPAWNSERVER,					2,		0,		"#LoadingProgress_SpawningServer" },
	{ PROGRESS_LOADWORLDMODEL,				4,		7,		"#LoadingProgress_LoadMap" },
	{ PROGRESS_CREATENETWORKSTRINGTABLES,	23,		0,		NULL },
	{ PROGRESS_PRECACHEWORLD,				23,		0,		"#LoadingProgress_PrecacheWorld" },
	{ PROGRESS_CLEARWORLD,					23,		0,		NULL },
	{ PROGRESS_LEVELINIT,					34,		0,		"#LoadingProgress_LoadResources" },
	{ PROGRESS_PRECACHE,					35,		239,	NULL },
	{ PROGRESS_ACTIVATESERVER,				68,		0,		NULL },
	{ PROGRESS_SIGNONCHALLENGE,				68,		0,		NULL },
	{ PROGRESS_SIGNONCONNECT,				70,		0,		NULL },
	{ PROGRESS_SIGNONCONNECTED,				73,		0,		"#LoadingProgress_SignonLocal" },
	{ PROGRESS_PROCESSSERVERINFO,			75,		0,		NULL },
	{ PROGRESS_PROCESSSTRINGTABLE,			77,		12,		NULL },	// 16
	{ PROGRESS_SIGNONNEW,					84,		0,		NULL },
	{ PROGRESS_SENDCLIENTINFO,				88,		0,		NULL },
	{ PROGRESS_SENDSIGNONDATA,				91,		0,		"#LoadingProgress_SignonDataLocal" },
	{ PROGRESS_SIGNONSPAWN,					94,		0,		NULL },
	{ PROGRESS_FULLYCONNECTED,				97,		0,		NULL },
	{ PROGRESS_READYTOPLAY,					99,		0,		NULL },
	{ PROGRESS_HIGHESTITEM,					100,	0,		NULL },
};

LoadingProgressDescription_t g_RemoteConnectLoadingProgressDescriptions[] =
{	
	{ PROGRESS_NONE,						0,		0,		NULL },
	{ PROGRESS_CHANGELEVEL,					1,		0,		"#LoadingProgress_Changelevel" },
	{ PROGRESS_BEGINCONNECT,				5,		0,		"#LoadingProgress_BeginConnect" },
	{ PROGRESS_SIGNONCHALLENGE,				10,		0,		"#LoadingProgress_Connecting" },
	{ PROGRESS_SIGNONCONNECTED,				15,		0,		NULL },
	{ PROGRESS_PROCESSSERVERINFO,			20,		0,		"#LoadingProgress_ProcessServerInfo" },
	{ PROGRESS_PROCESSSTRINGTABLE,			25,		11,		NULL },
	{ PROGRESS_LOADWORLDMODEL,				45,		7,		"#LoadingProgress_LoadMap" },
	{ PROGRESS_SIGNONNEW,					75,		0,		NULL },
	{ PROGRESS_SENDCLIENTINFO,				80,		0,		"#LoadingProgress_SendClientInfo" },
	{ PROGRESS_SENDSIGNONDATA,				85,		0,		"#LoadingProgress_SignonData" },
	{ PROGRESS_SIGNONSPAWN,					90,		0,		NULL },
	{ PROGRESS_FULLYCONNECTED,				95,		0,		NULL },
	{ PROGRESS_READYTOPLAY,					99,		0,		NULL },
	{ PROGRESS_HIGHESTITEM,					100,	0,		NULL },
};

static LoadingProgressDescription_t *g_pLoadingProgressDescriptions = NULL;

//-----------------------------------------------------------------------------
// Purpose: returns current progress point description
//-----------------------------------------------------------------------------
LoadingProgressDescription_t &GetProgressDescription(int eProgress)
{
	// search for the item in the current list
	int i = 0;
	while (g_pLoadingProgressDescriptions[i].eProgress != PROGRESS_HIGHESTITEM)
	{
		// find the closest match
		if (g_pLoadingProgressDescriptions[i].eProgress >= eProgress)
			return g_pLoadingProgressDescriptions[i];
	
		++i;
	}

	// not found
	return g_pLoadingProgressDescriptions[0];
}

//-----------------------------------------------------------------------------
// Purpose: transition handler
//-----------------------------------------------------------------------------
void CEngineVGui::OnLevelLoadingStarted()
{
	if (!staticGameUIFuncs)
		return;

	ConVar *pSyncReportConVar = g_pCVar->FindVar( "fs_report_sync_opens" );
	if ( pSyncReportConVar )
	{
		// If convar is set to 2, suppress warnings during level load
		g_syncReportLevel = pSyncReportConVar->GetInt();
		if ( g_syncReportLevel > 1 )
		{
			pSyncReportConVar->SetValue( 0 );
		}
	}
	
	if ( IsX360() || IsSteamDeck() )
	{
		// TCR requirement, always!!!
		m_bShowProgressDialog = true;
	}

	// we've starting loading a level/connecting to a server
	staticGameUIFuncs->OnLevelLoadingStarted( m_bShowProgressDialog );

	// reset progress bar timers
	m_flLoadingStartTime = Plat_FloatTime();
	m_LoadingProgress.RemoveAll();
	m_eLastProgressPoint = PROGRESS_NONE;
	m_nLastProgressPointRepeatCount = 0;
	m_ProgressBias = 0;

	// choose which progress bar to use
	if (NET_IsMultiplayer())
	{
		// we're connecting
		g_pLoadingProgressDescriptions = g_RemoteConnectLoadingProgressDescriptions;
	}
	else
	{
		g_pLoadingProgressDescriptions = g_ListenServerLoadingProgressDescriptions;
	}

	if ( m_bShowProgressDialog )
	{
		ActivateGameUI();
	}

	m_bShowProgressDialog = false;
}

//-----------------------------------------------------------------------------
// Purpose: transition handler
//-----------------------------------------------------------------------------
void CEngineVGui::OnLevelLoadingFinished()
{
	if (!staticGameUIFuncs)
		return;

	staticGameUIFuncs->OnLevelLoadingFinished( gfExtendedError, gszDisconnectReason, gszExtendedDisconnectReason );
	m_eLastProgressPoint = PROGRESS_NONE;

	// clear any error message
	gfExtendedError = false;
	gszDisconnectReason[0] = 0;
	gszExtendedDisconnectReason[0] = 0;

#if defined(ENABLE_LOADING_PROGRESS_PROFILING)
	// display progress bar stats (for debugging/tuning progress bar)
	float flEndTime = (float)Plat_FloatTime();
	// add a finished entry
	LoadingProgressEntry_t &entry = m_LoadingProgress[m_LoadingProgress.AddToTail()];
	entry.flTime = flEndTime - m_flLoadingStartTime;
	entry.eProgress = PROGRESS_HIGHESTITEM;
	// dump the info
	Msg("Level load timings:\n");
	float flTotalTime = flEndTime - m_flLoadingStartTime;
	int nRepeatCount = 0;
	float flTimeTaken = 0.0f;
	float flFirstLoadProgressTime = 0.0f;
	for (int i = 0; i < m_LoadingProgress.Count() - 1; i++)
	{
		// keep track of time
		flTimeTaken += (float)m_LoadingProgress[i+1].flTime - m_LoadingProgress[i].flTime;

		// keep track of how often something is repeated
		if (m_LoadingProgress[i+1].eProgress == m_LoadingProgress[i].eProgress)
		{
			if (nRepeatCount == 0)
			{
				flFirstLoadProgressTime = m_LoadingProgress[i].flTime;
			}
			++nRepeatCount;
			continue;
		}

		// work out the time it took to do this
		if (nRepeatCount == 0)
		{
			flFirstLoadProgressTime = m_LoadingProgress[i].flTime;
		}

		int nPerc = (int)(100 * (flFirstLoadProgressTime / flTotalTime));
		int nTickPerc = (int)(100 * ((float)m_LoadingProgress[i].eProgress / (float)PROGRESS_HIGHESTITEM));
		
		// interpolated percentage is in between the real times and the most ticks
		int nInterpPerc = (nPerc + nTickPerc) / 2;
		Msg("\t%d\t%.3f\t\ttime: %d%%\t\tinterp: %d%%\t\trepeat: %d\n", m_LoadingProgress[i].eProgress, flTimeTaken, nPerc, nInterpPerc, nRepeatCount);

		// reset accumlated vars
		nRepeatCount = 0;
		flTimeTaken = 0.0f;
	}
#endif // ENABLE_LOADING_PROGRESS_PROFILING

	HideGameUI();

	// Restore convar setting after level load
	if ( g_syncReportLevel > 1 )
	{
		ConVar *pSyncReportConVar = g_pCVar->FindVar( "fs_report_sync_opens" );
		if ( pSyncReportConVar )
		{
			pSyncReportConVar->SetValue( g_syncReportLevel );
		}
	}
}


//-----------------------------------------------------------------------------
// Purpose: transition handler
//-----------------------------------------------------------------------------
void CEngineVGui::ShowErrorMessage()
{
	if (!staticGameUIFuncs || !gfExtendedError)
		return;

	staticGameUIFuncs->OnLevelLoadingFinished( gfExtendedError, gszDisconnectReason, gszExtendedDisconnectReason );
	m_eLastProgressPoint = PROGRESS_NONE;

	// clear any error message
	gfExtendedError = false;
	gszDisconnectReason[0] = 0;
	gszExtendedDisconnectReason[0] = 0;

	HideGameUI();
}


//-----------------------------------------------------------------------------
// Purpose: Updates progress
//-----------------------------------------------------------------------------
void CEngineVGui::UpdateProgressBar(LevelLoadingProgress_e progress)
{
	if (!staticGameUIFuncs)
		return;

	if ( !ThreadInMainThread() )
		return;

#if defined(ENABLE_LOADING_PROGRESS_PROFILING)
	// track the progress times, for debugging & tuning
	LoadingProgressEntry_t &entry = m_LoadingProgress[m_LoadingProgress.AddToTail()];
	entry.flTime = Plat_FloatTime() - m_flLoadingStartTime;
	entry.eProgress = progress;
#endif

	if (!g_pLoadingProgressDescriptions)
		return;

	// don't go backwards
	if (progress < m_eLastProgressPoint)
		return;

	// count progress repeats
	if (progress == m_eLastProgressPoint)
	{
		++m_nLastProgressPointRepeatCount;
	}
	else
	{
		m_nLastProgressPointRepeatCount = 0;
	}

	// construct a string describing it
	LoadingProgressDescription_t &desc = GetProgressDescription(progress);

	// calculate partial progress
	float flPerc = desc.nPercent / 100.0f;
	if ( desc.nRepeat > 1 && m_nLastProgressPointRepeatCount )
	{
		// cap the repeat count
		m_nLastProgressPointRepeatCount = min(m_nLastProgressPointRepeatCount, desc.nRepeat);

		// next progress point
		float flNextPerc = GetProgressDescription(progress + 1).nPercent / 100.0f;

		// move along partially towards the next tick
		flPerc += (flNextPerc - flPerc) * ((float)m_nLastProgressPointRepeatCount / desc.nRepeat);
	}

	// the bias allows the loading bar to have an optional reserved initial band
	// isolated from the normal progress descriptions
	flPerc = flPerc * ( 1.0f - m_ProgressBias ) + m_ProgressBias;

	if ( staticGameUIFuncs->UpdateProgressBar( flPerc, desc.pszDesc ) )
	{
		// re-render vgui on screen
		extern void V_RenderVGuiOnly();
		V_RenderVGuiOnly();
	}

	m_eLastProgressPoint = progress;
}

//-----------------------------------------------------------------------------
// Purpose: Updates progress
//-----------------------------------------------------------------------------
void CEngineVGui::UpdateCustomProgressBar( float progress, const wchar_t *desc )
{
	if (!staticGameUIFuncs)
		return;

	char ansi[1024];
	g_pVGuiLocalize->ConvertUnicodeToANSI( desc, ansi, sizeof( ansi ) );

	if ( staticGameUIFuncs->UpdateProgressBar( progress, ansi ) )
	{
		// re-render vgui on screen
		extern void V_RenderVGuiOnly();
		V_RenderVGuiOnly();
	}
}

void CEngineVGui::StartCustomProgress()
{
	if (!staticGameUIFuncs)
		return;

	// we've starting loading a level/connecting to a server
	staticGameUIFuncs->OnLevelLoadingStarted(true);
	m_bSaveProgress = staticGameUIFuncs->SetShowProgressText( true );
}

void CEngineVGui::FinishCustomProgress()
{
	if (!staticGameUIFuncs)
		return;

	staticGameUIFuncs->SetShowProgressText( m_bSaveProgress );
	staticGameUIFuncs->OnLevelLoadingFinished( false, "", "" );
}

void CEngineVGui::SetProgressBias( float bias )
{
	m_ProgressBias = bias;
}

void CEngineVGui::UpdateProgressBar( float progress )
{
	if ( !staticGameUIFuncs )
		return;

	if ( staticGameUIFuncs->UpdateProgressBar( progress, "" ) )
	{
		// re-render vgui on screen
		extern void V_RenderVGuiOnly();
		V_RenderVGuiOnly();
	}
}


//-----------------------------------------------------------------------------
// Purpose: Returns 1 if the key event is handled, 0 if the engine should handle it
//-----------------------------------------------------------------------------
void CEngineVGui::UpdateButtonState( const InputEvent_t &event )
{
	m_pInputInternal->UpdateButtonState( event );
}

		
//-----------------------------------------------------------------------------
// Purpose: Returns 1 if the key event is handled, 0 if the engine should handle it
//-----------------------------------------------------------------------------
bool CEngineVGui::Key_Event( const InputEvent_t &event )
{
	bool bDown = event.m_nType != IE_ButtonReleased;
	ButtonCode_t code = (ButtonCode_t)event.m_nData;

	if ( IsPC() && IsShiftKeyDown() )
	{
		switch( code )
		{
		case KEY_F1:
			if ( bDown )
			{
				Cbuf_AddText( "debugsystemui" );
			}
			return true;

		case KEY_F2:
			if ( bDown )
			{
				Cbuf_AddText( "demoui" );
			}
			return true;
		}
	}

#if defined( _WIN32 )
	// Ignore alt tilde, since the Japanese IME uses this to toggle itself on/off
	if ( IsPC() && code == KEY_BACKQUOTE && ( IsAltKeyDown() || IsCtrlKeyDown() ) )
		return true;
#endif
			   
	// ESCAPE toggles game ui
	if ( bDown && ( code == KEY_ESCAPE || code == KEY_XBUTTON_START || code == STEAMCONTROLLER_START) && !g_ClientDLL->HandleUiToggle() )
	{
		if ( IsPC() )
		{
			if ( IsGameUIVisible()  )
			{
				// Don't allow hiding of the game ui if there's no level
				const char *pLevelName = engineClient->GetLevelName();
				if ( pLevelName && pLevelName[0] )
				{
					Cbuf_AddText( "gameui_hide" );
					if ( IsDebugSystemVisible() )
					{
						Cbuf_AddText( "debugsystemui 0" );
					}
				}
			}
			else
			{
				Cbuf_AddText( "gameui_activate" );
			}
			return true;
		}
		if ( IsX360() && !IsGameUIVisible() )
		{
			// 360 UI does not toggle, engine does "show", but UI needs to handle "hide"
			Cbuf_AddText( "gameui_activate" );
			return true;
		}
	}

	if ( g_pMatSystemSurface && g_pMatSystemSurface->HandleInputEvent( event ) )
	{
		// always let the engine handle the console keys
		// FIXME: Do a lookup of the key bound to toggleconsole
		// want to cache it off so the lookup happens only when keys are bound?
		if ( IsPC() && ( code == KEY_BACKQUOTE ) )
			return false;
		return true;
	}
	return false;
}

void CEngineVGui::Simulate()
{
	toolframework->VGui_PreSimulateAllTools();

	if ( staticPanel )
	{
		VPROF_BUDGET( "CEngineVGui::Simulate", VPROF_BUDGETGROUP_OTHER_VGUI );

		// update vgui animations
		//!! currently this has to be done once per dll, because the anim controller object is in a lib;
		//!! need to make it globally pumped (gameUI.dll has it's own version of this)
		vgui::GetAnimationController()->UpdateAnimations( Sys_FloatTime() );

		int w, h;
#if defined( USE_SDL )
		uint width,height;
		g_pLauncherMgr->RenderedSize( width, height, false );	// false = get
		w = width;
		h = height;
#else
		if ( ::IsIconic( *pmainwindow ) )
		{
			w = videomode->GetModeWidth();
			h = videomode->GetModeHeight();
		}
		else
		{
			RECT rect;
			::GetClientRect(*pmainwindow, &rect);

			w = rect.right;
			h = rect.bottom;
		}
#endif
		// don't hold this reference over RunFrame()
		{
			CMatRenderContextPtr pRenderContext( materials );
			pRenderContext->Viewport( 0, 0, w, h );
		}

		staticGameUIFuncs->RunFrame();
		vgui::ivgui()->RunFrame();

		// Some debugging helpers
		DrawMouseFocus();
		VGui_UpdateDrawTreePanel();
		VGui_UpdateTextureListPanel();

		vgui::surface()->CalculateMouseVisible();
		VGui_ActivateMouse();
	}

//	if ( !vgui::ivgui()->IsRunning() )
//		Cbuf_AddText( "quit\n" );
	
	toolframework->VGui_PostSimulateAllTools();
}

void CEngineVGui::BackwardCompatibility_Paint()
{
	Paint( (PaintMode_t)(PAINT_UIPANELS | PAINT_INGAMEPANELS) );
}


//-----------------------------------------------------------------------------
// Purpose: paints all the vgui elements
//-----------------------------------------------------------------------------
void CEngineVGui::Paint( PaintMode_t mode )
{
	VPROF_BUDGET( "CEngineVGui::Paint", VPROF_BUDGETGROUP_OTHER_VGUI );

	if ( !staticPanel )
		return;

	// setup the base panel to cover the screen
	vgui::VPANEL pVPanel = vgui::surface()->GetEmbeddedPanel();
	if ( !pVPanel )
		return;

	bool drawVgui = r_drawvgui.GetBool();

	// Don't draw the console at all if vgui is off during a time demo
	if ( demoplayer->IsPlayingTimeDemo() && !drawVgui )
	{
		return;
	}

	if ( !drawVgui || m_bNoShaderAPI )
	{
		return;
	}

	// draw from the main panel down
	vgui::Panel *panel = staticPanel;

	// Force engine's root panel (staticPanel) to be full screen size
	{
		int x, y, w, h;
		CMatRenderContextPtr pRenderContext( materials );
		pRenderContext->GetViewport( x, y, w, h );
		panel->SetBounds(0, 0, w, h); // ignore x and y here because the viewport takes care of that
	}

	panel->Repaint();

	toolframework->VGui_PreRenderAllTools( mode );

	// Paint both ( backward compatibility support )

	// It's either the full screen, or just the client .dll stuff
	if ( mode & PAINT_UIPANELS )
	{
		// Hide the client .dll, and paint everything else
		bool saveVisible = staticClientDLLPanel->IsVisible();
		bool saveToolsVisible = staticClientDLLToolsPanel->IsVisible();
		staticClientDLLPanel->SetVisible( false );
		staticClientDLLToolsPanel->SetVisible( false );

		vgui::surface()->PaintTraverseEx(pVPanel, true );

		staticClientDLLPanel->SetVisible( saveVisible );
		staticClientDLLToolsPanel->SetVisible( saveToolsVisible );
	}
	
	if ( mode & PAINT_INGAMEPANELS )
	{
		bool bSaveVisible = vgui::ipanel()->IsVisible( pVPanel );
		vgui::ipanel()->SetVisible( pVPanel, false );

		// Remove the client .dll from the main hierarchy so that popups will only paint for the client .dll here
		// NOTE: Disconnect each surface one at a time so that we don't draw popups twice

		// Paint the client .dll only
		vgui::VPANEL ingameRoot = staticClientDLLPanel->GetVPanel();
		vgui::VPANEL saveParent = vgui::ipanel()->GetParent( ingameRoot );
		vgui::ipanel()->SetParent( ingameRoot, 0 );
		vgui::surface()->PaintTraverseEx( ingameRoot, true );
		vgui::ipanel()->SetParent( ingameRoot, saveParent );

		// Overlay the client .dll tools next
		vgui::VPANEL ingameToolsRoot = staticClientDLLToolsPanel->GetVPanel();
		vgui::VPANEL saveToolParent = vgui::ipanel()->GetParent( ingameToolsRoot );
		vgui::ipanel()->SetParent( ingameToolsRoot, 0 );
		vgui::surface()->PaintTraverseEx( ingameToolsRoot, true );
		vgui::ipanel()->SetParent( ingameToolsRoot, saveToolParent );

		vgui::ipanel()->SetVisible( pVPanel, bSaveVisible );
	}

	if ( mode & PAINT_CURSOR )
	{
		vgui::surface()->PaintSoftwareCursor();
	}

	toolframework->VGui_PostRenderAllTools( mode );
}

bool CEngineVGui::IsDebugSystemVisible( void )
{
	return staticDebugSystemPanel ? staticDebugSystemPanel->IsVisible() : false;
}

void CEngineVGui::HideDebugSystem( void )
{
	if ( staticDebugSystemPanel )
	{
		staticDebugSystemPanel->SetVisible( false );
		SetEngineVisible( true );
	}
}


void CEngineVGui::ToggleDebugSystemUI( const CCommand &args )
{
	if ( !staticDebugSystemPanel )
		return;

	bool bVisible;
	if ( args.ArgC() == 1 )
	{
		// toggle the game UI
		bVisible = !IsDebugSystemVisible();
	}
	else
	{
		bVisible = atoi( args[1] ) != 0;
	}

	if ( !bVisible )
	{
		staticDebugSystemPanel->SetVisible( false );
		SetEngineVisible( true );
	}
	else
	{
		// clear any keys that might be stuck down
		ClearIOStates();
		staticDebugSystemPanel->SetVisible( true );
		SetEngineVisible( false );
	}
}

bool CEngineVGui::IsShiftKeyDown( void )
{
	if ( !vgui::input() )
		return false;

	return vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT );
}

bool CEngineVGui::IsAltKeyDown( void )
{
	if ( !vgui::input() )
		return false;

	return vgui::input()->IsKeyDown( KEY_LALT ) || vgui::input()->IsKeyDown( KEY_RALT );
}

bool CEngineVGui::IsCtrlKeyDown( void )
{
	if ( !vgui::input() )
		return false;

	return vgui::input()->IsKeyDown( KEY_LCONTROL ) || vgui::input()->IsKeyDown( KEY_RCONTROL );
}


//-----------------------------------------------------------------------------
// Purpose: notification
//-----------------------------------------------------------------------------
void CEngineVGui::NotifyOfServerConnect(const char *pchGame, int IP, int connectionPort, int queryPort)
{
	if (!staticGameUIFuncs)
		return;

	staticGameUIFuncs->OnConnectToServer2( pchGame, IP, connectionPort, queryPort);
}

//-----------------------------------------------------------------------------
// Purpose: notification
//-----------------------------------------------------------------------------
void CEngineVGui::NotifyOfServerDisconnect()
{
	if (!staticGameUIFuncs)
		return;

	staticGameUIFuncs->OnDisconnectFromServer( g_eSteamLoginFailure );
	g_eSteamLoginFailure = 0;
}

//-----------------------------------------------------------------------------
// Xbox 360: Matchmaking sessions send progress notifications to GameUI
//-----------------------------------------------------------------------------
void CEngineVGui::SessionNotification( const int notification, const int param )
{
	staticGameUIFuncs->SessionNotification( notification, param );
}

void CEngineVGui::SystemNotification( const int notification )
{
	staticGameUIFuncs->SystemNotification( notification );
}

//-----------------------------------------------------------------------------
// Xbox 360: Show a message/error dialog
//-----------------------------------------------------------------------------
void CEngineVGui::ShowMessageDialog( const uint nType, vgui::Panel *pOwner )
{
	ActivateGameUI();
	staticGameUIFuncs->ShowMessageDialog( nType, pOwner );
}

void CEngineVGui::UpdatePlayerInfo( uint64 nPlayerId, const char *pName, int nTeam, byte cVoiceState, int nPlayersNeeded, bool bHost )
{
	staticGameUIFuncs->UpdatePlayerInfo( nPlayerId, pName, nTeam, cVoiceState, nPlayersNeeded, bHost );
}

void CEngineVGui::SessionSearchResult( int searchIdx, void *pHostData, XSESSION_SEARCHRESULT *pResult, int ping )
{
	staticGameUIFuncs->SessionSearchResult( searchIdx, pHostData, pResult, ping );
}

//-----------------------------------------------------------------------------
// A helper to play sounds through vgui
//-----------------------------------------------------------------------------
void VGui_PlaySound( const char *pFileName )
{
	// Point at origin if they didn't specify a sound source.
	Vector vDummyOrigin;
	vDummyOrigin.Init();

	CSfxTable *pSound = (CSfxTable*)S_PrecacheSound(pFileName);
	if ( pSound )
	{
		S_MarkUISound( pSound );

		StartSoundParams_t params;
		params.staticsound = IsX360() ? true : false;
		params.soundsource = cl.m_nViewEntity;
		params.entchannel = CHAN_AUTO;
		params.pSfx = pSound;
		params.origin = vDummyOrigin;
		params.pitch = PITCH_NORM;
		params.soundlevel = SNDLVL_IDLE;
		params.flags = 0;
		params.fvol = 1.0f;

		S_StartSound( params );
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void VGui_ActivateMouse()
{
	if ( !g_ClientDLL )
		return;

	// Don't mess with mouse if not active
	if ( !game->IsActiveApp() )
	{
		g_ClientDLL->IN_DeactivateMouse ();
		return;
	}
		
	/* 
	//
	// MIKE AND ALFRED: these panels should expose whether they want mouse input or not and 
	// CalculateMouseVisible will take them into account.
	//
	// If showing game ui, make sure nothing else is hooking it
	if ( Base().IsGameUIVisible() || Base().IsDebugSystemVisible() )
	{
		g_ClientDLL->IN_DeactivateMouse();
		return;
	}
	*/
			
	if ( vgui::surface()->IsCursorLocked() && !g_bTextMode )
	{
		g_ClientDLL->IN_ActivateMouse ();
	}
	else
	{
		g_ClientDLL->IN_DeactivateMouse ();
	}
}

static ConVar mat_drawTitleSafe( "mat_drawTitleSafe", "0", 0, "Enable title safe overlay" );

CUtlVector< vgui::VPANEL > g_FocusPanelList;

ConVar vgui_drawfocus( "vgui_drawfocus", "0", 0, "Report which panel is under the mouse." );

CFocusOverlayPanel::CFocusOverlayPanel( vgui::Panel *pParent, const char *pName ) : vgui::Panel( pParent, pName )
{
	SetPaintEnabled( false );
	SetPaintBorderEnabled( false );
	SetPaintBackgroundEnabled( false );

	MakePopup();

	SetPostChildPaintEnabled( true );
	SetKeyBoardInputEnabled( false );
	SetMouseInputEnabled( false );
}

bool CFocusOverlayPanel::DrawTitleSafeOverlay( void )
{
	if ( !mat_drawTitleSafe.GetBool() )
		return false;

	int backBufferWidth, backBufferHeight;
	materials->GetBackBufferDimensions( backBufferWidth, backBufferHeight );

	int x, y, x1, y1;

	// Required Title safe is TCR documented at inner 90% (RED)
	int insetX = 0.05f * backBufferWidth;
	int insetY = 0.05f * backBufferHeight;

	x = insetX;
	y = insetY;
	x1 = backBufferWidth - insetX;
	y1 = backBufferHeight - insetY;

	vgui::surface()->DrawSetColor( 255, 0, 0, 255 );
	vgui::surface()->DrawOutlinedRect( x, y, x1, y1 );


	// Suggested Title Safe is TCR documented at inner 85% (YELLOW)
	insetX = 0.075f * backBufferWidth;
	insetY = 0.075f * backBufferHeight;

	x = insetX;
	y = insetY;
	x1 = backBufferWidth - insetX;
	y1 = backBufferHeight - insetY;

	vgui::surface()->DrawSetColor( 255, 255, 0, 255 );
	vgui::surface()->DrawOutlinedRect( x, y, x1, y1 );	

	return true;
}

void CFocusOverlayPanel::PostChildPaint( void )
{
	BaseClass::PostChildPaint();

	bool bNeedsMoveToFront = false;

	if ( g_DrawTreeSelectedPanel )
	{
		int x, y, x1, y1;
		vgui::ipanel()->GetClipRect( g_DrawTreeSelectedPanel, x, y, x1, y1 );
		vgui::surface()->DrawSetColor( Color( 255, 0, 0, 255 ) );
		vgui::surface()->DrawOutlinedRect( x, y, x1, y1 );

		bNeedsMoveToFront = true;
	}

	if ( DrawTitleSafeOverlay() )
	{
		bNeedsMoveToFront = true;
	}

	if ( DrawFocusPanelList() )
	{
		bNeedsMoveToFront = true;
	}

	if ( bNeedsMoveToFront )
	{
		// will be valid for the next frame
		MoveToFront();
	}
}

bool CFocusOverlayPanel::DrawFocusPanelList( void )
{
	if( !vgui_drawfocus.GetBool() )
		return false;

	int c = g_FocusPanelList.Size();
	if ( c <= 0 )
		return false;

	int slot = 0;
	int fullscreeninset = 0;

	for ( int i = 0; i < c; i++ )
	{
		if ( slot > 31 )
			break;

		vgui::VPANEL vpanel = g_FocusPanelList[ i ];
		if ( !vpanel )
			continue;

		if ( !vgui::ipanel()->IsVisible( vpanel ) )
			return false;

		// Convert panel bounds to screen space
		int r, g, b;
		GetColorForSlot( slot, r, g, b );

		int x, y, x1, y1;
		vgui::ipanel()->GetClipRect( vpanel, x, y, x1, y1 );

		if ( (x1 - x) == videomode->GetModeUIWidth() && 
			 (y1 - y) == videomode->GetModeUIHeight() )
		{
			x += fullscreeninset;
			y += fullscreeninset;
			x1 -= fullscreeninset;
			y1 -= fullscreeninset;
			fullscreeninset++;
		}
		vgui::surface()->DrawSetColor( Color( r, g, b, 255 ) );
		vgui::surface()->DrawOutlinedRect( x, y, x1, y1 );

		slot++;
	}

	return true;
}


static void VGui_RecursiveFindPanels( CUtlVector< vgui::VPANEL  >& panelList, vgui::VPANEL check, char const *panelname )
{
	vgui::Panel *panel = vgui::ipanel()->GetPanel( check, "ENGINE" );
	if ( !panel )
		return;

	if ( !Q_strncmp( panel->GetName(), panelname, strlen( panelname ) ) )
	{
		panelList.AddToTail( panel->GetVPanel() );
	}

	int childcount = panel->GetChildCount();
	for ( int i = 0; i < childcount; i++ )
	{
		vgui::Panel *child = panel->GetChild( i );
		VGui_RecursiveFindPanels( panelList, child->GetVPanel(), panelname );
	}
}

void VGui_FindNamedPanels( CUtlVector< vgui::VPANEL >& panelList, char const *panelname )
{
	vgui::VPANEL embedded = vgui::surface()->GetEmbeddedPanel();

	// faster version of code below
	// checks through each popup in order, top to bottom windows
	int c = vgui::surface()->GetPopupCount();
	for (int i = c - 1; i >= 0; i--)
	{
		vgui::VPANEL popup = vgui::surface()->GetPopup(i);
		if ( !popup )
			continue;

		if ( embedded == popup )
			continue;

		VGui_RecursiveFindPanels( panelList, popup, panelname );
	}

	VGui_RecursiveFindPanels( panelList, embedded, panelname );
}

CON_COMMAND( vgui_togglepanel, "show/hide vgui panel by name." )
{
	if ( args.ArgC() < 2 )
	{
		ConMsg( "Usage:  vgui_showpanel panelname\n" );
		return;
	}

	bool flip = false;
	bool fg = true;
	bool bg = true;

	if ( args.ArgC() == 5 )
	{
		flip = atoi( args[ 2 ] ) ? true : false;
		fg = atoi( args[ 3 ] ) ? true : false;
		bg = atoi( args[ 4 ] ) ? true : false;
	}
		
	char const *panelname = args[ 1 ];
	if ( !panelname || !panelname[ 0 ] )
		return;

	CUtlVector< vgui::VPANEL > panelList;

	VGui_FindNamedPanels( panelList, panelname );
	if ( !panelList.Size() )
	{
		ConMsg( "No panels starting with %s\n", panelname );
		return;
	}

	for ( int i = 0; i < panelList.Size(); i++ )
	{
		vgui::VPANEL p = panelList[ i ];
		if ( !p )
			continue;

		vgui::Panel *panel = vgui::ipanel()->GetPanel( p, "ENGINE");
		if ( !panel )
			continue;

		Msg( "Toggling %s\n", panel->GetName() );

		if ( fg )
		{
			panel->SetPaintEnabled( flip );
		}
		if ( bg )
		{
			panel->SetPaintBackgroundEnabled( flip );
		}
	}
}

static void VGui_RecursePanel( CUtlVector< vgui::VPANEL >& panelList, int x, int y, vgui::VPANEL check, bool include_hidden )
{
	if( !include_hidden && !vgui::ipanel()->IsVisible( check ) )
	{
		return;
	}

	if ( vgui::ipanel()->IsWithinTraverse( check, x, y, false ) )
	{
		panelList.AddToTail( check );
	}

	int childcount = vgui::ipanel()->GetChildCount( check );
	for ( int i = 0; i < childcount; i++ )
	{
		vgui::VPANEL child = vgui::ipanel()->GetChild( check, i );
		VGui_RecursePanel( panelList, x, y, child, include_hidden );
	}
}

void CEngineVGui::DrawMouseFocus( void )
{
	VPROF( "CEngineVGui::DrawMouseFocus" );

	g_FocusPanelList.RemoveAll();

	if ( !vgui_drawfocus.GetBool() )
		return;
	
	staticFocusOverlayPanel->MoveToFront();

	bool include_hidden = vgui_drawfocus.GetInt() == 2;

	int x, y;
	vgui::input()->GetCursorPos( x, y );

	vgui::VPANEL embedded = vgui::surface()->GetEmbeddedPanel();

	if ( vgui::surface()->IsCursorVisible() && vgui::surface()->IsWithin(x, y) )
	{
		// faster version of code below
		// checks through each popup in order, top to bottom windows
		int c = vgui::surface()->GetPopupCount();
		for (int i = c - 1; i >= 0; i--)
		{
			vgui::VPANEL popup = vgui::surface()->GetPopup(i);
			if ( !popup )
				continue;

			if ( popup == embedded )
				continue;
			if ( !vgui::ipanel()->IsVisible( popup ) )
				continue;

			VGui_RecursePanel( g_FocusPanelList, x, y, popup, include_hidden );
		}

		VGui_RecursePanel( g_FocusPanelList, x, y, embedded, include_hidden );
	}

	// Now draw them
	con_nprint_t np;
	np.time_to_live = 1.0f;
	
	int c = g_FocusPanelList.Size();

	int slot = 0;
	for ( int i = 0; i < c; i++ )
	{
		if ( slot > 31 )
			break;

		vgui::VPANEL vpanel = g_FocusPanelList[ i ];
		if ( !vpanel )
			continue;

		np.index = slot;

		int r, g, b;
		CFocusOverlayPanel::GetColorForSlot( slot, r, g, b );

		np.color[ 0 ] = r / 255.0f;
		np.color[ 1 ] = g / 255.0f;
		np.color[ 2 ] = b / 255.0f;

		Con_NXPrintf( &np, "%3i:  %s\n", slot + 1, vgui::ipanel()->GetName(vpanel) );

		slot++;
	}

	while ( slot <= 31 )
	{
		Con_NPrintf( slot, "" );
		slot++;
	}
}

void VGui_SetGameDLLPanelsVisible( bool show )
{
	EngineVGui()->SetGameDLLPanelsVisible( show );
}

void CEngineVGui::ShowNewGameDialog( int chapter )
{
	staticGameUIFuncs->ShowNewGameDialog( chapter );
}

void CEngineVGui::OnCreditsFinished( void ) 
{
	staticGameUIFuncs->OnCreditsFinished();
}

bool CEngineVGui::ValidateStorageDevice(int *pStorageDeviceValidated)
{
	return staticGameUIFuncs->ValidateStorageDevice( pStorageDeviceValidated );
}

//-----------------------------------------------------------------------------
// Dump the panel hierarchy
//-----------------------------------------------------------------------------
void DumpPanels_r( vgui::VPANEL panel, int level )
{
	int i;

	vgui::IPanel *ipanel = vgui::ipanel();

	const char *pName = ipanel->GetName( panel );

	char indentBuff[32];
	for (i=0; i<level; i++)
	{
		indentBuff[i] = '.';
	}
	indentBuff[i] = '\0';

	ConMsg( "%s%s\n", indentBuff, pName[0] ? pName : "???" );

	int childcount = ipanel->GetChildCount( panel );
	for ( i = 0; i < childcount; i++ )
	{
		vgui::VPANEL child = ipanel->GetChild( panel, i );
		DumpPanels_r( child, level+1 );
	}
}

void DumpPanels_f()
{
	vgui::VPANEL embedded = vgui::surface()->GetEmbeddedPanel();
	DumpPanels_r( embedded, 0 );
}
ConCommand DumpPanels("dump_panels", DumpPanels_f, "Dump Panel Tree" );

#if defined( _X360 )
//-----------------------------------------------------------------------------
// Purpose: For testing message dialogs 
//-----------------------------------------------------------------------------
#include "vgui_controls/MessageDialog.h"
CON_COMMAND( dlg_normal, "Display a sample message dialog" )
{
	EngineVGui()->ShowMessageDialog( MD_STANDARD_SAMPLE );
}

CON_COMMAND( dlg_warning, "Display a sample warning message dialog" )
{
	EngineVGui()->ShowMessageDialog( MD_WARNING_SAMPLE );
}

CON_COMMAND( dlg_error, "Display a sample error message dialog" )
{
	EngineVGui()->ShowMessageDialog( MD_ERROR_SAMPLE );
}
#endif