|
|
//========= Copyright 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "cbase.h"
#include "basemodpanel.h"
#include "uigamedata.h"
#include "./GameUI/IGameUI.h"
#include "ienginevgui.h"
#include "engine/ienginesound.h"
#include "EngineInterface.h"
#include "tier0/dbg.h"
#include "ixboxsystem.h"
#include "GameUI_Interface.h"
#include "game/client/IGameClientExports.h"
#include "gameui/igameconsole.h"
#include "inputsystem/iinputsystem.h"
#include "FileSystem.h"
#include "filesystem/IXboxInstaller.h"
#ifdef _GAMECONSOLE
#include "xbox/xbox_launch.h"
#endif
#include "gameconsole.h"
#include "vgui/ISystem.h"
#include "vgui/ISurface.h"
#include "vgui/ILocalize.h"
#include "vgui_controls/AnimationController.h"
#include "vguimatsurface/imatsystemsurface.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imesh.h"
#include "tier0/icommandline.h"
#include "fmtstr.h"
#include "smartptr.h"
// Embedded GameUI
#include "../gameui.h"
#include "game_controls/igameuisystemmgr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace BaseModUI; using namespace vgui;
//setup in GameUI_Interface.cpp
extern class IMatchSystem *matchsystem; extern const char *COM_GetModDirectory( void ); extern IGameConsole *IGameConsole();
//=============================================================================
CBaseModPanel* CBaseModPanel::m_CFactoryBasePanel = 0;
#ifndef _CERT
#ifdef _GAMECONSOLE
ConVar ui_gameui_debug( "ui_gameui_debug", "1" ); #else
ConVar ui_gameui_debug( "ui_gameui_debug", "0", FCVAR_RELEASE ); #endif
int UI_IsDebug() { return (*(int *)(&ui_gameui_debug)) ? ui_gameui_debug.GetInt() : 0; } #endif
#if defined( _GAMECONSOLE )
static void InstallStatusChanged( IConVar *pConVar, const char *pOldValue, float flOldValue ) { // spew out status
if ( ((ConVar *)pConVar)->GetBool() && g_pXboxInstaller ) { g_pXboxInstaller->SpewStatus(); } } ConVar xbox_install_status( "xbox_install_status", "0", 0, "Show install status", InstallStatusChanged ); #endif
// Use for show demos to force the correct campaign poster
ConVar demo_campaign_name( "demo_campaign_name", "L4D2C5", FCVAR_DEVELOPMENTONLY, "Short name of campaign (i.e. L4D2C5), used to show correct poster in demo mode." );
ConVar ui_lobby_noresults_create_msg_time( "ui_lobby_noresults_create_msg_time", "2.5", FCVAR_DEVELOPMENTONLY );
//=============================================================================
void SetGameUiEmbeddedScreen( char const *szBaseName ) { if ( !szBaseName || !*szBaseName ) { g_pGameUISystemMgr->ReleaseAllGameUIScreens(); g_pGameUISystemMgr->SetGameUIVisible( false ); return; }
IGameUISystem *pGameUiSystem = g_pGameUISystemMgr->LoadGameUIScreen( KeyValues::AutoDeleteInline( new KeyValues( szBaseName ) ) ); pGameUiSystem; g_pGameUISystemMgr->SetGameUIVisible( true ); }
//=============================================================================
CBaseModPanel::CBaseModPanel(): BaseClass(0, "CBaseModPanel"), m_bClosingAllWindows( false ), m_lastActiveUserId( 0 ) { #if !defined( _GAMECONSOLE ) && !defined( NOSTEAM )
// Set Steam overlay position
if ( steamapicontext && steamapicontext->SteamUtils() ) { steamapicontext->SteamUtils()->SetOverlayNotificationPosition( k_EPositionTopRight ); }
// Set special DLC parameters mask
static ConVarRef mm_dlcs_mask_extras( "mm_dlcs_mask_extras" ); if ( mm_dlcs_mask_extras.IsValid() && steamapicontext && steamapicontext->SteamUtils() ) { int iDLCmask = mm_dlcs_mask_extras.GetInt();
// Low Violence and Germany (or bordering countries) = CS.GUNS
char const *cc = steamapicontext->SteamUtils()->GetIPCountry(); char const *ccGuns = ":DE:DK:PL:CZ:AT:CH:FR:LU:BE:NL:"; if ( engine->IsLowViolence() && Q_stristr( ccGuns, CFmtStr( ":%s:", cc ) ) ) { // iDLCmask |= ( 1 << ? );
}
// PreOrder DLC AppId Ownership = BAT
if ( steamapicontext->SteamApps()->BIsSubscribedApp( 565 ) ) { // iDLCmask |= ( 1 << ? );
}
mm_dlcs_mask_extras.SetValue( iDLCmask ); }
#endif
MakePopup( false );
Assert(m_CFactoryBasePanel == 0); m_CFactoryBasePanel = this;
g_pVGuiLocalize->AddFile( "Resource/basemodui_%language%.txt"); g_pVGuiLocalize->AddFile( "Resource/basemodui_tu_%language%.txt" );
m_LevelLoading = false; // delay 3 frames before doing activation on initialization
// needed to allow engine to exec startup commands (background map signal is 1 frame behind)
m_DelayActivation = 3;
m_UIScheme = vgui::scheme()->LoadSchemeFromFileEx( 0, "resource/BaseModScheme.res", "BaseModScheme" ); SetScheme( m_UIScheme );
// Only one user on the PC, so set it now
SetLastActiveUserId( IsPC() ? 0 : -1 );
// Precache critical font characters for the 360, dampens severity of these runtime i/o hitches
IScheme *pScheme = vgui::scheme()->GetIScheme( m_UIScheme ); m_hDefaultFont = pScheme->GetFont( "Default", true ); vgui::surface()->PrecacheFontCharacters( m_hDefaultFont, NULL ); vgui::surface()->PrecacheFontCharacters( pScheme->GetFont( "DefaultBold", true ), NULL ); vgui::surface()->PrecacheFontCharacters( pScheme->GetFont( "DefaultLarge", true ), NULL ); vgui::surface()->PrecacheFontCharacters( pScheme->GetFont( "FrameTitle", true ), NULL );
m_bWarmRestartMode = false; m_ExitingFrameCount = 0;
m_flBlurScale = 0; m_flLastBlurTime = 0;
// Background movie
m_BIKHandle = BIKHANDLE_INVALID; m_pMovieMaterial = NULL; m_flU0 = m_flV0 = m_flU1 = m_flV1 = 0.0f; m_bMovieFailed = false;
m_iBackgroundImageID = -1; m_iFadeToBackgroundImageID = -1;
m_backgroundMusic = ""; m_nBackgroundMusicGUID = 0; m_bFadeMusicUp = false;
m_flMovieFadeInTime = 0; m_iMovieTransitionImage = 0;
// Subscribe to event notifications
g_pMatchFramework->GetEventsSubscription()->Subscribe( this ); }
//=============================================================================
CBaseModPanel::~CBaseModPanel() { // Unsubscribe from event notifications
g_pMatchFramework->GetEventsSubscription()->Unsubscribe( this );
Assert(m_CFactoryBasePanel == this); m_CFactoryBasePanel = 0;
// Free our movie resources
ShutdownBackgroundMovie();
surface()->DestroyTextureID( m_iBackgroundImageID ); surface()->DestroyTextureID( m_iFadeToBackgroundImageID );
// Shutdown UI game data
CUIGameData::Shutdown(); }
//=============================================================================
CBaseModPanel& CBaseModPanel::GetSingleton() { Assert(m_CFactoryBasePanel != 0); return *m_CFactoryBasePanel; }
//=============================================================================
CBaseModPanel* CBaseModPanel::GetSingletonPtr() { return m_CFactoryBasePanel; }
//=============================================================================
void CBaseModPanel::ReloadScheme() { }
bool CBaseModPanel::IsLevelLoading() { return m_LevelLoading; }
#if defined( _GAMECONSOLE ) && defined( _DEMO )
void CBaseModPanel::OnDemoTimeout() { if ( !engine->IsInGame() && !engine->IsConnected() && !engine->IsDrawingLoadingImage() ) { // exit is terminal and unstoppable
StartExitingProcess( false ); } else { engine->ExecuteClientCmd( "disconnect" ); } } #endif
bool CBaseModPanel::ActivateBackgroundEffects() { // PC needs to keep start music, can't loop MP3's
if ( IsPC() && !IsBackgroundMusicPlaying() ) { StartBackgroundMusic( 1.0f ); m_bFadeMusicUp = false; }
// bring up the video if we haven't before
if ( m_BIKHandle == BIKHANDLE_INVALID ) { if ( !InitBackgroundMovie() ) { // couldn't start movie, don't do the music either
return false; } if ( IsGameConsole() && !IsBackgroundMusicPlaying() ) { // only xbox's fades non-playing music up
m_bFadeMusicUp = StartBackgroundMusic( 0 ); } else { m_bFadeMusicUp = false; }
m_flMovieFadeInTime = 0; }
return true; }
//=============================================================================
void CBaseModPanel::OnGameUIActivated() { if ( UI_IsDebug() ) { Msg( "[GAMEUI] CBaseModPanel::OnGameUIActivated( delay = %d )\n", m_DelayActivation ); }
if ( m_DelayActivation ) { return; }
COM_TimestampedLog( "CBaseModPanel::OnGameUIActivated()" );
#if defined( _GAMECONSOLE )
if ( !engine->IsInGame() && !engine->IsConnected() && !engine->IsDrawingLoadingImage() ) { #if defined( _DEMO )
if ( engine->IsDemoExiting() ) { // just got activated, maybe from a disconnect
// exit is terminal and unstoppable
SetVisible( true ); StartExitingProcess( false ); return; } #endif
if ( !GameUI().IsInLevel() && !GameUI().IsInBackgroundLevel() ) { // not using a background map
// start the menu movie and music now, as the main menu is about to open
// these are very large i/o operations on the xbox
// they must occur before the installer takes over the DVD
// otherwise the transfer rate is so slow and we sync stall for 10-15 seconds
ActivateBackgroundEffects(); } // the installer runs in the background during the main menu
g_pXboxInstaller->Start();
#if defined( _DEMO )
// ui valid can now adhere to demo timeout rules
engine->EnableDemoTimeout( true ); #endif
} #endif
SetVisible( true );
if ( !IsGameConsole() && IsLevelLoading() ) { // Ignore UI activations when loading poster is up
return; } else if ( ( !m_LevelLoading && !engine->IsConnected() ) || GameUI().IsInBackgroundLevel() ) { OpenFrontScreen(); } else if ( engine->IsConnected() && !m_LevelLoading ) { SetGameUiEmbeddedScreen( "ingamemenu" ); } }
void CBaseModPanel::OpenFrontScreen() { char const *szScreen = NULL; #ifdef _GAMECONSOLE
// make sure we are in the startup menu.
if ( !GameUI().IsInBackgroundLevel() ) { engine->ClientCmd( "startupmenu" ); }
if ( g_pMatchFramework->GetMatchSession() ) { Warning( "CBaseModPanel::OpenFrontScreen during active game ignored!\n" ); return; }
if( XBX_GetNumGameUsers() > 0 ) { if ( 0 ) // ( CL4DFrame *pAttractScreen = GetWindow( WT_ATTRACTSCREEN ) )
{ szScreen = "attractscreen"; } else { szScreen = "mainmenu"; } } else { szScreen = "attractscreen"; } #else
szScreen = "mainmenu"; #endif // _GAMECONSOLE
if( szScreen ) { SetGameUiEmbeddedScreen( NULL ); // TEMP HACK: only devconsole interferes with this event being fired multiple times in main menu
// need a better fix for devconsole to be a little smarter about gameui activation events
SetGameUiEmbeddedScreen( szScreen ); } }
//=============================================================================
void CBaseModPanel::OnGameUIHidden() { if ( UI_IsDebug() ) { Msg( "[GAMEUI] CBaseModPanel::OnGameUIHidden()\n" ); }
#if defined( _GAMECONSOLE )
// signal the installer to stop
g_pXboxInstaller->Stop(); #endif
SetVisible(false);
// Close all gameui screens
SetGameUiEmbeddedScreen( NULL );
// Free the movie resouces
ShutdownBackgroundMovie(); }
//=============================================================================
void CBaseModPanel::RunFrame() { if ( s_NavLock > 0 ) { --s_NavLock; }
GetAnimationController()->UpdateAnimations( Plat_FloatTime() );
CUIGameData::Get()->RunFrame();
if ( m_DelayActivation ) { m_DelayActivation--; if ( !m_LevelLoading && !m_DelayActivation ) { if ( UI_IsDebug() ) { Msg( "[GAMEUI] Executing delayed UI activation\n"); } OnGameUIActivated(); } }
bool bDoBlur = true; bDoBlur = false; #if 0 // TODO: UI: determine blur
WINDOW_TYPE wt = GetActiveWindowType(); switch ( wt ) { case WT_NONE: case WT_MAINMENU: case WT_LOADINGPROGRESSBKGND: case WT_LOADINGPROGRESS: case WT_AUDIOVIDEO: bDoBlur = false; break; } if ( GetWindow( WT_ATTRACTSCREEN ) || ( enginevguifuncs && !enginevguifuncs->IsGameUIVisible() ) ) { // attract screen might be open, but not topmost due to notification dialogs
bDoBlur = false; } #endif
if ( !bDoBlur ) { bDoBlur = GameClientExports()->ClientWantsBlurEffect(); }
float nowTime = Plat_FloatTime(); float deltaTime = nowTime - m_flLastBlurTime; if ( deltaTime > 0 ) { m_flLastBlurTime = nowTime; m_flBlurScale += deltaTime * bDoBlur ? 0.05f : -0.05f; m_flBlurScale = clamp( m_flBlurScale, 0, 0.85f ); engine->SetBlurFade( m_flBlurScale ); }
if ( IsGameConsole() && m_ExitingFrameCount ) { #if 0 // TODO: UI: CTransitionScreen
CTransitionScreen *pTransitionScreen = static_cast< CTransitionScreen* >( GetWindow( WT_TRANSITIONSCREEN ) ); if ( pTransitionScreen && pTransitionScreen->IsTransitionComplete() ) { // totally obscured, safe to shutdown movie
ShutdownBackgroundMovie();
if ( m_ExitingFrameCount > 1 ) { m_ExitingFrameCount--; if ( m_ExitingFrameCount == 1 ) { // enough frames have transpired, send the single shot quit command
if ( m_bWarmRestartMode ) { // restarts self, skips any intros
engine->ClientCmd_Unrestricted( "quit_x360 restart\n" ); } else { // cold restart, quits to any startup app
engine->ClientCmd_Unrestricted( "quit_x360\n" ); } } } } #endif
} }
//=============================================================================
void CBaseModPanel::OnLevelLoadingStarted( char const *levelName, bool bShowProgressDialog ) { Assert( !m_LevelLoading );
#if defined( _GAMECONSOLE )
// stop the installer
g_pXboxInstaller->Stop(); g_pXboxInstaller->SpewStatus();
// If the installer has finished while we are in the menus, then this is the ONLY place we
// know that there is no open files and we can redirect the search paths
if ( g_pXboxInstaller->ForceCachePaths() ) { // the search paths got changed
// notify other systems who may have hooked absolute paths
engine->SearchPathsChangedAfterInstall(); } #endif
// close all UI screens
SetGameUiEmbeddedScreen( NULL );
// Stop the background movie
ShutdownBackgroundMovie();
DevMsg( 2, "[GAMEUI] OnLevelLoadingStarted - opening loading progress (%s)...\n", levelName ? levelName : "<< no level specified >>" );
//
// If playing on listen server then "levelName" is set to the map being loaded,
// so it is authoritative - it might be a background map or a real level.
//
if ( levelName ) { // Derive the mission info from the server game details
KeyValues *pGameSettings = g_pMatchFramework->GetMatchNetworkMsgController()->GetActiveServerGameDetails( NULL ); if ( !pGameSettings ) { // In this particular case we need to speculate about game details
// this happens when user types "map c5m2 versus easy" from console, so there's no
// active server spawned yet, nor is the local client connected to any server.
// We have to force server DLL to apply the map command line to the settings and then
// speculatively construct the settings key.
if ( IServerGameDLL *pServerDLL = ( IServerGameDLL * ) g_pMatchFramework->GetMatchExtensions()->GetRegisteredExtensionInterface( INTERFACEVERSION_SERVERGAMEDLL ) ) { KeyValues *pApplyServerSettings = new KeyValues( "::ExecGameTypeCfg" ); KeyValues::AutoDelete autodelete_pApplyServerSettings( pApplyServerSettings );
pApplyServerSettings->SetString( "map/mapname", levelName );
pServerDLL->ApplyGameSettings( pApplyServerSettings ); }
// Now we can retrieve all the settings from convars here!
static ConVarRef r_mp_gamemode( "mp_gamemode" ); if ( r_mp_gamemode.IsValid() ) { pGameSettings = new KeyValues( "CmdLineSettings" ); pGameSettings->SetString( "game/mode", r_mp_gamemode.GetString() ); } } KeyValues::AutoDelete autodelete_pGameSettings( pGameSettings ); if ( pGameSettings ) { // It is critical to get map info by the actual levelname that is being loaded, because
// for level transitions the server is still in the old map and the game settings returned
// will reflect the old state of the server.
// - pChapterInfo = g_pMatchExtPortal2->GetMapInfoByBspName( pGameSettings, levelName, &pMissionInfo );
// - Q_strncpy( chGameMode, pGameSettings->GetString( "game/mode", "" ), ARRAYSIZE( chGameMode ) );
}
// Let the ui nuggets know the loading map
IGameUIScreenControllerFactory *pFactory = g_pGameUISystemMgr->GetScreenControllerFactory( "loadingprogress" ); if ( pFactory && pFactory->GetControllerInstancesCount() ) { KeyValues *kvEvent = new KeyValues( "OnLevelLoadingProgress" ); KeyValues::AutoDelete autodelete_kvEvent( kvEvent ); kvEvent->SetString( "map", levelName ); kvEvent->SetFloat( "progress", 0.0f );
for ( int j = 0; j < pFactory->GetControllerInstancesCount(); ++ j ) { pFactory->GetControllerInstance(j)->BroadcastEventToScreens( kvEvent ); } } } m_LevelLoading = true;
// Bring up the level loading screen
SetGameUiEmbeddedScreen( "loadingbar" ); }
void CBaseModPanel::OnEngineLevelLoadingSession( KeyValues *pEvent ) { #if 0 // TODO: UI: OnEngineLevelLoadingSession
// We must keep the default loading poster because it will be replaced by
// the real campaign loading poster shortly
float flProgress = 0.0f; if ( LoadingProgress *pLoadingProgress = static_cast<LoadingProgress*>( GetWindow( WT_LOADINGPROGRESS ) ) ) { flProgress = pLoadingProgress->GetProgress(); pLoadingProgress->Close(); m_Frames[ WT_LOADINGPROGRESS ] = NULL; } CloseAllWindows( CLOSE_POLICY_DEFAULT );
// Pop up a fake bkgnd poster
if ( LoadingProgress *pLoadingProgress = static_cast<LoadingProgress*>( OpenWindow( WT_LOADINGPROGRESSBKGND, NULL ) ) ) { pLoadingProgress->SetLoadingType( LoadingProgress::LT_POSTER ); pLoadingProgress->SetProgress( flProgress ); } #endif
}
//=============================================================================
void CBaseModPanel::OnLevelLoadingFinished( KeyValues *kvEvent ) { int bError = kvEvent->GetInt( "error" ); const char *failureReason = kvEvent->GetString( "reason" ); Assert( m_LevelLoading );
if ( UI_IsDebug() ) { Msg( "[GAMEUI] CBaseModPanel::OnLevelLoadingFinished( %s, %s )\n", bError ? "Had Error" : "No Error", failureReason ); }
#if defined( _GAMECONSOLE )
if ( GameUI().IsInBackgroundLevel() ) { // start the installer when running the background map has finished
g_pXboxInstaller->Start(); } #endif
// Let the ui nuggets know
IGameUIScreenControllerFactory *pFactory = g_pGameUISystemMgr->GetScreenControllerFactory( "loadingprogress" ); if ( pFactory && pFactory->GetControllerInstancesCount() ) { KeyValues *kvEvent = new KeyValues( "OnLevelLoadingProgress" ); KeyValues::AutoDelete autodelete_kvEvent( kvEvent ); kvEvent->SetFloat( "progress", 1.0f );
for ( int j = 0; j < pFactory->GetControllerInstancesCount(); ++ j ) { pFactory->GetControllerInstance(j)->BroadcastEventToScreens( kvEvent ); } }
// Close all embedded gameui screens
SetGameUiEmbeddedScreen( NULL );
m_LevelLoading = false;
// - CBaseModFrame *pFrame = CBaseModPanel::GetSingleton().GetWindow( WT_GENERICCONFIRMATION );
// - if ( !pFrame )
{ // no confirmation up, hide the UI
GameUI().HideGameUI(); }
#if 0 // TODO: UI: handle errors after loading
// if we are loading into the lobby, then skip the UIActivation code path
// this can happen if we accepted an invite to player who is in the lobby while we were in-game
if ( WT_GAMELOBBY != GetActiveWindowType() ) { // if we are loading into the front-end, then activate the main menu (or attract screen, depending on state)
// or if a message box is pending force open game ui
if ( GameUI().IsInBackgroundLevel() || pFrame ) { GameUI().OnGameUIActivated(); } }
if ( bError ) { GenericConfirmation* pMsg = ( GenericConfirmation* ) OpenWindow( WT_GENERICCONFIRMATION, NULL, false ); if ( pMsg ) { GenericConfirmation::Data_t data; data.pWindowTitle = "#L4D360UI_MsgBx_DisconnectedFromServer"; data.bOkButtonEnabled = true; data.pMessageText = failureReason; pMsg->SetUsageData( data ); } } #endif
}
class CMatchSessionCreationAsyncOperation : public IMatchAsyncOperation { public: CMatchSessionCreationAsyncOperation() : m_eState( AOS_RUNNING ) {}
public: virtual bool IsFinished() { return false; } virtual AsyncOperationState_t GetState() { return m_eState; } virtual uint64 GetResult() { return 0ull; } virtual void Abort(); virtual void Release() { Assert( 0 ); } // we are a global object, cannot release
public: IMatchAsyncOperation * Prepare() { m_eState = AOS_RUNNING; return this; }
protected: AsyncOperationState_t m_eState; } g_MatchSessionCreationAsyncOperation;
void CMatchSessionCreationAsyncOperation::Abort() { m_eState = AOS_ABORTING; Assert( g_pMatchFramework->GetMatchSession() ); g_pMatchFramework->CloseSession();
#if 0 // TODO: UI: Abort session create
CBaseModPanel::GetSingleton().CloseAllWindows(); CBaseModPanel::GetSingleton().OpenFrontScreen(); #endif
}
void CBaseModPanel::OnEvent( KeyValues *pEvent ) { char const *szEvent = pEvent->GetName();
if ( !Q_stricmp( "OnMatchSessionUpdate", szEvent ) ) { char const *szState = pEvent->GetString( "state", "" ); if ( !Q_stricmp( "ready", szState ) ) { // Session has finished creating:
IMatchSession *pSession = g_pMatchFramework->GetMatchSession(); if ( !pSession ) return;
KeyValues *pSettings = pSession->GetSessionSettings(); if ( !pSettings ) return;
char const *szNetwork = pSettings->GetString( "system/network", "" ); int numLocalPlayers = pSettings->GetInt( "members/numPlayers", 1 ); // TODO: UI: session has been created!
// - WINDOW_TYPE wtGameLobby = WT_GAMELOBBY;
if ( !Q_stricmp( "offline", szNetwork ) && numLocalPlayers <= 1 ) { // We have a single-player offline session
// - wtGameLobby = WT_GAMESETTINGS;
}
// We have created a session
// - CloseAllWindows();
// Special case when we are creating a public session after empty search
if ( !Q_stricmp( pSettings->GetString( "options/createreason" ), "searchempty" ) && !Q_stricmp( pSettings->GetString( "system/access" ), "public" ) ) { // We are creating a public lobby after our search turned out empty
char const *szWaitScreenText = "#Matchmaking_NoResultsCreating"; REFERENCE(szWaitScreenText); // - CUIGameData::Get()->OpenWaitScreen( szWaitScreenText, ui_lobby_noresults_create_msg_time.GetFloat() );
// - CUIGameData::Get()->CloseWaitScreen( NULL, NULL );
// Delete the "createreason" key from the session settings
pSession->UpdateSessionSettings( KeyValues::AutoDeleteInline( KeyValues::FromString( "delete", " delete { options { createreason delete } } " ) ) ); }
// - CBaseModFrame *pLobbyWindow = OpenWindow( wtGameLobby, NULL, true, pSettings ); // derive from session
// - if ( CBaseModFrame *pWaitScreen = GetWindow( WT_GENERICWAITSCREEN ) )
{ // Normally "CloseAllWindows" above would take down the waitscreen, but
// we could pop it up for the special case of empty search results
// - pWaitScreen->SetNavBack( pLobbyWindow );
}
// Check for a special case when we lost connection to host and that's why we are going to lobby
if ( KeyValues *pOnEngineDisconnectReason = g_pMatchFramework->GetEventsSubscription()->GetEventData( "OnEngineDisconnectReason" ) ) { if ( !Q_stricmp( "lobby", pOnEngineDisconnectReason->GetString( "disconnecthdlr" ) ) ) { // - CUIGameData::Get()->OpenWaitScreen( "#L4D360UI_MsgBx_DisconnectedFromServer" );
// - CUIGameData::Get()->CloseWaitScreen( NULL, NULL );
} } } else if ( !Q_stricmp( "created", szState ) ) { //
// This section of code catches when we just connected to a lobby that
// is playing a campaign that we do not have installed.
// In this case we abort loading, forcefully close all windows including
// loading poster and game lobby and display the download info msg.
//
#if 1 // TODO: UI: connected to dlc session
return; #else
IMatchSession *pSession = g_pMatchFramework->GetMatchSession(); if ( !pSession ) return;
KeyValues *pSettings = pSession->GetSessionSettings();
KeyValues *pInfoMission = NULL; KeyValues *pInfoChapter = GetMapInfoRespectingAnyChapter( pSettings, &pInfoMission );
// If we do not have a valid chapter/mission, then we need to quit
if ( pInfoChapter && pInfoMission && ( !*pInfoMission->GetName() || pInfoMission->GetInt( "version" ) == pSettings->GetInt( "game/missioninfo/version", -1 ) ) ) return;
if ( pSettings ) pSettings = pSettings->MakeCopy();
engine->ExecuteClientCmd( "disconnect" ); g_pMatchFramework->CloseSession();
CloseAllWindows( CLOSE_POLICY_EVEN_MSGS | CLOSE_POLICY_EVEN_LOADING ); OpenFrontScreen();
const char *szCampaignWebsite = pSettings->GetString( "game/missioninfo/website", NULL ); if ( szCampaignWebsite && *szCampaignWebsite ) { OpenWindow( WT_DOWNLOADCAMPAIGN, GetWindow( CBaseModPanel::GetSingleton().GetActiveWindowType() ), true, pSettings ); } else { GenericConfirmation::Data_t data;
data.pWindowTitle = "#L4D360UI_Lobby_MissingContent"; data.pMessageText = "#L4D360UI_Lobby_MissingContent_Message"; data.bOkButtonEnabled = true;
GenericConfirmation* confirmation = static_cast< GenericConfirmation* >( OpenWindow( WT_GENERICCONFIRMATION, NULL, true ) );
confirmation->SetUsageData(data); } #endif
} else if ( !Q_stricmp( "progress", szState ) ) { struct WaitText_t { char const *m_szProgress; char const *m_szText; int m_eCloseAllWindowsFlags; };
// TODO: UI: session create progress
// - int eDefaultFlags = CLOSE_POLICY_EVEN_MSGS | CLOSE_POLICY_KEEP_BKGND;
int eDefaultFlags = -1; WaitText_t arrWaits[] = { { "creating", "#Matchmaking_creating", eDefaultFlags }, { "joining", "#Matchmaking_joining", eDefaultFlags }, { "searching", "#Matchmaking_searching", eDefaultFlags }, };
char const *szProgress = pEvent->GetString( "progress", "" ); WaitText_t const *pWaitText = NULL; for ( int k = 0; k < ARRAYSIZE( arrWaits ); ++ k ) { if ( !Q_stricmp( arrWaits[k].m_szProgress, szProgress ) ) { pWaitText = &arrWaits[k]; break; } }
// Wait screen options to cancel async process
KeyValues *pSettings = new KeyValues( "WaitScreen" ); KeyValues::AutoDelete autodelete_pSettings( pSettings ); pSettings->SetPtr( "options/asyncoperation", g_MatchSessionCreationAsyncOperation.Prepare() );
// For PC we don't want to cancel lobby creation
if ( IsPC() && !Q_stricmp( "creating", szProgress ) ) pSettings = NULL;
// Put up a wait screen
if ( pWaitText ) { if ( pWaitText->m_eCloseAllWindowsFlags != -1 ) { // - CloseAllWindows( pWaitText->m_eCloseAllWindowsFlags );
}
char const *szWaitScreenText = pWaitText->m_szText; float flMinDisplayTime = 0.0f; REFERENCE(flMinDisplayTime); if ( IMatchSession *pMatchSession = g_pMatchFramework->GetMatchSession() ) { KeyValues *pMatchSettings = pMatchSession->GetSessionSettings(); if ( !Q_stricmp( szProgress, "creating" ) && !Q_stricmp( pMatchSettings->GetString( "options/createreason" ), "searchempty" ) && !Q_stricmp( pMatchSettings->GetString( "system/access" ), "public" ) ) { // We are creating a public lobby after our search turned out empty
szWaitScreenText = "#Matchmaking_NoResultsCreating"; } }
// - CUIGameData::Get()->OpenWaitScreen( szWaitScreenText, flMinDisplayTime, pSettings );
} else if ( !Q_stricmp( "searchresult", szProgress ) ) { char const *arrText[] = { "#Matchmaking_SearchResults", "#Matchmaking_SearchResults1", "#Matchmaking_SearchResults2", "#Matchmaking_SearchResults3" }; int numResults = pEvent->GetInt( "numResults", 0 ); if ( numResults < 0 || numResults >= ARRAYSIZE( arrText ) ) numResults = 0; // TODO: UI: session search progress
// - CUIGameData::Get()->OpenWaitScreen( arrText[numResults], 0.0f, pSettings );
} } } else if ( !Q_stricmp( "OnEngineLevelLoadingSession", szEvent ) ) { OnEngineLevelLoadingSession( pEvent ); } else if ( !Q_stricmp( "OnEngineLevelLoadingFinished", szEvent ) ) { OnLevelLoadingFinished( pEvent ); } }
//=============================================================================
bool CBaseModPanel::UpdateProgressBar( float progress, const char *statusText ) { if ( !m_LevelLoading ) { // Warning( "WARN: CBaseModPanel::UpdateProgressBar called outside of level loading, discarded!\n" );
return false; }
// Need to call this periodically to collect sign in and sign out notifications,
// do NOT dispatch events here in the middle of loading and rendering!
if ( ThreadInMainThread() ) { XBX_ProcessEvents(); }
IGameUIScreenControllerFactory *pFactory = g_pGameUISystemMgr->GetScreenControllerFactory( "loadingprogress" ); if ( pFactory && pFactory->GetControllerInstancesCount() ) { KeyValues *kvEvent = new KeyValues( "OnLevelLoadingProgress" ); KeyValues::AutoDelete autodelete_kvEvent( kvEvent ); kvEvent->SetFloat( "progress", progress );
for ( int j = 0; j < pFactory->GetControllerInstancesCount(); ++ j ) { pFactory->GetControllerInstance(j)->BroadcastEventToScreens( kvEvent ); } }
// update required
return true; }
void CBaseModPanel::SetLastActiveUserId( int userId ) { if ( m_lastActiveUserId != userId ) { DevWarning( "SetLastActiveUserId: %d -> %d\n", m_lastActiveUserId, userId ); }
m_lastActiveUserId = userId; }
int CBaseModPanel::GetLastActiveUserId( ) { return m_lastActiveUserId; }
//-----------------------------------------------------------------------------
// Purpose: moves the game menu button to the right place on the taskbar
//-----------------------------------------------------------------------------
static void BaseUI_PositionDialog(vgui::PHandle dlg) { if (!dlg.Get()) return;
int x, y, ww, wt, wide, tall; vgui::surface()->GetWorkspaceBounds( x, y, ww, wt ); dlg->GetSize(wide, tall);
// Center it, keeping requested size
dlg->SetPos(x + ((ww - wide) / 2), y + ((wt - tall) / 2)); }
//=============================================================================
void CBaseModPanel::ApplySchemeSettings(IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme);
SetBgColor(pScheme->GetColor("Blank", Color(0, 0, 0, 0)));
char filename[MAX_PATH]; engine->GetStartupImage( filename, sizeof( filename ) ); m_iBackgroundImageID = surface()->CreateNewTextureID(); surface()->DrawSetTextureFile( m_iBackgroundImageID, filename, true, false );
const AspectRatioInfo_t &aspectRatioInfo = materials->GetAspectRatioInfo(); bool bIsWidescreen = aspectRatioInfo.m_bIsWidescreen;
m_iFadeToBackgroundImageID = -1; const char *pWhich = V_stristr( filename, "background" ); if ( pWhich ) { int nWhich = atoi( pWhich + 10 ); if ( nWhich ) { bool bIsWidescreen = ( V_stristr( pWhich, "widescreen" ) != NULL ); CFmtStr pFadeFilename( "vgui/maps/background%02d_exit%s", nWhich, ( bIsWidescreen ? "_widescreen" : "" ) ); m_iFadeToBackgroundImageID = surface()->CreateNewTextureID(); surface()->DrawSetTextureFile( m_iFadeToBackgroundImageID, pFadeFilename, true, false ); } }
// Recalculate the movie parameters if our video size has changed
CalculateMovieParameters();
bool bUseMono = false; bUseMono; // silence warnings on non-demo, PC build
#if defined( _GAMECONSOLE )
// cannot use the very large stereo version during the install
bUseMono = g_pXboxInstaller->IsInstallEnabled() && !g_pXboxInstaller->IsFullyInstalled(); #if defined( _DEMO )
bUseMono = true; #endif
#endif
// TODO: GetBackgroundMusic
#if 0
char backgroundMusic[MAX_PATH]; engine->GetBackgroundMusic( backgroundMusic, sizeof( backgroundMusic ), bUseMono );
// the precache will be a memory or stream wave as needed
// on 360 the sound system will detect the install state and force it to a memory wave to finalize the the i/o now
// it will be a stream resource if the installer is dormant
// On PC it will be a streaming MP3
if ( enginesound->PrecacheSound( backgroundMusic, true, false ) ) { // successfully precached
m_backgroundMusic = backgroundMusic; } #endif
}
void CBaseModPanel::DrawColoredText( vgui::HFont hFont, int x, int y, unsigned int color, const char *pAnsiText ) { wchar_t szconverted[256]; int len = g_pVGuiLocalize->ConvertANSIToUnicode( pAnsiText, szconverted, sizeof( szconverted ) ); if ( len <= 0 ) { return; }
int r = ( color >> 24 ) & 0xFF; int g = ( color >> 16 ) & 0xFF; int b = ( color >> 8 ) & 0xFF; int a = ( color >> 0 ) & 0xFF;
vgui::surface()->DrawSetTextFont( hFont ); vgui::surface()->DrawSetTextPos( x, y ); vgui::surface()->DrawSetTextColor( r, g, b, a ); vgui::surface()->DrawPrintText( szconverted, len ); }
void CBaseModPanel::DrawCopyStats() { #if defined( _GAMECONSOLE )
int wide, tall; GetSize( wide, tall );
int xPos = 0.1f * wide; int yPos = 0.1f * tall;
// draw copy status
char textBuffer[256]; const CopyStats_t *pCopyStats = g_pXboxInstaller->GetCopyStats();
V_snprintf( textBuffer, sizeof( textBuffer ), "Version: %d (%s)", g_pXboxInstaller->GetVersion(), XBX_GetLanguageString() ); DrawColoredText( m_hDefaultFont, xPos, yPos, 0xffff00ff, textBuffer ); yPos += 20;
V_snprintf( textBuffer, sizeof( textBuffer ), "DVD Hosted: %s", g_pFullFileSystem->IsDVDHosted() ? "Enabled" : "Disabled" ); DrawColoredText( m_hDefaultFont, xPos, yPos, 0xffff00ff, textBuffer ); yPos += 20;
bool bDrawProgress = true; if ( g_pFullFileSystem->IsInstalledToXboxHDDCache() ) { DrawColoredText( m_hDefaultFont, xPos, yPos, 0x00ff00ff, "Existing Image Found." ); yPos += 20; bDrawProgress = false; } if ( !g_pXboxInstaller->IsInstallEnabled() ) { DrawColoredText( m_hDefaultFont, xPos, yPos, 0xff0000ff, "Install Disabled." ); yPos += 20; bDrawProgress = false; } if ( g_pXboxInstaller->IsFullyInstalled() ) { DrawColoredText( m_hDefaultFont, xPos, yPos, 0x00ff00ff, "Install Completed." ); yPos += 20; }
if ( bDrawProgress ) { yPos += 20; V_snprintf( textBuffer, sizeof( textBuffer ), "From: %s (%.2f MB)", pCopyStats->m_srcFilename, (float)pCopyStats->m_ReadSize/(1024.0f*1024.0f) ); DrawColoredText( m_hDefaultFont, xPos, yPos, 0xffff00ff, textBuffer ); V_snprintf( textBuffer, sizeof( textBuffer ), "To: %s (%.2f MB)", pCopyStats->m_dstFilename, (float)pCopyStats->m_WriteSize/(1024.0f*1024.0f) ); DrawColoredText( m_hDefaultFont, xPos, yPos + 20, 0xffff00ff, textBuffer );
float elapsed = 0; float rate = 0; if ( pCopyStats->m_InstallStartTime ) { elapsed = (float)(GetTickCount() - pCopyStats->m_InstallStartTime) * 0.001f; } if ( pCopyStats->m_InstallStopTime ) { elapsed = (float)(pCopyStats->m_InstallStopTime - pCopyStats->m_InstallStartTime) * 0.001f; } if ( elapsed ) { rate = pCopyStats->m_TotalWriteSize/elapsed; } V_snprintf( textBuffer, sizeof( textBuffer ), "Progress: %d/%d MB Elapsed: %d secs (%.2f MB/s)", pCopyStats->m_BytesCopied/(1024*1024), g_pXboxInstaller->GetTotalSize()/(1024*1024), (int)elapsed, rate/(1024.0f*1024.0f) ); DrawColoredText( m_hDefaultFont, xPos, yPos + 40, 0xffff00ff, textBuffer ); } #endif
}
//-----------------------------------------------------------------------------
// Returns true if menu background movie is valid
//-----------------------------------------------------------------------------
bool CBaseModPanel::IsMenuBackgroundMovieValid( void ) { if ( !m_bMovieFailed && m_BIKHandle != BIKHANDLE_INVALID ) { return true; }
return false; }
//=============================================================================
void CBaseModPanel::CalculateMovieParameters( void ) { if ( m_BIKHandle == BIKHANDLE_INVALID ) return; m_flU0 = m_flV0 = 0.0f; g_pBIK->GetTexCoordRange( m_BIKHandle, &m_flU1, &m_flV1 );
m_pMovieMaterial = g_pBIK->GetMaterial( m_BIKHandle );
int nWidth, nHeight; g_pBIK->GetFrameSize( m_BIKHandle, &nWidth, &nHeight );
float flFrameRatio = ( (float) GetWide() / (float) GetTall() ); float flVideoRatio = ( (float) nWidth / (float) nHeight ); if ( flVideoRatio > flFrameRatio ) { // Width must be adjusted
float flImageWidth = (float) GetTall() * flVideoRatio; const float flSpanScaled = ( m_flU1 - m_flU0 ) * GetWide() / flImageWidth; m_flU0 = ( m_flU1 - flSpanScaled ) / 2.0f; m_flU1 = m_flU0 + flSpanScaled; } else if ( flVideoRatio < flFrameRatio ) { // Height must be adjusted
float flImageHeight = (float) GetWide() * ( (float) nHeight / (float) nWidth ); const float flSpanScaled = ( m_flV1 - m_flV0 ) * GetTall() / flImageHeight; m_flV0 = ( m_flV1 - flSpanScaled ) / 2.0f; m_flV1 = m_flV0 + flSpanScaled; } }
//=============================================================================
bool CBaseModPanel::InitBackgroundMovie( void ) { if ( m_bMovieFailed || m_ExitingFrameCount ) { // prevent constant i/o testing after failure condition
// do not restart the movie (after its been stopped), we are trying to stabilize the app for exit
return false; }
if ( CommandLine()->FindParm( "-nomenuvid" ) ) { // mimic movie i/o failure, render will fallback to use product image
m_bMovieFailed = false; return false; }
static bool bFirstTime = true; if ( bFirstTime ) { // one time only, on app startup transition from the product image
m_iMovieTransitionImage = m_iBackgroundImageID; bFirstTime = false; } else { // otherwise use the blur fade in
m_iMovieTransitionImage = m_iFadeToBackgroundImageID; }
// Grab our scheme to get the filename from
IScheme *pScheme = vgui::scheme()->GetIScheme( m_UIScheme ); if ( pScheme == NULL ) return false;
// Destroy any previously allocated video
if ( m_BIKHandle != BIKHANDLE_INVALID ) { g_pBIK->DestroyMaterial( m_BIKHandle ); m_BIKHandle = BIKHANDLE_INVALID; }
const char *pFilename; char movieFilename[MAX_PATH] = {0}; pFilename = movieFilename; // TODO: engine->GetBackgroundMovie( movieFilename, sizeof( movieFilename ) );
if ( !g_pFullFileSystem->FileExists( movieFilename, "GAME" ) ) { // bgnd movie not available, fallback and try this one
pFilename = pScheme->GetResourceString( "BackgroundMovie" ); }
COM_TimestampedLog( "Load Background Movie - %s", pFilename );
// Load and create our BINK video
// This menu background movie needs to loop and !!reside!! in memory (CRITICAL: Xbox is installing to HDD, w/o this it will frag the drive)
#ifndef _GAMECONSOLE
// Address bug caused by searchpath manipulation
materials ? materials->UncacheAllMaterials() : NULL; #endif
m_BIKHandle = BIKHANDLE_INVALID; // TODO: g_pBIK->CreateMaterial( "VideoBIKMaterial_Background", pFilename, "GAME", BIK_LOOP | BIK_PRELOAD );
if ( m_BIKHandle == BIKHANDLE_INVALID ) { m_bMovieFailed = true; return false; } COM_TimestampedLog( "Load Background Movie - End" );
// Find frame size and letterboxing information
CalculateMovieParameters();
return true; }
//=============================================================================
void CBaseModPanel::ShutdownBackgroundMovie( void ) { if ( m_BIKHandle != BIKHANDLE_INVALID ) { // FIXME: Make sure the m_pMaterial is actually destroyed at this point!
g_pBIK->DestroyMaterial( m_BIKHandle ); m_BIKHandle = BIKHANDLE_INVALID; }
// allow a retry
m_bMovieFailed = false;
ReleaseBackgroundMusic(); }
//=============================================================================
bool CBaseModPanel::RenderBackgroundMovie( float *pflFadeDelta ) { // goes from [0..1]
// provided to the caller to track the movie fade in
// callers may have other overlay elements to sync
*pflFadeDelta = 1.0f;
if ( IsGameConsole() && m_BIKHandle == BIKHANDLE_INVALID ) { // should have already started, cannot be started now
return false; }
if ( IsPC() ) { // Bring up the video if we haven't before or Alt+Tab has made it invalid
// The Xbox cannot start the movie at this point, the installer may be using the DVD
if ( !ActivateBackgroundEffects() ) { return false; } }
if ( !m_flMovieFadeInTime ) { // do the fade a little bit after the movie starts (needs to be stable)
// the product overlay will fade out
m_flMovieFadeInTime = Plat_FloatTime() + TRANSITION_TO_MOVIE_DELAY_TIME; }
// There are cases where our texture may never have been rendered (immediately alt+tabbing away on startup). This check allows us to
// recalculate the correct UVs in that case.
if ( m_flU1 == 0.0f || m_flV1 == 0.0f ) { CalculateMovieParameters(); }
// Update our frame, but only if Bink is ready for us to process another frame.
// We aren't really swapping here, but ReadyForSwap is a good way to throttle.
// We'd rather throttle this way so that we don't limit the overall frame rate of the system.
if ( false ) // TODO: if ( g_pBIK->ReadyForSwap( m_BIKHandle ) )
{ if ( g_pBIK->Update( m_BIKHandle ) == false ) { // Issue a close command
ShutdownBackgroundMovie(); return false; } }
// Draw the polys to draw the movie out
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->MatrixMode( MATERIAL_VIEW ); pRenderContext->PushMatrix(); pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_PROJECTION ); pRenderContext->PushMatrix(); pRenderContext->LoadIdentity();
IMaterial *pMaterial = g_pBIK->GetMaterial( m_BIKHandle );
pRenderContext->Bind( pMaterial, NULL );
CMeshBuilder meshBuilder; IMesh* pMesh = pRenderContext->GetDynamicMesh( true ); meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
float flLeftX = 0; float flRightX = GetWide()-1;
float flTopY = 0; float flBottomY = GetTall()-1;
// Map our UVs to cut out just the portion of the video we're interested in
float flLeftU = m_flU0; float flTopV = m_flV0;
// We need to subtract off a pixel to make sure we don't bleed
float flRightU = m_flU1 - ( 1.0f / (float) GetWide() ); float flBottomV = m_flV1 - ( 1.0f / (float) GetTall() );
// Get the current viewport size
int vx, vy, vw, vh; pRenderContext->GetViewport( vx, vy, vw, vh );
// map from screen pixel coords to -1..1
flRightX = FLerp( -1, 1, 0, vw, flRightX ); flLeftX = FLerp( -1, 1, 0, vw, flLeftX ); flTopY = FLerp( 1, -1, 0, vh ,flTopY ); flBottomY = FLerp( 1, -1, 0, vh, flBottomY );
for ( int corner=0; corner<4; corner++ ) { bool bLeft = (corner==0) || (corner==3); meshBuilder.Position3f( (bLeft) ? flLeftX : flRightX, (corner & 2) ? flBottomY : flTopY, 0.0f ); meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f ); meshBuilder.TexCoord2f( 0, (bLeft) ? flLeftU : flRightU, (corner & 2) ? flBottomV : flTopV ); meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f ); meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f ); meshBuilder.Color4f( 1.0f, 1.0f, 1.0f, 1.0f ); meshBuilder.AdvanceVertex(); }
meshBuilder.End(); pMesh->Draw();
pRenderContext->MatrixMode( MATERIAL_VIEW ); pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_PROJECTION ); pRenderContext->PopMatrix();
if ( IsGameConsole() ) { // The product screen has more range than the movie, so the fade works better if the overlay draws after and fades out.
// Fading the product screen out, modulate alpha [1..0]
float flFadeDelta = RemapValClamped( Plat_FloatTime(), m_flMovieFadeInTime, m_flMovieFadeInTime + TRANSITION_TO_MOVIE_FADE_TIME, 1.0f, 0.0f ); if ( flFadeDelta > 0.0f ) { surface()->DrawSetColor( 255, 255, 255, flFadeDelta * 255.0f ); surface()->DrawSetTexture( m_iMovieTransitionImage ); surface()->DrawTexturedRect( 0, 0, GetWide(), GetTall() ); }
// goes from [0..1]
flFadeDelta = 1.0f - flFadeDelta; if ( m_bFadeMusicUp ) { CBaseModPanel::GetSingleton().UpdateBackgroundMusicVolume( flFadeDelta ); if ( flFadeDelta >= 1.0f ) { // stop updating
m_bFadeMusicUp = false; } }
*pflFadeDelta = flFadeDelta; }
#if defined( ENABLE_BIK_PERF_SPEW ) && ENABLE_BIK_PERF_SPEW
{ // timing debug code for bink playback
static double flPreviousTime = -1.0; double flTime = Plat_FloatTime(); double flDeltaTime = flTime - flPreviousTime; if ( flDeltaTime > 0.0 ) { Warning( "%0.2lf sec*60 %0.2lf fps\n", flDeltaTime * 60.0, 1.0 / flDeltaTime ); } flPreviousTime = flTime; } #endif
return true; }
//=============================================================================
void CBaseModPanel::PaintBackground() { int wide, tall; GetSize( wide, tall );
if ( !m_LevelLoading && !GameUI().IsInLevel() && !GameUI().IsInBackgroundLevel() ) { if ( engine->IsTransitioningToLoad() ) { // ensure the background is clear
// the loading progress is about to take over in a few frames
// this keeps us from flashing a different graphic
surface()->DrawSetColor( 0, 0, 0, 255 ); surface()->DrawSetTexture( m_iBackgroundImageID ); surface()->DrawTexturedRect( 0, 0, wide, tall ); } else { // Render the background movie
float flFadeDelta; if ( !RenderBackgroundMovie( &flFadeDelta ) ) { // movie failed used product screen as background
surface()->DrawSetColor( 255, 255, 255, 255 ); surface()->DrawSetTexture( m_iBackgroundImageID ); surface()->DrawTexturedRect( 0, 0, wide, tall ); } } }
// Update and render the new UI
if ( g_pGameUIGameSystem ) { Rect_t uiViewport; uiViewport.x = 0; uiViewport.y = 0; uiViewport.width = wide; uiViewport.height = tall; g_pGameUISystemMgr->RunFrame(); // Need to use realtime so animations will play even when paused.
g_pGameUIGameSystem->Render( uiViewport, gpGlobals->realtime ); }
#if defined( _GAMECONSOLE )
if ( !m_LevelLoading && !GameUI().IsInLevel() && xbox_install_status.GetBool() ) { DrawCopyStats(); } #endif
}
void CBaseModPanel::OnCommand(const char *command) { if ( !Q_stricmp( command, "QuitRestartNoConfirm" ) ) { if ( IsGameConsole() ) { StartExitingProcess( false ); } } else if ( !Q_stricmp( command, "RestartWithNewLanguage" ) ) { if ( !IsGameConsole() ) { // TODO: UI: RestartWithNewLanguage
// - const char *pUpdatedAudioLanguage = Audio::GetUpdatedAudioLanguage();
const char *pUpdatedAudioLanguage = "english";
if ( pUpdatedAudioLanguage[ 0 ] != '\0' ) { char szSteamURL[50]; char szAppId[50];
// hide everything while we quit
SetVisible( false ); vgui::surface()->RestrictPaintToSinglePanel( GetVPanel() ); engine->ClientCmd_Unrestricted( "quit\n" );
// Construct Steam URL. Pattern is steam://run/<appid>/<language>. (e.g. Ep1 In French ==> steam://run/380/french)
Q_strcpy(szSteamURL, "steam://run/"); itoa( engine->GetAppID(), szAppId, 10 ); Q_strcat( szSteamURL, szAppId, sizeof( szSteamURL ) ); Q_strcat( szSteamURL, "/", sizeof( szSteamURL ) ); Q_strcat( szSteamURL, pUpdatedAudioLanguage, sizeof( szSteamURL ) );
// Set Steam URL for re-launch in registry. Launcher will check this registry key and exec it in order to re-load the game in the proper language
vgui::system()->SetRegistryString("HKEY_CURRENT_USER\\Software\\Valve\\Source\\Relaunch URL", szSteamURL ); } } } else { BaseClass::OnCommand( command ); } }
bool CBaseModPanel::RequestInfo( KeyValues *data ) { if ( !Q_stricmp( "InputControlState", data->GetName() ) ) { data->SetInt( "passthrough", 1 ); return true; }
return BaseClass::RequestInfo( data ); }
bool CBaseModPanel::IsReadyToWriteConfig( void ) { // For cert we only want to write config files is it has been at least 3 seconds
#ifdef _GAMECONSOLE
static ConVarRef r_host_write_last_time( "host_write_last_time" ); return ( Plat_FloatTime() > r_host_write_last_time.GetFloat() + 3.05f ); #endif
return false; }
//=============================================================================
// Start system shutdown. Cannot be stopped.
// A Restart is cold restart, plays the intro movie again.
//=============================================================================
void CBaseModPanel::StartExitingProcess( bool bWarmRestart ) { if ( !IsGameConsole() ) { // xbox only
Assert( 0 ); return; }
if ( m_ExitingFrameCount ) { // already fired
return; }
#if defined( _GAMECONSOLE )
// signal the installer to stop
g_pXboxInstaller->Stop(); #endif
// cold restart or warm
m_bWarmRestartMode = bWarmRestart;
// the exiting screen will transition to obscure all the game and UI
// TODO: UI: - OpenWindow( WT_TRANSITIONSCREEN, 0, false );
// must let a non trivial number of screen swaps occur to stabilize image
// ui runs in a constrained state, while shutdown is occurring
m_ExitingFrameCount = 15;
// exiting cannot be stopped
// do not allow any input to occur
g_pInputSystem->DetachFromWindow();
// start shutting down systems
engine->StartXboxExitingProcess(); }
void CBaseModPanel::OnSetFocus() { BaseClass::OnSetFocus(); if ( IsPC() ) { GameConsole().Hide(); } }
void CBaseModPanel::OnMovedPopupToFront() { if ( IsPC() ) { GameConsole().Hide(); } }
bool CBaseModPanel::IsBackgroundMusicPlaying() { if ( m_backgroundMusic.IsEmpty() ) return false;
if ( m_nBackgroundMusicGUID == 0 ) return false; return enginesound->IsSoundStillPlaying( m_nBackgroundMusicGUID ); }
// per Morasky
#define BACKGROUND_MUSIC_DUCK 0.15f
bool CBaseModPanel::StartBackgroundMusic( float fVol ) { if ( IsBackgroundMusicPlaying() ) return true; if ( m_backgroundMusic.IsEmpty() ) return false;
// trying to exit, cannot start it
if ( m_ExitingFrameCount ) return false; m_nBackgroundMusicGUID = 0; // TODO: enginesound->EmitAmbientSound( m_backgroundMusic, BACKGROUND_MUSIC_DUCK * fVol );
return ( m_nBackgroundMusicGUID != 0 ); }
void CBaseModPanel::UpdateBackgroundMusicVolume( float fVol ) { if ( !IsBackgroundMusicPlaying() ) return;
// mixes too loud against soft ui sounds
enginesound->SetVolumeByGuid( m_nBackgroundMusicGUID, BACKGROUND_MUSIC_DUCK * fVol ); }
void CBaseModPanel::ReleaseBackgroundMusic() { if ( m_backgroundMusic.IsEmpty() ) return;
if ( m_nBackgroundMusicGUID == 0 ) return;
// need to stop the sound now, do not queue the stop
// we must release the 2-5 MB held by this resource
// TODO: enginesound->StopSoundByGuid( m_nBackgroundMusicGUID, true );
#if defined( _GAMECONSOLE )
// TODO: enginesound->UnloadSound( m_backgroundMusic );
#endif
m_nBackgroundMusicGUID = 0; }
void CBaseModPanel::SafeNavigateTo( Panel *pExpectedFrom, Panel *pDesiredTo, bool bAllowStealFocus ) { Panel *pOriginalFocus = ipanel()->GetPanel( GetCurrentKeyFocus(), GetModuleName() ); bool bSomeoneElseHasFocus = pOriginalFocus && (pOriginalFocus != pExpectedFrom); bool bActuallyChangingFocus = (pExpectedFrom != pDesiredTo); bool bNeedToReturnKeyFocus = !bAllowStealFocus && bSomeoneElseHasFocus && bActuallyChangingFocus;
pDesiredTo->NavigateTo();
if ( bNeedToReturnKeyFocus ) { pDesiredTo->NavigateFrom(); pOriginalFocus->NavigateTo(); } }
|