//===== Copyright 1996-2005, 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" #elif OSX #include #endif #include "appframework/ilaunchermgr.h" #include #include #include #include #include #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 #include "vgui_controls/AnimationController.h" #include "vgui_vprofgraphpanel.h" #include "vgui_texturebudgetpanel.h" #include "vgui_budgetpanel.h" #include "Steam.h" // for SteamGetUser() #include "ivideomode.h" #include "cl_pluginhelpers.h" #include "cl_main.h" // CL_IsHL2Demo() #include "cl_steamauth.h" #include "inputsystem/iinputstacksystem.h" // interface to gameui dll #include #include // interface to expose vgui root panels #include #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 #include #include #include #include #include #include #include #include #include #include #include #include #include "IVguiModule.h" #include "vgui_baseui_interface.h" #include "vgui_DebugSystemPanel.h" #include "toolframework/itoolframework.h" #include "filesystem/IQueuedLoader.h" #include "LoadScreenUpdate.h" #include "tier0/etwprof.h" #if defined( _X360 ) #include "xbox/xbox_win32stubs.h" #endif #include "vgui_askconnectpanel.h" #include "tier1/tokenset.h" #if defined( INCLUDE_SCALEFORM ) #include "scaleformui/scaleformui.h" #endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" using namespace vgui; extern IVEngineClient *engineClient; extern HWND *pmainwindow; extern bool g_bTextMode; static int g_syncReportLevel = -1; static void VGui_PlaySound(const char *pFileName); void VGui_ActivateMouse(); extern CreateInterfaceFn g_AppSystemFactory; // functions to reference GameUI and GameConsole functions, from GameUI.dll IGameUI *staticGameUIFuncs = NULL; IGameUI* GetGameUI( void ) { return staticGameUIFuncs; } 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 ); // Tracks whether console window is open or not - true as soon as we receive the request to open it, until after it has shutdown ConVar cv_console_window_open( "console_window_open", NULL, FCVAR_HIDDEN, "Is the console window active" ); ConVar cv_ignore_ui_activate_key( "ignore_ui_activate_key", NULL, FCVAR_HIDDEN, "When set will ignore UI activation key" ); ConVar cv_vguipanel_active( "vgui_panel_active", NULL, FCVAR_HIDDEN, "Is a vgui panel currently active" ); ConVar cv_server_browser_dialog_open( "server_browser_dialog_open", NULL, FCVAR_HIDDEN, "Is the server browser window active" ); void Con_CreateConsolePanel( Panel *parent ); void CL_CreateEntityReportPanel( Panel *parent ); void ClearIOStates( void ); #ifdef IHV_DEMO // Enabled for IHV demos void CreateWatermarkPanel( Panel *parent ); #endif // turn this on if you're tuning progress bars // #define ENABLE_LOADING_PROGRESS_PROFILING #define PT( x ) #x, x static tokenset_t< LevelLoadingProgress_e > g_ProgressTokens[]= { { PT( PROGRESS_DEFAULT ) }, { PT( PROGRESS_NONE ) }, { PT( PROGRESS_CHANGELEVEL ) }, { PT( PROGRESS_SPAWNSERVER ) }, { PT( PROGRESS_LOADWORLDMODEL ) }, { PT( PROGRESS_CRCMAP ) }, { PT( PROGRESS_CRCCLIENTDLL ) }, { PT( PROGRESS_CREATENETWORKSTRINGTABLES ) }, { PT( PROGRESS_PRECACHEWORLD ) }, { PT( PROGRESS_CLEARWORLD ) }, { PT( PROGRESS_LEVELINIT ) }, { PT( PROGRESS_PRECACHE ) }, { PT( PROGRESS_ACTIVATESERVER ) }, { PT( PROGRESS_BEGINCONNECT ) }, { PT( PROGRESS_SIGNONCHALLENGE ) }, { PT( PROGRESS_SIGNONCONNECT ) }, { PT( PROGRESS_SIGNONCONNECTED ) }, { PT( PROGRESS_PROCESSSERVERINFO ) }, { PT( PROGRESS_PROCESSSTRINGTABLE ) }, { PT( PROGRESS_SIGNONNEW ) }, { PT( PROGRESS_SENDCLIENTINFO ) }, { PT( PROGRESS_SENDSIGNONDATA ) }, { PT( PROGRESS_SIGNONSPAWN ) }, { PT( PROGRESS_CREATEENTITIES ) }, { PT( PROGRESS_FULLYCONNECTED ) }, { PT( PROGRESS_PRECACHELIGHTING ) }, { PT( PROGRESS_READYTOPLAY ) }, { PT( PROGRESS_HIGHESTITEM ) }, { NULL, PROGRESS_INVALID } }; //----------------------------------------------------------------------------- // 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 EditablePanel { typedef EditablePanel BaseClass; public: CEnginePanel( Panel *pParent, const char *pName ) : BaseClass( pParent, pName ) { //m_bCanFocus = true; SetMouseInputEnabled( true ); SetKeyBoardInputEnabled( true ); } CEnginePanel( VPANEL parent, const char *pName ) : BaseClass( NULL, pName ) { SetParent( parent ); //m_bCanFocus = true; SetMouseInputEnabled( true ); SetKeyBoardInputEnabled( true ); } void EnableMouseFocus( bool state ) { //m_bCanFocus = state; SetMouseInputEnabled( state ); SetKeyBoardInputEnabled( state ); } }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CStaticPanel : public Panel { typedef Panel BaseClass; public: CStaticPanel( Panel *pParent, const char *pName ) : Panel( pParent, pName ) { SetCursor( dc_none ); SetKeyBoardInputEnabled( false ); SetMouseInputEnabled( false ); } }; vgui::VPanelHandle g_DrawTreeSelectedPanel; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CFocusOverlayPanel : public Panel { typedef Panel BaseClass; public: CFocusOverlayPanel( 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 ); bool DrawKeyFocusPanel( void ); }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CTransitionEffectPanel : public EditablePanel { typedef EditablePanel BaseClass; public: CTransitionEffectPanel( Panel *pParent, const char *pName ) : BaseClass( pParent, pName ) { SetBounds( 0, 0, videomode->GetModeWidth(), videomode->GetModeHeight() ); SetPaintBorderEnabled( false ); SetPaintBackgroundEnabled( false ); SetPaintEnabled( true ); SetVisible( true ); SetCursor( dc_none ); SetMouseInputEnabled( false ); SetKeyBoardInputEnabled( true ); } bool IsEffectEnabled() { return staticGameUIFuncs->IsTransitionEffectEnabled(); } }; //----------------------------------------------------------------------------- // // Purpose: Centerpoint for handling all user interface in the engine // //----------------------------------------------------------------------------- class CEngineVGui : public IEngineVGuiInternal { public: CEngineVGui(); ~CEngineVGui(); // Methods of IEngineVGui virtual 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( char const *levelName, bool bLocalServer ); virtual void OnLevelLoadingFinished(); virtual void NotifyOfServerConnect(const char *game, int IP, int connectionPort, int queryPort); virtual void NotifyOfServerDisconnect(); virtual void UpdateProgressBar(LevelLoadingProgress_e progress, bool showDialog = true ); virtual void UpdateCustomProgressBar( float progress, const wchar_t *desc ); virtual void StartCustomProgress(); virtual void FinishCustomProgress(); virtual void UpdateSecondaryProgressBarWithFile( float progress, const char *pDesc, int nBytesTotal ); virtual void UpdateSecondaryProgressBar( float progress, const wchar_t *desc ); virtual void StartLoadingScreenForCommand( const char* command ); virtual void StartLoadingScreenForKeyValues( KeyValues* keyValues ); 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; } virtual void HideLoadingPlaque( void ) { if ( scr_drawloading ) { OnLevelLoadingFinished(); S_OnLoadScreen( false ); } S_PreventSound(false);//it is now safe to use audio again. scr_disabled_for_loading = false; scr_drawloading = false; } void SetGameDLLPanelsVisible( bool show ) { if ( !staticGameDLLPanel ) { return; } staticGameDLLPanel->SetVisible( show ); } // Allows the level loading progress to show map-specific info virtual void SetProgressLevelName( const char *levelName ); virtual void OnToolModeChanged( bool bGameMode ); virtual InputContextHandle_t GetGameUIInputContext() { return m_hGameUIInputContext; } virtual void NeedConnectionProblemWaitScreen(); virtual void ShowPasswordUI( char const *pchCurrentPW ); void SetProgressBias( float bias ); void UpdateProgressBar( float progress, const char *pszDesc = NULL, bool showDialog = true ); virtual bool IsPlayingFullScreenVideo(); private: Panel *GetRootPanel( VGuiPanel_t type ); void SetEngineVisible( bool state ); void DrawMouseFocus( void ); void DrawKeyFocus( void ); void CreateVProfPanels( Panel *pParent ); void DestroyVProfPanels( ); void HideVProfPanels(); 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 ); void PreparePanel( Panel *panel, int nZPos, bool bVisible = true ); 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 *staticGameUIBackgroundPanel; CEnginePanel *staticGameDLLPanel; // Want engine tools to be on top of other engine panels CEnginePanel *staticEngineToolsPanel; CDebugSystemPanel *staticDebugSystemPanel; CEnginePanel *staticSteamOverlayPanel; CFocusOverlayPanel *staticFocusOverlayPanel; CTransitionEffectPanel *staticTransitionPanel; #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 m_LoadingProgress; bool m_bSaveProgress : 1; bool m_bNoShaderAPI : 1; // game ui hiding control bool m_bNotAllowedToHideGameUI : 1; bool m_bNotAllowedToShowGameUI : 1; IInputInternal *m_pInputInternal; // used to start the progress from an arbitrary position float m_ProgressBias; InputContextHandle_t m_hGameUIInputContext; IMaterial *m_pConstantColorMaterial; }; //----------------------------------------------------------------------------- // 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; m_flLastProgress = 0.0f; } void BeginProgress() { g_EngineVGuiImp.SetProgressBias( 0 ); m_SnappedProgress = 0; } void UpdateProgress( float progress, bool bForce ) { if ( !bForce ) { m_flLastProgress = progress; } if ( m_SnappedProgress == - 1 && !bForce ) { // not enabled return; } int snappedProgress = progress * 15; // Need excessive updates on the console to keep the XBox slider inny bar/XMB active if ( !IsGameConsole() && ( snappedProgress <= m_SnappedProgress ) ) { // prevent excessive updates return; } m_SnappedProgress = snappedProgress; // up to reserved g_EngineVGuiImp.UpdateProgressBar( bForce ? 1.0f : ( PROGRESS_RESERVE * progress ) ); } void EndProgress() { // the normal legacy bar now picks up after reserved region g_EngineVGuiImp.SetProgressBias( PROGRESS_RESERVE ); m_SnappedProgress = -1; } void PauseNonInteractiveProgress( bool bPause ) { PauseLoadingUpdates( bPause ); } private: int m_SnappedProgress; float m_flLastProgress; }; static CLoaderProgress s_LoaderProgress; //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CEngineVGui::CEngineVGui() { staticPanel = NULL; staticClientDLLToolsPanel = NULL; staticClientDLLPanel = NULL; staticGameDLLPanel = NULL; staticGameUIPanel = NULL; staticGameUIBackgroundPanel = NULL; staticEngineToolsPanel = NULL; staticDebugSystemPanel = NULL; staticSteamOverlayPanel = NULL; staticFocusOverlayPanel = NULL; staticTransitionPanel = NULL; m_hGameUIInputContext = INPUT_CONTEXT_HANDLE_INVALID; 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; m_pConstantColorMaterial = NULL; } //----------------------------------------------------------------------------- // Purpose: Destructor //----------------------------------------------------------------------------- CEngineVGui::~CEngineVGui() { } //----------------------------------------------------------------------------- // add all the base search paths used by VGUI (platform, skins directory, language dirs) //----------------------------------------------------------------------------- bool CEngineVGui::SetVGUIDirectories() { // add vgui skins directory last #if defined(_WIN32) if ( IsPC() ) { char temp[ 512 ]; char skin[128]; skin[0] = 0; Sys_GetRegKeyValue("Software\\Valve\\Steam", "Skin", skin, sizeof(skin), ""); if (strlen(skin) > 0) { sprintf( temp, "%s/platform/skins/%s", GetBaseDirectory(), skin ); g_pFileSystem->AddSearchPath( temp, "SKIN" ); } } #endif return true; } void CEngineVGui::PreparePanel( Panel *panel, int nZPos, bool bVisible /*= true*/ ) { panel->SetBounds( 0, 0, videomode->GetModeWidth(), videomode->GetModeHeight() ); panel->SetPaintBorderEnabled(false); panel->SetPaintBackgroundEnabled(false); panel->SetPaintEnabled(false); panel->SetVisible(true); panel->SetCursor( dc_none ); panel->SetVisible( bVisible ); panel->SetZPos( nZPos ); } //----------------------------------------------------------------------------- // Setup the base vgui panels //----------------------------------------------------------------------------- void CEngineVGui::Init() { const char *szDllName = ""; if ( CommandLine()->FindParm( "-gameuidll" ) ) { COM_TimestampedLog( "Loading gameui.dll" ); // load the GameUI dll szDllName = "gameui"; m_hStaticGameUIModule = g_pFileSystem->LoadModule(szDllName, "GAMEBIN", true); // LoadModule() does a GetLocalCopy() call m_GameUIFactory = Sys_GetFactory(m_hStaticGameUIModule); if ( !m_GameUIFactory ) { Error( "Could not load: %s\n", szDllName ); } } else { // Get the gameui interfaces from client.dll extern CreateInterfaceFn g_ClientFactory; m_GameUIFactory = g_ClientFactory; szDllName = "client"; } // 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 ); } } // Create UI Input contexts // NOTE: The GameUI context may or may not be used by the client // so we'll start it out disabled m_hGameUIInputContext = g_pInputStackSystem->PushInputContext(); g_pInputStackSystem->EnableInputContext( m_hGameUIInputContext, false ); InputContextHandle_t hVGuiInputContext = g_pInputStackSystem->PushInputContext(); g_pMatSystemSurface->SetInputContext( hVGuiInputContext ); VGui_InitMatSysInterfacesList( "BaseUI", &g_AppSystemFactory, 1 ); #ifdef OSX if ( Steam3Client().SteamApps() ) { // just follow the language steam wants you to be const char *lang = Steam3Client().SteamApps()->GetCurrentGameLanguage(); if ( lang && Q_strlen(lang) ) vgui::system()->SetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Language", lang ); } #endif 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 ( !scheme()->LoadSchemeFromFile( pStr, "Tracker" )) { Sys_Error( "Error loading file %s\n", pStr ); return; } if ( IsGameConsole() ) { 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( "ivgui()->Start()" ); // Start the App running ivgui()->Start(); ivgui()->SetSleep(false); bool bTools = CommandLine()->CheckParm( "-tools" ) != NULL; // 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: // Root -- staticPanel #if defined( TOOLFRAMEWORK_VGUI_REFACTOR ) // staticGameUIBackgroundPanel ( loading image only ) (zpos 0) // staticClientDLLPanel ( zpos == 25 ) // staticClientDLLPanelFullscreen ( zpos == 26 ) // staticGameUIPanel ( GameUI stuff, zpos 40 ) // staticClientDLLToolsPanel ( zpos == 28 ) // staticGameDLLPanel ( zpos == 50 ) [ Tool Framework Root ] // staticEngineToolsPanel ( zpos == 75 ) // staticDebugSystemPanel ( Engine debug stuff ) zpos == 125 ) // staticSteamOverlayPanel (STEAM OVERLAY ON PS3) zpos = 140 // staticFocusOverlayPanel (zpos == 150) #endif COM_TimestampedLog( "Building Panels (staticPanel)" ); staticPanel = new CStaticPanel( NULL, "staticPanel" ); staticPanel->SetParent( surface()->GetEmbeddedPanel() ); PreparePanel( staticPanel, 0 ); COM_TimestampedLog( "Building Panels (staticGameUIBackgroundPanel)" ); staticGameUIBackgroundPanel = new CEnginePanel( staticPanel, "GameUI Background Panel" ); PreparePanel( staticGameUIBackgroundPanel, 0 ); COM_TimestampedLog( "Building Panels (staticClientDLLPanel)" ); staticClientDLLPanel = new CEnginePanel( staticPanel, "staticClientDLLPanel" ); PreparePanel( staticClientDLLPanel, 25, false ); staticClientDLLPanel->SetKeyBoardInputEnabled( false ); // popups in the client DLL can enable this. // This panel has it's own animation controller, which makes it 1.1Mb to instance // which is too much on the console which doesn't support plugins anyway. if ( IsPC() ) { COM_TimestampedLog( "Building Panels (CreateAskConnectPanel)" ); CreateAskConnectPanel( staticPanel->GetVPanel() ); } COM_TimestampedLog( "Building Panels (staticClientDLLToolsPanel)" ); staticClientDLLToolsPanel = new CEnginePanel( staticPanel, "staticClientDLLToolsPanel" ); PreparePanel( staticClientDLLToolsPanel, 28 ); // popups in the client DLL can enable this. staticClientDLLToolsPanel->SetKeyBoardInputEnabled( false ); COM_TimestampedLog( "Building Panels (staticGameUIPanel)" ); staticGameUIPanel = new CEnginePanel( staticPanel, "GameUI Panel" ); #if defined( TOOLFRAMEWORK_VGUI_REFACTOR ) PreparePanel( staticGameUIPanel, 40 ); #else PreparePanel( staticGameUIPanel, 100 ); #endif COM_TimestampedLog( "Building Panels (staticGameDLLPanel)" ); staticGameDLLPanel = new CEnginePanel( staticPanel, "staticGameDLLPanel" ); #if defined( TOOLFRAMEWORK_VGUI_REFACTOR ) PreparePanel( staticGameDLLPanel, 50 ); #else PreparePanel( staticGameDLLPanel, 135 ); #endif staticGameDLLPanel->SetKeyBoardInputEnabled( false ); // popups in the game DLL can enable this. COM_TimestampedLog( "Building Panels (Engine Tools)" ); staticEngineToolsPanel = new CEnginePanel( bTools ? staticGameDLLPanel->GetVPanel() : staticPanel->GetVPanel(), "Engine Tools" ); #if defined( TOOLFRAMEWORK_VGUI_REFACTOR ) PreparePanel( staticEngineToolsPanel, 75 ); #else PreparePanel( staticEngineToolsPanel, 100 ); #endif staticEngineToolsPanel->SetKeyBoardInputEnabled( false ); // popups in the game DLL can enable this. staticEngineToolsPanel->SetMouseInputEnabled( false ); // popups in the game DLL can enable this. 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(); } COM_TimestampedLog( "Building Panels (staticTransitionPanel)" ); staticTransitionPanel = new CTransitionEffectPanel( staticPanel, "TransitionEffect" ); staticTransitionPanel->SetZPos( 135 ); if ( IsPS3() ) { COM_TimestampedLog( "Building Panels (staticSteamOverlayPanel)" ); staticSteamOverlayPanel = new CEnginePanel( staticPanel, "Steam Overlay" ); staticSteamOverlayPanel->SetZPos( 140 ); staticSteamOverlayPanel->SetKeyBoardInputEnabled( false ); staticSteamOverlayPanel->SetMouseInputEnabled( false ); } COM_TimestampedLog( "Building Panels (FocusOverlayPanel)" ); // Make sure this is on top of everything staticFocusOverlayPanel = new CFocusOverlayPanel( staticPanel, "FocusOverlayPanel" ); staticFocusOverlayPanel->SetBounds( 0, 0, videomode->GetModeWidth(), videomode->GetModeHeight() ); staticFocusOverlayPanel->SetZPos( 150 ); staticFocusOverlayPanel->MoveToFront(); COM_TimestampedLog( "Building Panels (console, entity report, drawtree, texturelist, vprof)" ); // Create engine vgui panels if ( IsPC() ) { #ifdef IHV_DEMO // if ( GetSteamUniverse() == k_EUniversePublic ) // IHV_DEMO - we must remove this before we publicly release // { // CreateWatermarkPanel( staticEngineToolsPanel ); // } #endif Con_CreateConsolePanel( staticEngineToolsPanel ); CL_CreateEntityReportPanel( staticEngineToolsPanel ); VGui_CreateDrawTreePanel( staticEngineToolsPanel ); CL_CreateTextureListPanel( staticEngineToolsPanel ); CreateVProfPanels( staticEngineToolsPanel ); } #ifndef _CERT else if ( IsGameConsole() ) { Con_CreateConsolePanel( staticEngineToolsPanel ); CL_CreateEntityReportPanel( staticEngineToolsPanel ); if ( IsX360() ) { CreateVProfPanels( staticGameDLLPanel ); } } #endif // !_CERT staticEngineToolsPanel->LoadControlSettings( "scripts/EngineVGuiLayout.res" ); // Loading the .res will show some panels which really should stay hidden HideVProfPanels(); COM_TimestampedLog( "materials->CacheUsedMaterials()" ); // This material is used by CPotteryWheelPanel::Paint() to copy stencil to the render target's alpha. Not sure of the best place to put it, but this needs to be done sometime before the used materials are precached. m_pConstantColorMaterial = materials->FindMaterial( "dev/constant_color", TEXTURE_GROUP_OTHER, true ); if ( m_pConstantColorMaterial ) { m_pConstantColorMaterial->IncrementReferenceCount(); } // 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" ); char szFileName[MAX_PATH]; // We also want to load the localization file for the base game. Nomrally, all these values would already be in valve_language.txt, but // with CSGO we decided to move them into csgo_language (which is NOT a mod). Q_snprintf( szFileName, sizeof( szFileName ) - 1, "resource/%s_%%language%%.txt", GetCurrentGame() ); szFileName[ sizeof( szFileName ) - 1 ] = '\0'; g_pVGuiLocalize->AddFile( szFileName ); // don't need to load the "valve" localization file twice // Each mod can 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. Q_snprintf( szFileName, sizeof( szFileName ) - 1, "resource/%s_%%language%%.txt", GetCurrentMod() ); szFileName[ sizeof( szFileName ) - 1 ] = '\0'; g_pVGuiLocalize->AddFile( szFileName ); // Load a low-violence-specific string file to override strings in the mod string file if ( g_bLowViolence ) { Q_snprintf( szFileName, sizeof( szFileName ) - 1, "resource/%s_%%language%%_lv.txt", GetCurrentMod() ); szFileName[ sizeof( szFileName ) - 1 ] = '\0'; g_pVGuiLocalize->AddFile( szFileName ); } COM_TimestampedLog( "staticGameUIFuncs->Initialize" ); staticGameUIFuncs->Initialize( g_GameSystemFactory ); COM_TimestampedLog( "staticGameUIFuncs->Start" ); staticGameUIFuncs->Start(); // setup console if ( staticGameConsole ) { staticGameConsole->Initialize(); #if defined( TOOLFRAMEWORK_VGUI_REFACTOR ) staticGameConsole->SetParent(staticEngineToolsPanel->GetVPanel()); #elif !defined (CSTRIKE15) staticGameConsole->SetParent(staticGameUIPanel->GetVPanel()); #endif } if ( IsGameConsole() ) { // 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" ) ? true : false; } void CEngineVGui::PostInit() { staticGameUIFuncs->PostInit(); #if defined( _GAMECONSOLE ) g_pMatSystemSurface->ClearTemporaryFontCache(); #endif } //----------------------------------------------------------------------------- // Purpose: connects interfaces in gameui //----------------------------------------------------------------------------- void CEngineVGui::Connect() { m_pInputInternal = (IInputInternal *)g_GameSystemFactory( VGUI_INPUTINTERNAL_INTERFACE_VERSION, NULL ); staticGameUIFuncs->Connect( g_GameSystemFactory ); #if OSX // g_pLauncherMgr = (ILauncherMgr *)g_GameSystemFactory( COCOAMGR_INTERFACE_VERSION, NULL ); #endif #if LINUX // g_pLauncherMgr = (ILauncherMgr *)g_GameSystemFactory( LINUXMGR_INTERFACE_VERSION, NULL ); #endif #if defined( _WIN32 ) && defined( DX_TO_GL_ABSTRACTION ) // g_pLauncherMgr = (ILauncherMgr *)g_GameSystemFactory( WINMGR_INTERFACE_VERSION, NULL ); #endif } //----------------------------------------------------------------------------- // Create/destroy the vprof panels //----------------------------------------------------------------------------- void CEngineVGui::CreateVProfPanels( Panel *pParent ) { #ifdef _CERT if ( IsGameConsole() ) return; #endif #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::HideVProfPanels() { #ifdef _CERT if ( IsGameConsole() ) return; #endif #ifdef VPROF_ENABLED m_pVProfPanel->SetVisible( false ); m_pBudgetPanel->SetVisible( false ); HideVProfGraphPanel(); m_pTextureBudgetPanel->SetVisible( false ); #endif } void CEngineVGui::DestroyVProfPanels( ) { #ifdef _CERT if ( IsGameConsole() ) return; #endif #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 ( m_pConstantColorMaterial ) { m_pConstantColorMaterial->DecrementReferenceCount(); m_pConstantColorMaterial = NULL; } if ( IsPC() && CL_IsHL2Demo() ) // if they are playing the demo then open the storefront on shutdown { 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( (VPANEL)0 ); } if ( staticGameConsole ) { staticGameConsole->Shutdown(); staticGameConsole = NULL; } staticGameUIPanel = NULL; staticClientDLLToolsPanel = NULL; staticClientDLLPanel = NULL; staticEngineToolsPanel = NULL; staticDebugSystemPanel = NULL; staticSteamOverlayPanel = NULL; staticFocusOverlayPanel = NULL; staticGameDLLPanel = NULL; // This will delete the engine subpanel since it's a child delete staticPanel; staticPanel = NULL; // Give panels a chance to settle so things // Marked for deletion will actually get deleted { FORCE_DEFAULT_SPLITSCREEN_PLAYER_GUARD; ivgui()->RunFrame(); } // unload the gameUI staticGameUIFuncs->Shutdown(); staticGameUIFuncs = NULL; // stop the App running ivgui()->Stop(); // Disable the input contexts if ( m_hGameUIInputContext != INPUT_CONTEXT_HANDLE_INVALID ) { g_pMatSystemSurface->SetInputContext( INPUT_CONTEXT_HANDLE_INVALID ); g_pInputStackSystem->PopInputContext(); // VGui g_pInputStackSystem->PopInputContext(); // GameUI m_hGameUIInputContext = INPUT_CONTEXT_HANDLE_INVALID; } // unload the dll if ( m_hStaticGameUIModule ) { Sys_UnloadModule(m_hStaticGameUIModule); } m_hStaticGameUIModule = NULL; m_GameUIFactory = NULL; m_pInputInternal = NULL; } //----------------------------------------------------------------------------- // Purpose: Retrieve specified root panel //----------------------------------------------------------------------------- inline 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; case PANEL_GAMEUIBACKGROUND: return staticGameUIBackgroundPanel; case PANEL_TRANSITIONEFFECT: return staticTransitionPanel; case PANEL_STEAMOVERLAY: return staticSteamOverlayPanel; } } 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: Shows any GameUI related panels //----------------------------------------------------------------------------- void CEngineVGui::ActivateGameUI() { if ( m_bNotAllowedToShowGameUI ) return; if (!staticGameUIFuncs) return; // clear any keys that might be stuck down ClearIOStates(); staticGameUIPanel->SetVisible(true); staticGameUIBackgroundPanel->SetVisible( true ); staticGameUIPanel->MoveToFront(); staticClientDLLPanel->SetVisible(false); staticClientDLLPanel->SetMouseInputEnabled(false); surface()->SetCursor( dc_arrow ); //staticGameDLLPanel->SetVisible( true ); //staticGameDLLPanel->SetMouseInputEnabled( true ); SetEngineVisible( false ); staticGameUIFuncs->OnGameUIActivated(); //Reapplying this hack so that the game doesn't pause when the player opens up the menu. //This existed initially but was removed with the Portal 2 integration. #if defined( CSTRIKE15 ) if ( sv.IsPlayingSoloAgainstBots() ) { Cbuf_AddText( Cbuf_GetCurrentPlayer(), "pause\n" ); } #endif } //----------------------------------------------------------------------------- // Purpose: Hides an Game UI related features (not client UI stuff tho!) //----------------------------------------------------------------------------- bool CEngineVGui::HideGameUI() { if ( m_bNotAllowedToHideGameUI ) return false; if (!staticGameUIFuncs) return false; const char *levelName = engineClient->GetLevelName(); bool bInNonBgLevel = levelName && levelName[0] && !engineClient->IsLevelMainMenuBackground(); if ( bInNonBgLevel ) { staticGameUIPanel->SetVisible(false); staticGameUIBackgroundPanel->SetVisible( false ); #if !defined( TOOLFRAMEWORK_VGUI_REFACTOR ) staticGameUIPanel->SetPaintBackgroundEnabled(false); #endif staticClientDLLPanel->SetVisible(true); staticClientDLLPanel->MoveToFront(); staticClientDLLPanel->SetMouseInputEnabled(true); //staticGameDLLPanel->SetVisible( false ); //staticGameDLLPanel->SetMouseInputEnabled(false); SetEngineVisible( true ); staticGameUIFuncs->OnGameUIHidden(); } #if defined (CSTRIKE15) // Decouple the pause menu and console window: ensure we hide the console when the game UI is hidden (eg. when we hit ESC key) HideConsole(); #endif // CSTRIKE15 // 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 ) || sv.IsPlayingSoloAgainstBots() ) && engineClient->IsPaused() ) { Cbuf_AddText(Cbuf_GetCurrentPlayer(), "unpause\n"); } VGui_MoveDrawTreePanelToFront(); return true; } //----------------------------------------------------------------------------- // Purpose: Hides the game console (but not the complete GameUI!) //----------------------------------------------------------------------------- void CEngineVGui::HideConsole() { if ( IsGameConsole() ) return; if ( staticGameConsole ) { staticGameConsole->Hide(); } } //----------------------------------------------------------------------------- // Purpose: shows the console //----------------------------------------------------------------------------- void CEngineVGui::ShowConsole() { if ( IsGameConsole() ) return; if ( staticGameConsole ) { staticGameConsole->Activate(); } } //----------------------------------------------------------------------------- // Purpose: returns true if the console is currently open //----------------------------------------------------------------------------- bool CEngineVGui::IsConsoleVisible() { if ( IsPC() ) { return 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, 5, 0, "#LoadingProgress_SpawningServer" }, { PROGRESS_LOADWORLDMODEL, 8, 5, "#LoadingProgress_LoadMap" }, { PROGRESS_CREATENETWORKSTRINGTABLES, 12, 0, NULL }, { PROGRESS_PRECACHEWORLD, 15, 0, "#LoadingProgress_PrecacheWorld" }, { PROGRESS_CLEARWORLD, 16, 20, NULL }, { PROGRESS_LEVELINIT, 20, 200, "#LoadingProgress_LoadResources" }, { PROGRESS_ACTIVATESERVER, 50, 0, NULL }, { PROGRESS_SIGNONCHALLENGE, 51, 0, "#LoadingProgress_Connecting" }, { PROGRESS_SIGNONCONNECT, 55, 0, NULL }, { PROGRESS_SIGNONCONNECTED, 56, 1, "#LoadingProgress_SignonLocal" }, { PROGRESS_PROCESSSERVERINFO, 58, 0, NULL }, { PROGRESS_PROCESSSTRINGTABLE, 60, 3, NULL }, // 16 { PROGRESS_SIGNONNEW, 63, 200, NULL }, { PROGRESS_SENDCLIENTINFO, 80, 1, NULL }, { PROGRESS_SENDSIGNONDATA, 81, 1, "#LoadingProgress_SignonDataLocal" }, { PROGRESS_SIGNONSPAWN, 83, 10, NULL }, { PROGRESS_CREATEENTITIES, 85, 3, NULL }, { PROGRESS_FULLYCONNECTED, 86, 0, NULL }, { PROGRESS_PRECACHELIGHTING, 87, 50, NULL }, { PROGRESS_READYTOPLAY, 95, 100, 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, 11, 0, NULL }, { PROGRESS_PROCESSSERVERINFO, 12, 0, "#LoadingProgress_ProcessServerInfo" }, { PROGRESS_PROCESSSTRINGTABLE, 15, 3, NULL }, { PROGRESS_LOADWORLDMODEL, 20, 14, "#LoadingProgress_LoadMap" }, { PROGRESS_SIGNONNEW, 30, 200, "#LoadingProgress_PrecacheWorld" }, { PROGRESS_SENDCLIENTINFO, 60, 1, "#LoadingProgress_SendClientInfo" }, { PROGRESS_SENDSIGNONDATA, 64, 1, "#LoadingProgress_SignonData" }, { PROGRESS_SIGNONSPAWN, 65, 10, NULL }, { PROGRESS_CREATEENTITIES, 85, 3, NULL }, { PROGRESS_FULLYCONNECTED, 86, 0, NULL }, { PROGRESS_PRECACHELIGHTING, 87, 50, NULL }, { PROGRESS_READYTOPLAY, 95, 100, NULL }, { PROGRESS_HIGHESTITEM, 100, 0, NULL }, }; static LoadingProgressDescription_t *g_pLoadingProgressDescriptions = NULL; //----------------------------------------------------------------------------- // Purpose: returns current progress point description //----------------------------------------------------------------------------- LoadingProgressDescription_t &GetProgressDescription(LevelLoadingProgress_e eProgress) { // search for the item in the current list int i = 0; while ( true ) { // find the closest match if (g_pLoadingProgressDescriptions[i].eProgress >= eProgress) return g_pLoadingProgressDescriptions[i]; if ( g_pLoadingProgressDescriptions[i].eProgress == PROGRESS_HIGHESTITEM ) break; ++i; } // not found return g_pLoadingProgressDescriptions[0]; } //----------------------------------------------------------------------------- // Purpose: transition handler //----------------------------------------------------------------------------- void CEngineVGui::OnLevelLoadingStarted( char const *levelName, bool bLocalServer ) { 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 ( IsGameConsole() || IsPC() ) { // TCR requirement, always!!! m_bShowProgressDialog = true; } // we've starting loading a level/connecting to a server staticGameUIFuncs->OnLevelLoadingStarted( levelName, 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 ( !bLocalServer ) { // we're connecting g_pLoadingProgressDescriptions = g_RemoteConnectLoadingProgressDescriptions; } else { g_pLoadingProgressDescriptions = g_ListenServerLoadingProgressDescriptions; } if ( m_bShowProgressDialog ) { ActivateGameUI(); } m_bShowProgressDialog = false; } void CEngineVGui::StartLoadingScreenForCommand( const char* command ) { staticGameUIFuncs->StartLoadingScreenForCommand( command ); } void CEngineVGui::StartLoadingScreenForKeyValues( KeyValues* keyValues ) { staticGameUIFuncs->StartLoadingScreenForKeyValues( keyValues ); } //----------------------------------------------------------------------------- // 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%2d/%50.50s\t%.3f\t\ttime: %d%%\t\tinterp: %d%%\t\trepeat: %d\n", m_LoadingProgress[i].eProgress, g_ProgressTokens->GetNameByToken( m_LoadingProgress[i].eProgress ), flTimeTaken, nPerc, nInterpPerc, nRepeatCount); // reset accumlated vars nRepeatCount = 0; flTimeTaken = 0.0f; } #endif // ENABLE_LOADING_PROGRESS_PROFILING // 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 //----------------------------------------------------------------------------- #define LOADING_PRESENT_UPDATE_INTERVAL 0.05f double g_flLastUpdateTime = 0.0f; void CEngineVGui::UpdateProgressBar( LevelLoadingProgress_e progress, bool showDialog ) { if (!staticGameUIFuncs) return; if ( !ThreadInMainThread() ) return; // Don't update in tools mode; it renders the tools too, which takes forever! if ( toolframework->InToolMode() ) return; if (!g_pLoadingProgressDescriptions) return; // don't go backwards if (progress < m_eLastProgressPoint) return; bool bNewCheckpoint = progress != m_eLastProgressPoint; // Early time-based throttle for UpdateProgressBar double t = Plat_FloatTime(); float dt = t - g_flLastUpdateTime; if ( ( !bNewCheckpoint && ( dt < LOADING_PRESENT_UPDATE_INTERVAL ) ) || g_pMaterialSystem->IsInFrame() ) { return; } #if defined(ENABLE_LOADING_PROGRESS_PROFILING) if ( dt > 0.5f ) { Msg( "%f msec gap in %s\n", 1000.0f * dt, g_ProgressTokens->GetNameByToken( progress ) ); } // 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 // count progress repeats if ( !bNewCheckpoint ) { ++m_nLastProgressPointRepeatCount; #if defined(ENABLE_LOADING_PROGRESS_PROFILING) //if ( !( m_nLastProgressPointRepeatCount % 500 ) ) { Msg( "Repeating %s [%d] at %f\n", g_ProgressTokens->GetNameByToken( progress ), m_nLastProgressPointRepeatCount, t - m_flLoadingStartTime ); } #endif } else { m_nLastProgressPointRepeatCount = 0; #if defined(ENABLE_LOADING_PROGRESS_PROFILING) Msg( "Entering %s at %f\n", g_ProgressTokens->GetNameByToken( progress ), t - m_flLoadingStartTime ); #endif } // 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((LevelLoadingProgress_e)((int)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; // Send loading progress to the server GetBaseLocalClient().SendLoadingProgress( (int)(flPerc * 100) ); UpdateProgressBar( flPerc, desc.pszDesc, showDialog ); // Help with profiling load times. ETWMarkPrintf( "UpdateProgressBar to %s, stage %d, took %1.3f s", desc.pszDesc, progress, Plat_FloatTime() - g_flLastUpdateTime ); m_eLastProgressPoint = progress; // NOTE: It is necessary to re-read time, since Refresh // may block, and if it does, it'll force a refresh every allocation // if we don't resample time after the block g_flLastUpdateTime = Plat_FloatTime(); } //----------------------------------------------------------------------------- // Purpose: Updates progress //----------------------------------------------------------------------------- void CEngineVGui::UpdateCustomProgressBar( float progress, const wchar_t *desc ) { char ansi[1024]; g_pVGuiLocalize->ConvertUnicodeToANSI( desc, ansi, sizeof( ansi ) ); UpdateProgressBar( progress, ansi ); } void CEngineVGui::StartCustomProgress() { if (!staticGameUIFuncs) return; // we've starting loading a level/connecting to a server staticGameUIFuncs->OnLevelLoadingStarted( NULL, 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, const char *pDesc, bool showDialog ) { if ( !staticGameUIFuncs ) return; bool bUpdated = staticGameUIFuncs->UpdateProgressBar( progress, pDesc ? pDesc : "", showDialog ); if ( staticGameUIFuncs->LoadingProgressWantsIsolatedRender( false ) ) { while ( staticGameUIFuncs->LoadingProgressWantsIsolatedRender( true ) ) { extern void V_RenderVGuiOnly(); V_RenderVGuiOnly(); if ( g_ClientGlobalVariables.frametime != 0.0f && g_ClientGlobalVariables.frametime != 0.1f) { static ConVarRef host_timescale( "host_timescale" ); float timeScale = host_timescale.GetFloat() * sv.GetTimescale(); if ( timeScale <= 0.0f ) timeScale = 1.0f; g_pScaleformUI->RunFrame( g_ClientGlobalVariables.frametime / timeScale ); } else { break; } } } else if ( bUpdated ) { g_pScaleformUI->RunFrame( 0 ); // re-render vgui on screen extern void V_RenderVGuiOnly(); V_RenderVGuiOnly(); } } void CEngineVGui::UpdateSecondaryProgressBarWithFile( float progress, const char *pPath, int nBytesTotal ) { if ( !pPath ) return; char szFile[MAX_PATH]; V_strcpy_safe( szFile, pPath ); //V_StripFilename(szFile); wchar_t wszPercent[ 10 ]; V_snwprintf( wszPercent, ARRAYSIZE( wszPercent ), L"%d%%", (int)(100*progress) ); wchar_t wszMegs[ 64 ]; char szBytes[32]; V_strcpy_safe( szBytes, V_pretifymem(nBytesTotal) ); V_strtowcs( szBytes, -1, wszMegs, ARRAYSIZE( wszMegs ) ); wchar_t wszFile[ MAX_PLAYER_NAME_LENGTH ]; g_pVGuiLocalize->ConvertANSIToUnicode( szFile, wszFile, sizeof( wszFile ) ); wchar_t szWideBuff[ 256 ]; g_pVGuiLocalize->ConstructString( szWideBuff, sizeof( szWideBuff ), g_pVGuiLocalize->Find( "#SFUI_DownLoading_" ), 3, wszFile, wszPercent, wszMegs ); UpdateSecondaryProgressBar( progress, szWideBuff ); } void CEngineVGui::UpdateSecondaryProgressBar( float progress, const wchar_t *desc ) { if ( !staticGameUIFuncs ) return; bool bUpdated = staticGameUIFuncs->UpdateSecondaryProgressBar( progress, desc ? desc : L"" ); if ( staticGameUIFuncs->LoadingProgressWantsIsolatedRender( false ) ) { while ( staticGameUIFuncs->LoadingProgressWantsIsolatedRender( true ) ) { extern void V_RenderVGuiOnly(); V_RenderVGuiOnly(); if ( g_ClientGlobalVariables.frametime != 0.0f && g_ClientGlobalVariables.frametime != 0.1f) { static ConVarRef host_timescale( "host_timescale" ); float timeScale = host_timescale.GetFloat() * sv.GetTimescale(); if ( timeScale <= 0.0f ) timeScale = 1.0f; g_pScaleformUI->RunFrame( g_ClientGlobalVariables.frametime / timeScale ); } else { break; } } } else if ( bUpdated ) { g_pScaleformUI->RunFrame( 0 ); // 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_ButtonPressed ) || ( event.m_nType == IE_ButtonDoubleClicked ); ButtonCode_t code = (ButtonCode_t)event.m_nData; if ( IsPC() && IsShiftKeyDown() ) { switch( code ) { case KEY_F1: if ( bDown ) { Cbuf_AddText( Cbuf_GetCurrentPlayer(), "debugsystemui" ); } return true; case KEY_F2: if ( bDown ) { Cbuf_AddText( Cbuf_GetCurrentPlayer(), "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 event.m_nType != IE_ButtonReleased; #endif // ESCAPE toggles game ui bool isConsole = IsX360() || IsPS3(); ButtonCode_t uiToggleKey = isConsole ? KEY_XBUTTON_START : KEY_ESCAPE; ButtonCode_t baseButtonCode = GetBaseButtonCode( code ); // make sure PS3 supports the console default press (START) or ESCAPE bool isUIToggleKey = ( baseButtonCode == uiToggleKey ) || ( IsPS3() && baseButtonCode == KEY_ESCAPE ) ; // Hitting the Start button on any xbox controller brings up the game ui, so translate to base code space if ( bDown && isUIToggleKey ) { if ( IsPC() ) { if ( cv_console_window_open.GetBool() ) { HideConsole(); } else if ( IsGameUIVisible() ) { // gameui_hide on console start button but not ESC key. if ( baseButtonCode != KEY_ESCAPE ) { // Don't allow hiding of the game ui if there's no level const char *pLevelName = engineClient->GetLevelName(); if ( pLevelName && pLevelName[0] ) { Cbuf_AddText( Cbuf_GetCurrentPlayer(), "gameui_hide" ); if ( IsDebugSystemVisible() ) { Cbuf_AddText( Cbuf_GetCurrentPlayer(), "debugsystemui 0" ); } } } } else if ( !cv_ignore_ui_activate_key.GetBool() ) { Cbuf_AddText( Cbuf_GetCurrentPlayer(), "gameui_activate" ); } return true; } if ( IsGameConsole() && !IsGameUIVisible() ) { // console UI does not toggle, engine does "show", but UI needs to handle "hide" Cbuf_AddText( Cbuf_GetCurrentPlayer(), "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 event.m_nType != IE_ButtonReleased; // don't trap key up events } return false; } void CEngineVGui::Simulate() { if ( IsGameConsole() && r_drawvgui.GetInt() == 0 ) { return; } toolframework->VGui_PreSimulateAllTools(); if ( staticPanel ) { VPROF_BUDGET( "CEngineVGui::Simulate", "VGUI_Simulate" ); // 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) GetAnimationController()->UpdateAnimations( Sys_FloatTime() ); int w, h; #if defined( USE_SDL ) || defined( OSX ) uint width,height; g_pLauncherMgr->RenderedSize( width, height, false ); // false = get w = width; h = height; #elif defined( WIN32 ) if ( ::IsIconic( *pmainwindow ) ) { w = videomode->GetModeWidth(); h = videomode->GetModeHeight(); } else { RECT rect; ::GetClientRect(*pmainwindow, &rect); w = rect.right; h = rect.bottom; } #elif defined( _PS3 ) g_pMaterialSystem->GetBackBufferDimensions( w, h ); #else #error #endif // don't hold this reference over RunFrame() { CMatRenderContextPtr pRenderContext( materials ); pRenderContext->Viewport( 0, 0, w, h ); } staticGameUIFuncs->RunFrame(); surface()->CalculateMouseVisible(); { FORCE_DEFAULT_SPLITSCREEN_PLAYER_GUARD; ivgui()->RunFrame(); } // Some debugging helpers DrawMouseFocus(); DrawKeyFocus(); VGui_UpdateDrawTreePanel(); VGui_UpdateTextureListPanel(); VGui_ActivateMouse(); } toolframework->VGui_PostSimulateAllTools(); } void CEngineVGui::BackwardCompatibility_Paint() { Paint( (PaintMode_t)(PAINT_UIPANELS | PAINT_INGAMEPANELS) ); } class CVGuiPaintHelper { public: void AddUIPanel( VPANEL panel ); void Paint( VPANEL rootPanel, PaintMode_t mode ); private: struct Entry_t { bool m_bWasVisible; VPANEL m_pVPanel; VPANEL m_Parent; }; typedef void (CVGuiPaintHelper::*mapFunc)( Entry_t &entry ); void MapOverEntries( mapFunc mapper ); // Mapping functions void MapHide( Entry_t &entry ); void MapRestore( Entry_t &entry ); void MapPaintTraverse( Entry_t &entry ); CUtlVector< Entry_t > m_Entries; }; void CVGuiPaintHelper::AddUIPanel( VPANEL panel ) { Entry_t e; e.m_pVPanel = panel; e.m_bWasVisible = ipanel()->IsVisible( panel ); e.m_Parent = ipanel()->GetParent( panel ); m_Entries.AddToTail( e ); } void CVGuiPaintHelper::MapOverEntries( mapFunc mapper ) { for ( int i = 0; i < m_Entries.Count(); ++i ) { (this->*mapper)( m_Entries[ i ] ); } } void CVGuiPaintHelper::MapHide( Entry_t &entry ) { ipanel()->SetVisible( entry.m_pVPanel, false ); } void CVGuiPaintHelper::MapRestore( Entry_t &entry ) { ipanel()->SetVisible( entry.m_pVPanel, entry.m_bWasVisible ); } void CVGuiPaintHelper::MapPaintTraverse( Entry_t &entry ) { ipanel()->SetParent( entry.m_pVPanel, 0 ); surface()->PaintTraverseEx( entry.m_pVPanel, true ); ipanel()->SetParent( entry.m_pVPanel, entry.m_Parent ); } void CVGuiPaintHelper::Paint( VPANEL rootPanel, PaintMode_t mode ) { if ( mode & PAINT_UIPANELS ) { MapOverEntries( &CVGuiPaintHelper::MapHide ); surface()->PaintTraverseEx( rootPanel, true ); MapOverEntries( &CVGuiPaintHelper::MapRestore ); } if ( mode & PAINT_INGAMEPANELS ) { bool bSaveVisible = ipanel()->IsVisible( rootPanel ); ipanel()->SetVisible( rootPanel, false ); MapOverEntries( &CVGuiPaintHelper::MapPaintTraverse ); ipanel()->SetVisible( rootPanel, bSaveVisible ); } } //----------------------------------------------------------------------------- // 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 VPANEL pVPanel = surface()->GetEmbeddedPanel(); if ( !pVPanel ) return; bool drawVgui = IsGameConsole() ? ( r_drawvgui.GetInt() == 1 ) : 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; } int w, h; #if defined( USE_SDL ) || defined ( OSX ) uint width,height; g_pLauncherMgr->RenderedSize( width, height, false ); // false = get w = width; h = height; #elif defined( WIN32 ) if ( ::IsIconic( *pmainwindow ) ) { w = videomode->GetModeWidth(); h = videomode->GetModeHeight(); } else { RECT rect; ::GetClientRect(*pmainwindow, &rect); w = rect.right; h = rect.bottom; } #elif defined( _PS3 ) g_pMaterialSystem->GetBackBufferDimensions( w, h ); #else #error #endif Panel *panel = staticPanel; panel->SetBounds(0, 0, w, h); panel->Repaint(); toolframework->VGui_PreRenderAllTools( mode ); // Paint both ( backward compatibility support ) CVGuiPaintHelper helper; VPANEL fullscreenClientDLLPanel = ClientDLL_GetFullscreenClientDLLVPanel(); switch( mode ) { case PAINT_UIPANELS: { // AddUIPanel excludes the 2 non-fullscreen panels from rendering in this pass int childcount = ipanel()->GetChildCount( staticClientDLLPanel->GetVPanel() ); for ( int i = 0; i < childcount; i++ ) { // child always returns null, not in the same module! VPANEL child = ipanel()->GetChild( staticClientDLLPanel->GetVPanel(), i ); if ( child && child != fullscreenClientDLLPanel ) { helper.AddUIPanel( child ); } } } break; case PAINT_INGAMEPANELS: { int childcount = ipanel()->GetChildCount( staticClientDLLPanel->GetVPanel() ); for ( int i = 0; i < childcount; i++ ) { // child always returns null, not in the same module! VPANEL child = ipanel()->GetChild( staticClientDLLPanel->GetVPanel(), i ); if ( child && child != fullscreenClientDLLPanel ) { int iMessageContext = ipanel()->GetMessageContextId( child ); if ( iMessageContext == splitscreen->GetActiveSplitScreenPlayerSlot() ) { helper.AddUIPanel( child ); } } } } break; default: break; } #if defined( TOOLFRAMEWORK_VGUI_REFACTOR ) helper.AddUIPanel( staticGameUIPanel->GetVPanel() ); #endif helper.AddUIPanel( staticClientDLLToolsPanel->GetVPanel() ); // Prevent Steam Overlay from rendering prematurely if ( staticSteamOverlayPanel ) { ipanel()->SetVisible( staticSteamOverlayPanel->GetVPanel(), false ); } if ( staticTransitionPanel ) { ipanel()->SetVisible( staticTransitionPanel->GetVPanel(), false ); } // It's either the full screen, or just the client .dll stuff helper.Paint( pVPanel, mode ); if ( staticTransitionPanel && ( mode & PAINT_UIPANELS ) && staticTransitionPanel->IsEffectEnabled() ) { ipanel()->SetVisible( staticTransitionPanel->GetVPanel(), true ); VPANEL vPanelRememberParent = ipanel()->GetParent( staticTransitionPanel->GetVPanel() ); ipanel()->SetParent( staticTransitionPanel->GetVPanel(), 0 ); surface()->PaintTraverseEx( staticTransitionPanel->GetVPanel(), false ); ipanel()->SetParent( staticTransitionPanel->GetVPanel(), vPanelRememberParent ); } // Paint Steam Overlay if ( staticSteamOverlayPanel && ( mode & PAINT_UIPANELS ) ) { ipanel()->SetVisible( staticSteamOverlayPanel->GetVPanel(), true ); VPANEL vPanelRememberParent = ipanel()->GetParent( staticSteamOverlayPanel->GetVPanel() ); ipanel()->SetParent( staticSteamOverlayPanel->GetVPanel(), 0 ); surface()->PaintTraverseEx( staticSteamOverlayPanel->GetVPanel(), false ); ipanel()->SetParent( staticSteamOverlayPanel->GetVPanel(), vPanelRememberParent ); } 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 ( !input() ) return false; return input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ); } bool CEngineVGui::IsAltKeyDown( void ) { if ( !input() ) return false; return input()->IsKeyDown( KEY_LALT ) || input()->IsKeyDown( KEY_RALT ); } bool CEngineVGui::IsCtrlKeyDown( void ) { if ( !input() ) return false; return input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ); } //----------------------------------------------------------------------------- // Purpose: notification //----------------------------------------------------------------------------- void CEngineVGui::NotifyOfServerConnect(const char *game, int IP, int connectionPort, int queryPort) { if (!staticGameUIFuncs) return; staticGameUIFuncs->OnConnectToServer2(game, IP, connectionPort, queryPort); } //----------------------------------------------------------------------------- // Purpose: notification //----------------------------------------------------------------------------- void CEngineVGui::NotifyOfServerDisconnect() { if (!staticGameUIFuncs) return; staticGameUIFuncs->OnDisconnectFromServer( g_eSteamLoginFailure ); g_eSteamLoginFailure = 0; } //----------------------------------------------------------------------------- // A helper to play sounds through vgui //----------------------------------------------------------------------------- void VGui_PlaySound( const char *pFileName ) { //Put '+' on the front of sounds to make them play without spatialization. char buf[2048]; Q_snprintf( buf, sizeof( buf ), "%c%s", '+', pFileName ); // Point at origin if they didn't specify a sound source. Vector vDummyOrigin; vDummyOrigin.Init(); CSfxTable *pSound = (CSfxTable*)S_PrecacheSound( buf ); if ( pSound ) { S_MarkUISound( pSound ); ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 ); StartSoundParams_t params; params.staticsound = IsGameConsole() ? true : false; params.soundsource = GetLocalClient().GetViewEntity(); 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 ( 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< VPANEL > g_FocusPanelList; ConVar vgui_drawfocus( "vgui_drawfocus", "0", 0, "Report which panel is under the mouse." ); VPANEL g_KeyFocusPanel = NULL; ConVar vgui_drawkeyfocus( "vgui_drawkeyfocus", "0", 0, "Report which panel has keyboard focus." ); CFocusOverlayPanel::CFocusOverlayPanel( Panel *pParent, const char *pName ) : 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, insetX, insetY; if ( IsX360() || !IsPS3() ) { // Required Xbox360 Title safe is TCR documented at inner 90% (RED) insetX = 0.05f * backBufferWidth; 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 Xbox360 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 ); } else if ( IsPS3() ) { // Required PS3 Title Safe is TCR documented at inner 85% (RED) insetX = 0.075f * backBufferWidth; insetY = 0.075f * 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 ); } return true; } void CFocusOverlayPanel::PostChildPaint( void ) { BaseClass::PostChildPaint(); bool bNeedsMoveToFront = false; if ( g_DrawTreeSelectedPanel ) { int x, y, x1, y1; ipanel()->GetClipRect( g_DrawTreeSelectedPanel, x, y, x1, y1 ); surface()->DrawSetColor( Color( 255, 0, 0, 255 ) ); surface()->DrawOutlinedRect( x, y, x1, y1 ); bNeedsMoveToFront = true; } if ( DrawTitleSafeOverlay() ) { bNeedsMoveToFront = true; } if ( DrawFocusPanelList() ) { bNeedsMoveToFront = true; } if ( DrawKeyFocusPanel() ) { bNeedsMoveToFront = true; } if ( bNeedsMoveToFront ) { // will be valid for the next frame MoveToFront(); } } bool CFocusOverlayPanel::DrawKeyFocusPanel( void ) { if( !vgui_drawkeyfocus.GetBool() ) return false; if ( g_KeyFocusPanel ) { int x, y, x1, y1; ipanel()->GetClipRect( g_KeyFocusPanel, x, y, x1, y1 ); if ( (x1 - x) == videomode->GetModeWidth() && (y1 - y) == videomode->GetModeHeight() ) { x++; y++; x1--; y1--; } const int FOCUS_BLINK_PERIOD = 500; if ( system()->GetTimeMillis() % FOCUS_BLINK_PERIOD > FOCUS_BLINK_PERIOD/2 ) { surface()->DrawSetColor( Color( 0, 0, 0, 255 ) ); } else { surface()->DrawSetColor( Color( 255, 255, 255, 255 ) ); } surface()->DrawOutlinedRect( x, y, x1, y1 ); } return true; } bool CFocusOverlayPanel::DrawFocusPanelList( void ) { if( !vgui_drawfocus.GetBool() ) return false; int c = g_FocusPanelList.Count(); if ( c <= 0 ) return false; int slot = 0; int fullscreeninset = 0; for ( int i = 0; i < c; i++ ) { if ( slot > 31 ) break; VPANEL vpanel = g_FocusPanelList[ i ]; if ( !vpanel ) continue; if ( !ipanel()->IsFullyVisible( vpanel ) ) return false; // Convert panel bounds to screen space int r, g, b; GetColorForSlot( slot, r, g, b ); int x, y, x1, y1; ipanel()->GetClipRect( vpanel, x, y, x1, y1 ); if ( (x1 - x) == videomode->GetModeWidth() && (y1 - y) == videomode->GetModeHeight() ) { x += fullscreeninset; y += fullscreeninset; x1 -= fullscreeninset; y1 -= fullscreeninset; fullscreeninset++; } surface()->DrawSetColor( Color( r, g, b, 255 ) ); surface()->DrawOutlinedRect( x, y, x1, y1 ); slot++; } return true; } static void VGui_RecursiveFindPanels( CUtlVector< VPANEL >& panelList, VPANEL check, char const *panelname ) { Panel *panel = ipanel()->GetPanel( check, "ENGINE" ); if ( !panel ) return; if ( StringHasPrefixCaseSensitive( panel->GetName(), panelname ) ) { panelList.AddToTail( panel->GetVPanel() ); } int childcount = panel->GetChildCount(); for ( int i = 0; i < childcount; i++ ) { Panel *child = panel->GetChild( i ); VGui_RecursiveFindPanels( panelList, child->GetVPanel(), panelname ); } } void VGui_FindNamedPanels( CUtlVector< VPANEL >& panelList, char const *panelname ) { VPANEL embedded = surface()->GetEmbeddedPanel(); // faster version of code below // checks through each popup in order, top to bottom windows int c = surface()->GetPopupCount(); for (int i = c - 1; i >= 0; i--) { VPANEL popup = 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< VPANEL > panelList; VGui_FindNamedPanels( panelList, panelname ); if ( !panelList.Count() ) { ConMsg( "No panels starting with %s\n", panelname ); return; } for ( int i = 0; i < panelList.Count(); i++ ) { VPANEL p = panelList[ i ]; if ( !p ) continue; Panel *panel = 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< VPANEL >& panelList, int x, int y, VPANEL check, bool include_hidden ) { if( !include_hidden && !ipanel()->IsVisible( check ) ) { return; } if ( ipanel()->IsWithinTraverse( check, x, y, false ) ) { if ( panelList.Find( check ) == panelList.InvalidIndex() ) panelList.AddToTail( check ); } int childcount = ipanel()->GetChildCount( check ); for ( int i = 0; i < childcount; i++ ) { VPANEL child = ipanel()->GetChild( check, i ); VGui_RecursePanel( panelList, x, y, child, include_hidden ); } } void CEngineVGui::DrawKeyFocus( void ) { VPROF( "CEngineVGui::DrawKeyFocus" ); if ( !vgui_drawkeyfocus.GetBool() ) return; staticFocusOverlayPanel->MoveToFront(); g_KeyFocusPanel = input()->GetFocus(); } 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; input()->GetCursorPos( x, y ); VPANEL embedded = surface()->GetEmbeddedPanel(); if ( surface()->IsCursorVisible() && surface()->IsWithin(x, y) ) { // faster version of code below // checks through each popup in order, top to bottom windows int c = surface()->GetPopupCount(); for (int i = c - 1; i >= 0; i--) { VPANEL popup = surface()->GetPopup(i); if ( !popup ) continue; if ( popup == embedded ) continue; if ( !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.Count(); int slot = 0; for ( int i = 0; i < c; i++ ) { if ( slot > 31 ) break; 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; bool bThisOne = false; if ( input()->GetMouseFocus() == vpanel ) { bThisOne = true; } Con_NXPrintf( &np, "%s %3i: %s(vpanel%d)(ctx%d)\n", bThisOne ? "-->" : " ", slot + 1, ipanel()->GetName(vpanel), vpanel, ipanel()->GetMessageContextId( vpanel ) ); slot++; } while ( slot <= 31 ) { Con_NPrintf( slot, "" ); slot++; } } void VGui_SetGameDLLPanelsVisible( bool show ) { EngineVGui()->SetGameDLLPanelsVisible( show ); } void CEngineVGui::SetProgressLevelName( const char *levelName ) { // staticGameUIFuncs->SetProgressLevelName( levelName ); } void CEngineVGui::OnToolModeChanged( bool bGameMode ) { //#if defined( TOOLFRAMEWORK_VGUI_REFACTOR ) staticEngineToolsPanel->SetParent( bGameMode ? staticPanel->GetVPanel() : staticGameDLLPanel->GetVPanel() ); staticEngineToolsPanel->SetMouseInputEnabled( false ); staticEngineToolsPanel->SetKeyBoardInputEnabled( false ); //#endif } void CEngineVGui::NeedConnectionProblemWaitScreen() { return staticGameUIFuncs->NeedConnectionProblemWaitScreen(); } void CEngineVGui::ShowPasswordUI( char const *pchCurrentPW ) { // staticGameUIFuncs->ShowPasswordUI( pchCurrentPW ); } bool CEngineVGui::IsPlayingFullScreenVideo() { return staticGameUIFuncs->IsPlayingFullScreenVideo(); } //----------------------------------------------------------------------------- // Dump the panel hierarchy //----------------------------------------------------------------------------- void DumpPanels_r( VPANEL panel, int level, bool bVisibleOnly ) { int i; const char *pName = ipanel()->GetName( panel ); bool bVisible = ipanel()->IsVisible( panel ); if ( bVisibleOnly && !bVisible ) { // cull return; } char indentBuff[32]; for ( i = 0; i < level; i++ ) { indentBuff[i] = '.'; } indentBuff[i] = '\0'; ConMsg( "%s%s%s\n", indentBuff, pName[0] ? pName : "???", bVisible ? " (Visible)" : " (Not Visible)" ); int childcount = ipanel()->GetChildCount( panel ); for ( i = 0; i < childcount; i++ ) { VPANEL child = ipanel()->GetChild( panel, i ); DumpPanels_r( child, level+1, bVisibleOnly ); } } CON_COMMAND( vgui_dump_panels, "vgui_dump_panels [visible]" ) { bool bVisibleOnly = ( args.ArgC() == 2 ) && ( !V_stricmp( args[1], "visible" ) ); VPANEL embedded = surface()->GetEmbeddedPanel(); DumpPanels_r( embedded, 0, bVisibleOnly ); }