summaryrefslogtreecommitdiff
path: root/gameui/GameUI_Interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gameui/GameUI_Interface.cpp')
-rw-r--r--gameui/GameUI_Interface.cpp1285
1 files changed, 1285 insertions, 0 deletions
diff --git a/gameui/GameUI_Interface.cpp b/gameui/GameUI_Interface.cpp
new file mode 100644
index 0000000..01c7b39
--- /dev/null
+++ b/gameui/GameUI_Interface.cpp
@@ -0,0 +1,1285 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implements all the functions exported by the GameUI dll
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#ifdef WIN32
+#if !defined( _X360 )
+#include <windows.h>
+#endif
+#include <io.h>
+#include <direct.h>
+#elif defined( POSIX )
+#include <sys/time.h>
+#else
+#error
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <tier0/dbg.h>
+
+#ifdef SendMessage
+#undef SendMessage
+#endif
+
+#include "filesystem.h"
+#include "GameUI_Interface.h"
+#include "Sys_Utils.h"
+#include "string.h"
+#include "tier0/icommandline.h"
+
+// interface to engine
+#include "EngineInterface.h"
+
+#include "replay/ienginereplay.h"
+#include "replay/ireplaysystem.h"
+
+#include "VGuiSystemModuleLoader.h"
+#include "bitmap/tgaloader.h"
+
+#include "GameConsole.h"
+#include "LoadingDialog.h"
+#include "CDKeyEntryDialog.h"
+#include "ModInfo.h"
+#include "game/client/IGameClientExports.h"
+#include "materialsystem/imaterialsystem.h"
+#include "engine/imatchmaking.h"
+#include "ixboxsystem.h"
+#include "iachievementmgr.h"
+#include "IGameUIFuncs.h"
+#include <ienginevgui.h>
+#include "steam/steam_api.h"
+#include "BonusMapsDatabase.h"
+#include "BonusMapsDialog.h"
+#include "sourcevr/isourcevirtualreality.h"
+
+// vgui2 interface
+// note that GameUI project uses ..\vgui2\include, not ..\utils\vgui\include
+#include "BasePanel.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/Menu.h>
+#include <vgui_controls/PHandle.h>
+#include "tier3/tier3.h"
+#include "tier0/vcrmode.h"
+#include "matsys_controls/matsyscontrols.h"
+#include "steam/steam_api.h"
+
+#if defined( _X360 )
+#include "xbox/xbox_win32stubs.h"
+#endif
+
+#include "tier0/dbg.h"
+#include "engine/IEngineSound.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+IGameUIFuncs *gameuifuncs = NULL;
+IEngineVGui *enginevguifuncs = NULL;
+IMatchmaking *matchmaking = NULL;
+IXboxSystem *xboxsystem = NULL; // 360 only
+vgui::ISurface *enginesurfacefuncs = NULL;
+IVEngineClient *engine = NULL;
+IEngineSound *enginesound = NULL;
+IAchievementMgr *achievementmgr = NULL;
+IEngineClientReplay *g_pEngineClientReplay = NULL;
+ISourceVirtualReality *g_pSourceVR = NULL;
+
+static CSteamAPIContext g_SteamAPIContext;
+CSteamAPIContext *steamapicontext = &g_SteamAPIContext;
+
+static CBasePanel *staticPanel = NULL;
+
+class CGameUI;
+CGameUI *g_pGameUI = NULL;
+
+class CLoadingDialog;
+vgui::DHANDLE<CLoadingDialog> g_hLoadingDialog;
+vgui::VPANEL g_hLoadingBackgroundDialog = NULL;
+
+static CGameUI g_GameUI;
+static WHANDLE g_hMutex = NULL;
+static WHANDLE g_hWaitMutex = NULL;
+
+static IGameClientExports *g_pGameClientExports = NULL;
+IGameClientExports *GameClientExports()
+{
+ return g_pGameClientExports;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: singleton accessor
+//-----------------------------------------------------------------------------
+CGameUI &GameUI()
+{
+ return g_GameUI;
+}
+
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CGameUI, IGameUI, GAMEUI_INTERFACE_VERSION, g_GameUI);
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CGameUI::CGameUI()
+{
+ g_pGameUI = this;
+ m_bTryingToLoadFriends = false;
+ m_iFriendsLoadPauseFrames = 0;
+ m_iGameIP = 0;
+ m_iGameConnectionPort = 0;
+ m_iGameQueryPort = 0;
+ m_bActivatedUI = false;
+ m_szPreviousStatusText[0] = 0;
+ m_bIsConsoleUI = false;
+ m_bHasSavedThisMenuSession = false;
+ m_bOpenProgressOnStart = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CGameUI::~CGameUI()
+{
+ g_pGameUI = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Initialization
+//-----------------------------------------------------------------------------
+void CGameUI::Initialize( CreateInterfaceFn factory )
+{
+ ConnectTier1Libraries( &factory, 1 );
+ ConnectTier2Libraries( &factory, 1 );
+ ConVar_Register( FCVAR_CLIENTDLL );
+ ConnectTier3Libraries( &factory, 1 );
+
+ enginesound = (IEngineSound *)factory(IENGINESOUND_CLIENT_INTERFACE_VERSION, NULL);
+ engine = (IVEngineClient *)factory( VENGINE_CLIENT_INTERFACE_VERSION, NULL );
+
+ steamapicontext->Init();
+
+ ConVarRef var( "gameui_xbox" );
+ m_bIsConsoleUI = var.IsValid() && var.GetBool();
+
+ vgui::VGui_InitInterfacesList( "GameUI", &factory, 1 );
+ vgui::VGui_InitMatSysInterfacesList( "GameUI", &factory, 1 );
+
+ // load localization file
+ g_pVGuiLocalize->AddFile( "Resource/gameui_%language%.txt", "GAME", true );
+
+ // load mod info
+ ModInfo().LoadCurrentGameInfo();
+
+ // load localization file for kb_act.lst
+ g_pVGuiLocalize->AddFile( "Resource/valve_%language%.txt", "GAME", true );
+
+ enginevguifuncs = (IEngineVGui *)factory( VENGINE_VGUI_VERSION, NULL );
+ enginesurfacefuncs = (vgui::ISurface *)factory(VGUI_SURFACE_INTERFACE_VERSION, NULL);
+ gameuifuncs = (IGameUIFuncs *)factory( VENGINE_GAMEUIFUNCS_VERSION, NULL );
+ matchmaking = (IMatchmaking *)factory( VENGINE_MATCHMAKING_VERSION, NULL );
+ xboxsystem = (IXboxSystem *)factory( XBOXSYSTEM_INTERFACE_VERSION, NULL );
+ g_pEngineClientReplay = (IEngineClientReplay *)factory( ENGINE_REPLAY_CLIENT_INTERFACE_VERSION, NULL );
+
+ if ( ModInfo().SupportsVR() && CommandLine()->CheckParm( "-vr" ) )
+ {
+ g_pSourceVR = (ISourceVirtualReality *)factory( SOURCE_VIRTUAL_REALITY_INTERFACE_VERSION, NULL );
+ }
+
+ // NOTE: g_pEngineReplay intentionally not checked here
+ if ( !enginesurfacefuncs || !gameuifuncs || !enginevguifuncs || !xboxsystem || (IsX360() && !matchmaking) )
+ {
+ Error( "CGameUI::Initialize() failed to get necessary interfaces\n" );
+ }
+
+ // setup base panel
+ staticPanel = new CBasePanel();
+ staticPanel->SetBounds(0, 0, 400, 300 );
+ staticPanel->SetPaintBorderEnabled( false );
+ staticPanel->SetPaintBackgroundEnabled( true );
+ staticPanel->SetPaintEnabled( false );
+ staticPanel->SetVisible( true );
+ staticPanel->SetMouseInputEnabled( false );
+ staticPanel->SetKeyBoardInputEnabled( false );
+
+ vgui::VPANEL rootpanel = enginevguifuncs->GetPanel( PANEL_GAMEUIDLL );
+ staticPanel->SetParent( rootpanel );
+}
+
+void CGameUI::PostInit()
+{
+ if ( IsX360() )
+ {
+ enginesound->PrecacheSound( "UI/buttonrollover.wav", true, true );
+ enginesound->PrecacheSound( "UI/buttonclick.wav", true, true );
+ enginesound->PrecacheSound( "UI/buttonclickrelease.wav", true, true );
+ enginesound->PrecacheSound( "player/suit_denydevice.wav", true, true );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the specified panel as the background panel for the loading
+// dialog. If NULL, default background is used. If you set a panel,
+// it should be full-screen with an opaque background, and must be a VGUI popup.
+//-----------------------------------------------------------------------------
+void CGameUI::SetLoadingBackgroundDialog( vgui::VPANEL panel )
+{
+ g_hLoadingBackgroundDialog = panel;
+}
+
+void CGameUI::BonusMapUnlock( const char *pchFileName, const char *pchMapName )
+{
+ if ( !pchFileName || pchFileName[ 0 ] == '\0' ||
+ !pchMapName || pchMapName[ 0 ] == '\0' )
+ {
+ if ( !g_pBonusMapsDialog )
+ return;
+
+ g_pBonusMapsDialog->SetSelectedBooleanStatus( "lock", false );
+ return;
+ }
+
+ if ( BonusMapsDatabase()->SetBooleanStatus( "lock", pchFileName, pchMapName, false ) )
+ {
+ BonusMapsDatabase()->RefreshMapData();
+
+ if ( !g_pBonusMapsDialog )
+ {
+ // It unlocked without the bonus maps menu open, so flash the menu item
+ CBasePanel *pBasePanel = BasePanel();
+ if ( pBasePanel )
+ {
+ if ( GameUI().IsConsoleUI() )
+ {
+ if ( Q_stricmp( pchFileName, "scripts/advanced_chambers" ) == 0 )
+ {
+ pBasePanel->SetMenuItemBlinkingState( "OpenNewGameDialog", true );
+ }
+ }
+ else
+ {
+ pBasePanel->SetMenuItemBlinkingState( "OpenBonusMapsDialog", true );
+ }
+ }
+
+ BonusMapsDatabase()->SetBlink( true );
+ }
+ else
+ g_pBonusMapsDialog->RefreshData(); // Update the open dialog
+ }
+}
+
+void CGameUI::BonusMapComplete( const char *pchFileName, const char *pchMapName )
+{
+ if ( !pchFileName || pchFileName[ 0 ] == '\0' ||
+ !pchMapName || pchMapName[ 0 ] == '\0' )
+ {
+ if ( !g_pBonusMapsDialog )
+ return;
+
+ g_pBonusMapsDialog->SetSelectedBooleanStatus( "complete", true );
+ BonusMapsDatabase()->RefreshMapData();
+ g_pBonusMapsDialog->RefreshData();
+ return;
+ }
+
+ if ( BonusMapsDatabase()->SetBooleanStatus( "complete", pchFileName, pchMapName, true ) )
+ {
+ BonusMapsDatabase()->RefreshMapData();
+
+ // Update the open dialog
+ if ( g_pBonusMapsDialog )
+ g_pBonusMapsDialog->RefreshData();
+ }
+}
+
+void CGameUI::BonusMapChallengeUpdate( const char *pchFileName, const char *pchMapName, const char *pchChallengeName, int iBest )
+{
+ if ( !pchFileName || pchFileName[ 0 ] == '\0' ||
+ !pchMapName || pchMapName[ 0 ] == '\0' ||
+ !pchChallengeName || pchChallengeName[ 0 ] == '\0' )
+ {
+ return;
+ }
+ else
+ {
+ if ( BonusMapsDatabase()->UpdateChallengeBest( pchFileName, pchMapName, pchChallengeName, iBest ) )
+ {
+ // The challenge best changed, so write it to the file
+ BonusMapsDatabase()->WriteSaveData();
+ BonusMapsDatabase()->RefreshMapData();
+
+ // Update the open dialog
+ if ( g_pBonusMapsDialog )
+ g_pBonusMapsDialog->RefreshData();
+ }
+ }
+}
+
+void CGameUI::BonusMapChallengeNames( char *pchFileName, char *pchMapName, char *pchChallengeName )
+{
+ if ( !pchFileName || !pchMapName || !pchChallengeName )
+ return;
+
+ BonusMapsDatabase()->GetCurrentChallengeNames( pchFileName, pchMapName, pchChallengeName );
+}
+
+void CGameUI::BonusMapChallengeObjectives( int &iBronze, int &iSilver, int &iGold )
+{
+ BonusMapsDatabase()->GetCurrentChallengeObjectives( iBronze, iSilver, iGold );
+}
+
+void CGameUI::BonusMapDatabaseSave( void )
+{
+ BonusMapsDatabase()->WriteSaveData();
+}
+
+int CGameUI::BonusMapNumAdvancedCompleted( void )
+{
+ return BonusMapsDatabase()->NumAdvancedComplete();
+}
+
+void CGameUI::BonusMapNumMedals( int piNumMedals[ 3 ] )
+{
+ BonusMapsDatabase()->NumMedals( piNumMedals );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: connects to client interfaces
+//-----------------------------------------------------------------------------
+void CGameUI::Connect( CreateInterfaceFn gameFactory )
+{
+ g_pGameClientExports = (IGameClientExports *)gameFactory(GAMECLIENTEXPORTS_INTERFACE_VERSION, NULL);
+
+ achievementmgr = engine->GetAchievementMgr();
+
+ if (!g_pGameClientExports)
+ {
+ Error("CGameUI::Initialize() failed to get necessary interfaces\n");
+ }
+
+ m_GameFactory = gameFactory;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Callback function; sends platform Shutdown message to specified window
+//-----------------------------------------------------------------------------
+int __stdcall SendShutdownMsgFunc(WHANDLE hwnd, int lparam)
+{
+ Sys_PostMessage(hwnd, Sys_RegisterWindowMessage("ShutdownValvePlatform"), 0, 1);
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Searches for GameStartup*.mp3 files in the sound/ui folder and plays one
+//-----------------------------------------------------------------------------
+void CGameUI::PlayGameStartupSound()
+{
+ if ( IsX360() )
+ return;
+
+ if ( CommandLine()->FindParm( "-nostartupsound" ) )
+ return;
+
+ FileFindHandle_t fh;
+
+ CUtlVector<char *> fileNames;
+ char path[ 512 ];
+
+ bool bHolidayFound = false;
+
+ // only want to run the holiday check for TF2
+ const char *pGameName = CommandLine()->ParmValue( "-game", "hl2" );
+ if ( ( Q_stricmp( pGameName, "tf" ) == 0 ) || ( Q_stricmp( pGameName, "tf_beta" ) == 0 ) )
+ {
+ // check for a holiday sound file
+ const char *pszHoliday = NULL;
+
+ if ( GameClientExports() )
+ {
+ pszHoliday = GameClientExports()->GetHolidayString();
+ if ( pszHoliday && pszHoliday[0] )
+ {
+ Q_snprintf( path, sizeof( path ), "sound/ui/holiday/gamestartup_%s*.mp3", pszHoliday );
+ Q_FixSlashes( path );
+
+ char const *fn = g_pFullFileSystem->FindFirstEx( path, "MOD", &fh );
+ {
+ if ( fn )
+ {
+ bHolidayFound = true;
+ }
+ }
+ }
+ }
+ }
+
+ // only want to do this if we haven't found a holiday file
+ if ( !bHolidayFound )
+ {
+ Q_snprintf( path, sizeof( path ), "sound/ui/gamestartup*.mp3" );
+ Q_FixSlashes( path );
+ }
+
+ char const *fn = g_pFullFileSystem->FindFirstEx( path, "MOD", &fh );
+ if ( fn )
+ {
+ do
+ {
+ char ext[ 10 ];
+ Q_ExtractFileExtension( fn, ext, sizeof( ext ) );
+
+ if ( !Q_stricmp( ext, "mp3" ) )
+ {
+ char temp[ 512 ];
+ if ( bHolidayFound )
+ {
+ Q_snprintf( temp, sizeof( temp ), "ui/holiday/%s", fn );
+ }
+ else
+ {
+ Q_snprintf( temp, sizeof( temp ), "ui/%s", fn );
+ }
+
+ char *found = new char[ strlen( temp ) + 1 ];
+ Q_strncpy( found, temp, strlen( temp ) + 1 );
+
+ Q_FixSlashes( found );
+ fileNames.AddToTail( found );
+ }
+
+ fn = g_pFullFileSystem->FindNext( fh );
+
+ } while ( fn );
+
+ g_pFullFileSystem->FindClose( fh );
+ }
+
+ // did we find any?
+ if ( fileNames.Count() > 0 )
+ {
+#ifdef WIN32
+ SYSTEMTIME SystemTime;
+ GetSystemTime( &SystemTime );
+ int index = SystemTime.wMilliseconds % fileNames.Count();
+#else
+ struct timeval tm;
+ gettimeofday( &tm, NULL );
+ int index = tm.tv_usec/1000 % fileNames.Count();
+#endif
+
+ if ( fileNames.IsValidIndex( index ) && fileNames[index] )
+ {
+ // Play the Saxxy music if we're in saxxy mode.
+#if defined( SAXXYMAINMENU_ENABLED )
+ bool bIsTF = false;
+ const char *pGameDir = engine->GetGameDirectory();
+ if ( pGameDir )
+ {
+ // Is the game TF?
+ const int nStrLen = V_strlen( pGameDir );
+ bIsTF = nStrLen
+ && nStrLen >= 2 &&
+ pGameDir[nStrLen-2] == 't' &&
+ pGameDir[nStrLen-1] == 'f';
+ }
+
+ // escape chars "*#" make it stream, and be affected by snd_musicvolume
+ const char *pSoundFile = bIsTF ? "ui/holiday/gamestartup_saxxy.mp3" : fileNames[index];
+#else
+ const char *pSoundFile = fileNames[index];
+#endif
+
+ char found[ 512 ];
+ Q_snprintf( found, sizeof( found ), "play *#%s", pSoundFile );
+
+ engine->ClientCmd_Unrestricted( found );
+ }
+
+ fileNames.PurgeAndDeleteElements();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called to setup the game UI
+//-----------------------------------------------------------------------------
+void CGameUI::Start()
+{
+ // determine Steam location for configuration
+ if ( !FindPlatformDirectory( m_szPlatformDir, sizeof( m_szPlatformDir ) ) )
+ return;
+
+ if ( IsPC() )
+ {
+ // setup config file directory
+ char szConfigDir[512];
+ Q_strncpy( szConfigDir, m_szPlatformDir, sizeof( szConfigDir ) );
+ Q_strncat( szConfigDir, "config", sizeof( szConfigDir ), COPY_ALL_CHARACTERS );
+
+ Msg( "Steam config directory: %s\n", szConfigDir );
+
+ g_pFullFileSystem->AddSearchPath(szConfigDir, "CONFIG");
+ g_pFullFileSystem->CreateDirHierarchy("", "CONFIG");
+
+ // user dialog configuration
+ vgui::system()->SetUserConfigFile("InGameDialogConfig.vdf", "CONFIG");
+
+ g_pFullFileSystem->AddSearchPath( "platform", "PLATFORM" );
+ }
+
+ // localization
+ g_pVGuiLocalize->AddFile( "Resource/platform_%language%.txt");
+ g_pVGuiLocalize->AddFile( "Resource/vgui_%language%.txt");
+
+ Sys_SetLastError( SYS_NO_ERROR );
+
+ if ( IsPC() )
+ {
+ if ( !IsPosix() )
+ {
+ // Alfred says this is really, really old code that does some wacky crap that only
+ // happened in the first version of HL and it's the only game that does this and
+ // it was a steam testing type thing and we don't need to do it on Posix, etc.
+
+ g_hMutex = Sys_CreateMutex( "ValvePlatformUIMutex" );
+ g_hWaitMutex = Sys_CreateMutex( "ValvePlatformWaitMutex" );
+ if ( g_hMutex == 0 || g_hWaitMutex == 0 || Sys_GetLastError() == SYS_ERROR_INVALID_HANDLE )
+ {
+ // error, can't get handle to mutex
+ if (g_hMutex)
+ {
+ Sys_ReleaseMutex(g_hMutex);
+ }
+ if (g_hWaitMutex)
+ {
+ Sys_ReleaseMutex(g_hWaitMutex);
+ }
+ g_hMutex = NULL;
+ g_hWaitMutex = NULL;
+ Error("Steam Error: Could not access Steam, bad mutex\n");
+ return;
+ }
+ unsigned int waitResult = Sys_WaitForSingleObject(g_hMutex, 0);
+ if (!(waitResult == SYS_WAIT_OBJECT_0 || waitResult == SYS_WAIT_ABANDONED))
+ {
+ // mutex locked, need to deactivate Steam (so we have the Friends/ServerBrowser data files)
+ // get the wait mutex, so that Steam.exe knows that we're trying to acquire ValveTrackerMutex
+ waitResult = Sys_WaitForSingleObject(g_hWaitMutex, 0);
+#ifdef WIN32
+ if (waitResult == SYS_WAIT_OBJECT_0 || waitResult == SYS_WAIT_ABANDONED)
+ {
+ Sys_EnumWindows(SendShutdownMsgFunc, 1);
+ }
+#endif
+ }
+ }
+
+ // Delay playing the startup music until the first frame
+ m_bPlayGameStartupSound = true;
+
+ // now we are set up to check every frame to see if we can friends/server browser
+ m_bTryingToLoadFriends = true;
+ m_iFriendsLoadPauseFrames = 1;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Validates the user has a cdkey in the registry
+//-----------------------------------------------------------------------------
+void CGameUI::ValidateCDKey()
+{
+ // this check is disabled, since we have no plans for an offline version of hl2
+#if 0
+ //!! hack, write out a regkey for now so developers don't have to type it in
+ //!! undo this before release
+ vgui::system()->SetRegistryString("HKEY_CURRENT_USER\\Software\\Valve\\Source\\Settings\\EncryptedCDKey", "QOgi:JXrJj<Eb8abkESf4Pg;OfofJwDzRsyH>AdjtyPnV[FB");
+
+ // see what's in the registry
+ if (!CCDKeyEntryDialog::IsValidWeakCDKeyInRegistry())
+ {
+ m_hCDKeyEntryDialog = new CCDKeyEntryDialog(NULL, false);
+ m_hCDKeyEntryDialog->Activate();
+ }
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Finds which directory the platform resides in
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CGameUI::FindPlatformDirectory(char *platformDir, int bufferSize)
+{
+ platformDir[0] = '\0';
+
+ if ( platformDir[0] == '\0' )
+ {
+ // we're not under steam, so setup using path relative to game
+ if ( IsPC() )
+ {
+#ifdef WIN32
+ if ( ::GetModuleFileName( ( HINSTANCE )GetModuleHandle( NULL ), platformDir, bufferSize ) )
+ {
+ char *lastslash = strrchr(platformDir, '\\'); // this should be just before the filename
+ if ( lastslash )
+ {
+ *lastslash = 0;
+ Q_strncat(platformDir, "\\platform\\", bufferSize, COPY_ALL_CHARACTERS );
+ return true;
+ }
+ }
+#else
+ if ( getcwd( platformDir, bufferSize ) )
+ {
+ V_AppendSlash( platformDir, bufferSize );
+ Q_strncat(platformDir, "platform", bufferSize, COPY_ALL_CHARACTERS );
+ V_AppendSlash( platformDir, bufferSize );
+ return true;
+ }
+#endif
+ }
+ else
+ {
+ // xbox fetches the platform path from exisiting platform search path
+ // path to executeable is not correct for xbox remote configuration
+ if ( g_pFullFileSystem->GetSearchPath( "PLATFORM", false, platformDir, bufferSize ) )
+ {
+ char *pSeperator = strchr( platformDir, ';' );
+ if ( pSeperator )
+ *pSeperator = '\0';
+ return true;
+ }
+ }
+
+ Error( "Unable to determine platform directory\n" );
+ return false;
+ }
+
+ return (platformDir[0] != 0);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called to Shutdown the game UI system
+//-----------------------------------------------------------------------------
+void CGameUI::Shutdown()
+{
+ // notify all the modules of Shutdown
+ g_VModuleLoader.ShutdownPlatformModules();
+
+ // unload the modules them from memory
+ g_VModuleLoader.UnloadPlatformModules();
+
+ ModInfo().FreeModInfo();
+
+ // release platform mutex
+ // close the mutex
+ if (g_hMutex)
+ {
+ Sys_ReleaseMutex(g_hMutex);
+ }
+ if (g_hWaitMutex)
+ {
+ Sys_ReleaseMutex(g_hWaitMutex);
+ }
+
+ BonusMapsDatabase()->WriteSaveData();
+
+ steamapicontext->Clear();
+
+
+ ConVar_Unregister();
+ DisconnectTier3Libraries();
+ DisconnectTier2Libraries();
+ DisconnectTier1Libraries();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: just wraps an engine call to activate the gameUI
+//-----------------------------------------------------------------------------
+void CGameUI::ActivateGameUI()
+{
+ engine->ExecuteClientCmd("gameui_activate");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: just wraps an engine call to hide the gameUI
+//-----------------------------------------------------------------------------
+void CGameUI::HideGameUI()
+{
+ engine->ExecuteClientCmd("gameui_hide");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Toggle allowing the engine to hide the game UI with the escape key
+//-----------------------------------------------------------------------------
+void CGameUI::PreventEngineHideGameUI()
+{
+ engine->ExecuteClientCmd("gameui_preventescape");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Toggle allowing the engine to hide the game UI with the escape key
+//-----------------------------------------------------------------------------
+void CGameUI::AllowEngineHideGameUI()
+{
+ engine->ExecuteClientCmd("gameui_allowescape");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Activate the game UI
+//-----------------------------------------------------------------------------
+void CGameUI::OnGameUIActivated()
+{
+ m_bActivatedUI = true;
+
+ // hide/show the main panel to Activate all game ui
+ staticPanel->SetVisible( true );
+
+ // pause the server in single player
+ if ( engine->GetMaxClients() <= 1 )
+ {
+ engine->ClientCmd_Unrestricted( "setpause" );
+ }
+
+ SetSavedThisMenuSession( false );
+
+ // notify taskbar
+ BasePanel()->OnGameUIActivated();
+
+ if ( GameClientExports() )
+ {
+ const char *pGameName = CommandLine()->ParmValue( "-game", "hl2" );
+ // only want to run this for TF2
+ if ( ( Q_stricmp( pGameName, "tf" ) == 0 ) || ( Q_stricmp( pGameName, "tf_beta" ) == 0 ) )
+ {
+ GameClientExports()->OnGameUIActivated();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Hides the game ui, in whatever state it's in
+//-----------------------------------------------------------------------------
+void CGameUI::OnGameUIHidden()
+{
+ if ( GameClientExports() )
+ {
+ const char *pGameName = CommandLine()->ParmValue( "-game", "hl2" );
+ // only want to run this for TF2
+ if ( ( Q_stricmp( pGameName, "tf" ) == 0 ) || ( Q_stricmp( pGameName, "tf_beta" ) == 0 ) )
+ {
+ GameClientExports()->OnGameUIHidden();
+ }
+ }
+
+ // unpause the game when leaving the UI
+ if ( engine->GetMaxClients() <= 1 )
+ {
+ engine->ClientCmd_Unrestricted("unpause");
+ }
+
+ BasePanel()->OnGameUIHidden();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: paints all the vgui elements
+//-----------------------------------------------------------------------------
+void CGameUI::RunFrame()
+{
+ if ( IsX360() && m_bOpenProgressOnStart )
+ {
+ StartProgressBar();
+ m_bOpenProgressOnStart = false;
+ }
+
+ // resize the background panel to the screen size
+ int wide, tall;
+ vgui::surface()->GetScreenSize(wide, tall);
+ staticPanel->SetSize(wide,tall);
+
+ // Run frames
+ g_VModuleLoader.RunFrame();
+ BasePanel()->RunFrame();
+
+ // Play the start-up music the first time we run frame
+ if ( IsPC() && m_bPlayGameStartupSound )
+ {
+ PlayGameStartupSound();
+ m_bPlayGameStartupSound = false;
+ }
+
+ if ( IsPC() && ( ( IsPosix() && m_bTryingToLoadFriends ) ||
+ ( m_bTryingToLoadFriends && m_iFriendsLoadPauseFrames-- < 1 && g_hMutex && g_hWaitMutex ) ) )
+ {
+ // try and load Steam platform files
+ unsigned int waitResult = Sys_WaitForSingleObject(g_hMutex, 0);
+ if ( IsPosix() || ( waitResult == SYS_WAIT_OBJECT_0 || waitResult == SYS_WAIT_ABANDONED ))
+ {
+ // we got the mutex, so load Friends/Serverbrowser
+ // clear the loading flag
+ m_bTryingToLoadFriends = false;
+ g_VModuleLoader.LoadPlatformModules(&m_GameFactory, 1, false);
+
+ // release the wait mutex
+ if ( !IsPosix() )
+ Sys_ReleaseMutex(g_hWaitMutex);
+
+ // notify the game of our game name
+ const char *fullGamePath = engine->GetGameDirectory();
+ const char *pathSep = strrchr( fullGamePath, '/' );
+ if ( !pathSep )
+ {
+ pathSep = strrchr( fullGamePath, '\\' );
+ }
+ if ( pathSep )
+ {
+ KeyValues *pKV = new KeyValues("ActiveGameName" );
+ pKV->SetString( "name", pathSep + 1 );
+ pKV->SetInt( "appid", engine->GetAppID() );
+ KeyValues *modinfo = new KeyValues("ModInfo");
+ if ( modinfo->LoadFromFile( g_pFullFileSystem, "gameinfo.txt" ) )
+ {
+ pKV->SetString( "game", modinfo->GetString( "game", "" ) );
+ }
+ modinfo->deleteThis();
+
+ g_VModuleLoader.PostMessageToAllModules( pKV );
+ }
+
+ // notify the ui of a game connect if we're already in a game
+ if (m_iGameIP)
+ {
+ SendConnectedToGameMessage();
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when the game connects to a server
+//-----------------------------------------------------------------------------
+void CGameUI::OLD_OnConnectToServer(const char *game, int IP, int port)
+{
+ // Nobody should use this anymore because the query port and the connection port can be different.
+ // Use OnConnectToServer2 instead.
+ Assert( false );
+ OnConnectToServer2( game, IP, port, port );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when the game connects to a server
+//-----------------------------------------------------------------------------
+void CGameUI::OnConnectToServer2(const char *game, int IP, int connectionPort, int queryPort)
+{
+ m_iGameIP = IP;
+ m_iGameConnectionPort = connectionPort;
+ m_iGameQueryPort = queryPort;
+
+ SendConnectedToGameMessage();
+}
+
+
+void CGameUI::SendConnectedToGameMessage()
+{
+ KeyValues *kv = new KeyValues( "ConnectedToGame" );
+ kv->SetInt( "ip", m_iGameIP );
+ kv->SetInt( "connectionport", m_iGameConnectionPort );
+ kv->SetInt( "queryport", m_iGameQueryPort );
+
+ g_VModuleLoader.PostMessageToAllModules( kv );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when the game disconnects from a server
+//-----------------------------------------------------------------------------
+void CGameUI::OnDisconnectFromServer( uint8 eSteamLoginFailure )
+{
+ m_iGameIP = 0;
+ m_iGameConnectionPort = 0;
+ m_iGameQueryPort = 0;
+
+ g_VModuleLoader.PostMessageToAllModules(new KeyValues("DisconnectedFromGame"));
+
+ if ( eSteamLoginFailure == STEAMLOGINFAILURE_NOSTEAMLOGIN )
+ {
+ if ( g_hLoadingDialog )
+ {
+ g_hLoadingDialog->DisplayNoSteamConnectionError();
+ }
+ }
+ else if ( eSteamLoginFailure == STEAMLOGINFAILURE_VACBANNED )
+ {
+ if ( g_hLoadingDialog )
+ {
+ g_hLoadingDialog->DisplayVACBannedError();
+ }
+ }
+ else if ( eSteamLoginFailure == STEAMLOGINFAILURE_LOGGED_IN_ELSEWHERE )
+ {
+ if ( g_hLoadingDialog )
+ {
+ g_hLoadingDialog->DisplayLoggedInElsewhereError();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: activates the loading dialog on level load start
+//-----------------------------------------------------------------------------
+void CGameUI::OnLevelLoadingStarted( bool bShowProgressDialog )
+{
+ g_VModuleLoader.PostMessageToAllModules( new KeyValues( "LoadingStarted" ) );
+
+ // notify
+ BasePanel()->OnLevelLoadingStarted();
+
+ if ( bShowProgressDialog )
+ {
+ StartProgressBar();
+ }
+
+ // Don't play the start game sound if this happens before we get to the first frame
+ m_bPlayGameStartupSound = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: closes any level load dialog
+//-----------------------------------------------------------------------------
+void CGameUI::OnLevelLoadingFinished(bool bError, const char *failureReason, const char *extendedReason)
+{
+ StopProgressBar( bError, failureReason, extendedReason );
+
+ // notify all the modules
+ g_VModuleLoader.PostMessageToAllModules( new KeyValues( "LoadingFinished" ) );
+
+ // hide the UI
+ HideGameUI();
+
+ // notify
+ BasePanel()->OnLevelLoadingFinished();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates progress bar
+// Output : Returns true if screen should be redrawn
+//-----------------------------------------------------------------------------
+bool CGameUI::UpdateProgressBar(float progress, const char *statusText)
+{
+ // if either the progress bar or the status text changes, redraw the screen
+ bool bRedraw = false;
+
+ if ( ContinueProgressBar( progress ) )
+ {
+ bRedraw = true;
+ }
+
+ if ( SetProgressBarStatusText( statusText ) )
+ {
+ bRedraw = true;
+ }
+
+ return bRedraw;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGameUI::StartProgressBar()
+{
+ if ( !g_hLoadingDialog.Get() )
+ {
+ g_hLoadingDialog = new CLoadingDialog(staticPanel);
+ }
+
+ // open a loading dialog
+ m_szPreviousStatusText[0] = 0;
+ g_hLoadingDialog->SetProgressPoint(0.0f);
+ g_hLoadingDialog->Open();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if the screen should be updated
+//-----------------------------------------------------------------------------
+bool CGameUI::ContinueProgressBar( float progressFraction )
+{
+ if (!g_hLoadingDialog.Get())
+ return false;
+
+ g_hLoadingDialog->Activate();
+ return g_hLoadingDialog->SetProgressPoint(progressFraction);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: stops progress bar, displays error if necessary
+//-----------------------------------------------------------------------------
+void CGameUI::StopProgressBar(bool bError, const char *failureReason, const char *extendedReason)
+{
+ if (!g_hLoadingDialog.Get() && bError)
+ {
+ g_hLoadingDialog = new CLoadingDialog(staticPanel);
+ }
+
+ if (!g_hLoadingDialog.Get())
+ return;
+
+ if ( !IsX360() && bError )
+ {
+ // turn the dialog to error display mode
+ g_hLoadingDialog->DisplayGenericError(failureReason, extendedReason);
+ }
+ else
+ {
+ // close loading dialog
+ g_hLoadingDialog->Close();
+ g_hLoadingDialog = NULL;
+ }
+ // should update the background to be in a transition here
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets loading info text
+//-----------------------------------------------------------------------------
+bool CGameUI::SetProgressBarStatusText(const char *statusText)
+{
+ if (!g_hLoadingDialog.Get())
+ return false;
+
+ if (!statusText)
+ return false;
+
+ if (!stricmp(statusText, m_szPreviousStatusText))
+ return false;
+
+ g_hLoadingDialog->SetStatusText(statusText);
+ Q_strncpy(m_szPreviousStatusText, statusText, sizeof(m_szPreviousStatusText));
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGameUI::SetSecondaryProgressBar(float progress /* range [0..1] */)
+{
+ if (!g_hLoadingDialog.Get())
+ return;
+
+ g_hLoadingDialog->SetSecondaryProgress(progress);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGameUI::SetSecondaryProgressBarText(const char *statusText)
+{
+ if (!g_hLoadingDialog.Get())
+ return;
+
+ g_hLoadingDialog->SetSecondaryProgressText(statusText);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns prev settings
+//-----------------------------------------------------------------------------
+bool CGameUI::SetShowProgressText( bool show )
+{
+ if (!g_hLoadingDialog.Get())
+ return false;
+
+ return g_hLoadingDialog->SetShowProgressText( show );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if we're currently playing the game
+//-----------------------------------------------------------------------------
+bool CGameUI::IsInLevel()
+{
+ const char *levelName = engine->GetLevelName();
+ if (levelName && levelName[0] && !engine->IsLevelMainMenuBackground())
+ {
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if we're at the main menu and a background level is loaded
+//-----------------------------------------------------------------------------
+bool CGameUI::IsInBackgroundLevel()
+{
+ const char *levelName = engine->GetLevelName();
+ if (levelName && levelName[0] && engine->IsLevelMainMenuBackground())
+ {
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if we're in a multiplayer game
+//-----------------------------------------------------------------------------
+bool CGameUI::IsInMultiplayer()
+{
+ return (IsInLevel() && engine->GetMaxClients() > 1);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if we're playing back a replay
+//-----------------------------------------------------------------------------
+bool CGameUI::IsInReplay()
+{
+ return g_pEngineClientReplay && g_pEngineClientReplay->IsPlayingReplayDemo();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if we're console ui
+//-----------------------------------------------------------------------------
+bool CGameUI::IsConsoleUI()
+{
+ return m_bIsConsoleUI;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if we've saved without closing the menu
+//-----------------------------------------------------------------------------
+bool CGameUI::HasSavedThisMenuSession()
+{
+ return m_bHasSavedThisMenuSession;
+}
+
+void CGameUI::SetSavedThisMenuSession( bool bState )
+{
+ m_bHasSavedThisMenuSession = bState;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGameUI::ShowNewGameDialog( int chapter )
+{
+ char val[32];
+ Q_snprintf( val, sizeof(val), "%d", chapter);
+ staticPanel->OnOpenNewGameDialog(val);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Makes the loading background dialog visible, if one has been set
+//-----------------------------------------------------------------------------
+void CGameUI::ShowLoadingBackgroundDialog()
+{
+ if ( g_hLoadingBackgroundDialog )
+ {
+ vgui::ipanel()->SetParent( g_hLoadingBackgroundDialog, staticPanel->GetVPanel() );
+ vgui::ipanel()->PerformApplySchemeSettings( g_hLoadingBackgroundDialog );
+ vgui::ipanel()->SetVisible( g_hLoadingBackgroundDialog, true );
+ vgui::ipanel()->MoveToFront( g_hLoadingBackgroundDialog );
+ vgui::ipanel()->SendMessage( g_hLoadingBackgroundDialog, new KeyValues( "activate" ), staticPanel->GetVPanel() );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Hides the loading background dialog, if one has been set
+//-----------------------------------------------------------------------------
+void CGameUI::HideLoadingBackgroundDialog()
+{
+ if ( g_hLoadingBackgroundDialog )
+ {
+ vgui::ipanel()->SetParent( g_hLoadingBackgroundDialog, NULL );
+ vgui::ipanel()->SetVisible( g_hLoadingBackgroundDialog, false );
+ vgui::ipanel()->MoveToBack( g_hLoadingBackgroundDialog );
+ vgui::ipanel()->SendMessage( g_hLoadingBackgroundDialog, new KeyValues( "deactivate" ), staticPanel->GetVPanel() );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns whether a loading background dialog has been set
+//-----------------------------------------------------------------------------
+bool CGameUI::HasLoadingBackgroundDialog()
+{
+ return ( 0 != g_hLoadingBackgroundDialog );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Xbox 360 calls from engine to GameUI
+//-----------------------------------------------------------------------------
+void CGameUI::SessionNotification( const int notification, const int param )
+{
+ BasePanel()->SessionNotification( notification, param );
+}
+void CGameUI::SystemNotification( const int notification )
+{
+ BasePanel()->SystemNotification( notification );
+}
+void CGameUI::ShowMessageDialog( const uint nType, vgui::Panel *pOwner )
+{
+ BasePanel()->ShowMessageDialog( nType, pOwner );
+}
+void CGameUI::CloseMessageDialog( const uint nType )
+{
+ BasePanel()->CloseMessageDialog( nType );
+}
+void CGameUI::UpdatePlayerInfo( uint64 nPlayerId, const char *pName, int nTeam, byte cVoiceState, int nPlayersNeeded, bool bHost )
+{
+ BasePanel()->UpdatePlayerInfo( nPlayerId, pName, nTeam, cVoiceState, nPlayersNeeded, bHost );
+}
+void CGameUI::SessionSearchResult( int searchIdx, void *pHostData, XSESSION_SEARCHRESULT *pResult, int ping )
+{
+ BasePanel()->SessionSearchResult( searchIdx, pHostData, pResult, ping );
+}
+void CGameUI::OnCreditsFinished( void )
+{
+ BasePanel()->OnCreditsFinished();
+}
+bool CGameUI::ValidateStorageDevice( int *pStorageDeviceValidated )
+{
+ return BasePanel()->ValidateStorageDevice( pStorageDeviceValidated );
+}
+
+void CGameUI::SetProgressOnStart()
+{
+ m_bOpenProgressOnStart = true;
+}
+
+void CGameUI::OnConfirmQuit( void )
+{
+ BasePanel()->OnOpenQuitConfirmationDialog();
+}
+
+bool CGameUI::IsMainMenuVisible( void )
+{
+ CBasePanel *pBasePanel = BasePanel();
+ if ( pBasePanel )
+ return (pBasePanel->IsVisible() && pBasePanel->GetMenuAlpha() > 0 );
+ return false;
+}
+
+// Client DLL is providing us with a panel that it wants to replace the main menu with
+void CGameUI::SetMainMenuOverride( vgui::VPANEL panel )
+{
+ CBasePanel *pBasePanel = BasePanel();
+ if ( pBasePanel )
+ {
+ pBasePanel->SetMainMenuOverride( panel );
+ }
+}
+
+// Client DLL is telling us that a main menu command was issued, probably from its custom main menu panel
+void CGameUI::SendMainMenuCommand( const char *pszCommand )
+{
+ CBasePanel *pBasePanel = BasePanel();
+ if ( pBasePanel )
+ {
+ pBasePanel->RunMenuCommand( pszCommand );
+ }
+} \ No newline at end of file