You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4987 lines
138 KiB
4987 lines
138 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//===========================================================================// |
|
|
|
#include <stdio.h> |
|
|
|
#include "threadtools.h" |
|
|
|
#include "BasePanel.h" |
|
#include "EngineInterface.h" |
|
#include "VGuiSystemModuleLoader.h" |
|
|
|
#include "vgui/IInput.h" |
|
#include "vgui/ILocalize.h" |
|
#include "vgui/IPanel.h" |
|
#include "vgui/ISurface.h" |
|
#include "vgui/ISystem.h" |
|
#include "vgui/IVGui.h" |
|
#include "filesystem.h" |
|
#include "GameConsole.h" |
|
#include "GameUI_Interface.h" |
|
#include "vgui_controls/PropertyDialog.h" |
|
#include "vgui_controls/PropertySheet.h" |
|
#include "materialsystem/materialsystem_config.h" |
|
#include "materialsystem/imaterialsystem.h" |
|
#include "sourcevr/isourcevirtualreality.h" |
|
#include "VGuiMatSurface/IMatSystemSurface.h" |
|
|
|
using namespace vgui; |
|
|
|
#include "GameConsole.h" |
|
#include "ModInfo.h" |
|
|
|
#include "IGameUIFuncs.h" |
|
#include "LoadingDialog.h" |
|
#include "BackgroundMenuButton.h" |
|
#include "vgui_controls/AnimationController.h" |
|
#include "vgui_controls/ImagePanel.h" |
|
#include "vgui_controls/Label.h" |
|
#include "vgui_controls/Menu.h" |
|
#include "vgui_controls/MenuItem.h" |
|
#include "vgui_controls/PHandle.h" |
|
#include "vgui_controls/MessageBox.h" |
|
#include "vgui_controls/QueryBox.h" |
|
#include "vgui_controls/ControllerMap.h" |
|
#include "vgui_controls/KeyRepeat.h" |
|
#include "tier0/icommandline.h" |
|
#include "tier1/convar.h" |
|
#include "NewGameDialog.h" |
|
#include "BonusMapsDialog.h" |
|
#include "LoadGameDialog.h" |
|
#include "SaveGameDialog.h" |
|
#include "OptionsDialog.h" |
|
#include "CreateMultiplayerGameDialog.h" |
|
#include "ChangeGameDialog.h" |
|
#include "BackgroundMenuButton.h" |
|
#include "PlayerListDialog.h" |
|
#include "BenchmarkDialog.h" |
|
#include "LoadCommentaryDialog.h" |
|
#include "ControllerDialog.h" |
|
#include "BonusMapsDatabase.h" |
|
#include "engine/IEngineSound.h" |
|
#include "bitbuf.h" |
|
#include "tier1/fmtstr.h" |
|
#include "inputsystem/iinputsystem.h" |
|
#include "ixboxsystem.h" |
|
#include "matchmaking/matchmakingbasepanel.h" |
|
#include "matchmaking/achievementsdialog.h" |
|
#include "iachievementmgr.h" |
|
#include "UtlSortVector.h" |
|
|
|
#include "game/client/IGameClientExports.h" |
|
|
|
#include "OptionsSubAudio.h" |
|
#include "hl2orange.spa.h" |
|
#include "CustomTabExplanationDialog.h" |
|
#if defined( _X360 ) |
|
#include "xbox/xbox_launch.h" |
|
#else |
|
#include "xbox/xboxstubs.h" |
|
#endif |
|
|
|
#include "../engine/imatchmaking.h" |
|
#include "tier1/utlstring.h" |
|
#include "steam/steam_api.h" |
|
|
|
#ifdef ANDROID |
|
#include <SDL_misc.h> |
|
#endif |
|
|
|
#undef MessageBox // Windows helpfully #define's this to MessageBoxA, we're using vgui::MessageBox |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
|
|
#define MAIN_MENU_INDENT_X360 10 |
|
|
|
ConVar vgui_message_dialog_modal( "vgui_message_dialog_modal", "1", FCVAR_ARCHIVE ); |
|
|
|
extern vgui::DHANDLE<CLoadingDialog> g_hLoadingDialog; |
|
static CBasePanel *g_pBasePanel = NULL; |
|
static float g_flAnimationPadding = 0.01f; |
|
|
|
extern const char *COM_GetModDirectory( void ); |
|
|
|
extern ConVar x360_audio_english; |
|
extern bool bSteamCommunityFriendsVersion; |
|
|
|
static vgui::DHANDLE<vgui::PropertyDialog> g_hOptionsDialog; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: singleton accessor |
|
//----------------------------------------------------------------------------- |
|
CBasePanel *BasePanel() |
|
{ |
|
return g_pBasePanel; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: hack function to give the module loader access to the main panel handle |
|
// only used in VguiSystemModuleLoader |
|
//----------------------------------------------------------------------------- |
|
VPANEL GetGameUIBasePanel() |
|
{ |
|
return BasePanel()->GetVPanel(); |
|
} |
|
|
|
CGameMenuItem::CGameMenuItem(vgui::Menu *parent, const char *name) : BaseClass(parent, name, "GameMenuItem") |
|
{ |
|
m_bRightAligned = false; |
|
} |
|
|
|
void CGameMenuItem::ApplySchemeSettings(IScheme *pScheme) |
|
{ |
|
BaseClass::ApplySchemeSettings(pScheme); |
|
|
|
// make fully transparent |
|
SetFgColor(GetSchemeColor("MainMenu.TextColor", pScheme)); |
|
SetBgColor(Color(0, 0, 0, 0)); |
|
SetDefaultColor(GetSchemeColor("MainMenu.TextColor", pScheme), Color(0, 0, 0, 0)); |
|
SetArmedColor(GetSchemeColor("MainMenu.ArmedTextColor", pScheme), Color(0, 0, 0, 0)); |
|
SetDepressedColor(GetSchemeColor("MainMenu.DepressedTextColor", pScheme), Color(0, 0, 0, 0)); |
|
SetContentAlignment(Label::a_west); |
|
SetBorder(NULL); |
|
SetDefaultBorder(NULL); |
|
SetDepressedBorder(NULL); |
|
SetKeyFocusBorder(NULL); |
|
|
|
vgui::HFont hMainMenuFont = pScheme->GetFont( "MainMenuFont", IsProportional() ); |
|
|
|
if ( hMainMenuFont ) |
|
{ |
|
SetFont( hMainMenuFont ); |
|
} |
|
else |
|
{ |
|
SetFont( pScheme->GetFont( "MenuLarge", IsProportional() ) ); |
|
} |
|
SetTextInset(0, 0); |
|
SetArmedSound("UI/buttonrollover.wav"); |
|
SetDepressedSound("UI/buttonclick.wav"); |
|
SetReleasedSound("UI/buttonclickrelease.wav"); |
|
SetButtonActivationType(Button::ACTIVATE_ONPRESSED); |
|
|
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
SetArmedColor(GetSchemeColor("MainMenu.ArmedTextColor", pScheme), GetSchemeColor("Button.ArmedBgColor", pScheme)); |
|
SetTextInset( MAIN_MENU_INDENT_X360, 0 ); |
|
} |
|
|
|
if (m_bRightAligned) |
|
{ |
|
SetContentAlignment(Label::a_east); |
|
} |
|
} |
|
|
|
void CGameMenuItem::PaintBackground() |
|
{ |
|
if ( !GameUI().IsConsoleUI() ) |
|
{ |
|
BaseClass::PaintBackground(); |
|
} |
|
else |
|
{ |
|
if ( !IsArmed() || !IsVisible() || GetParent()->GetAlpha() < 32 ) |
|
return; |
|
|
|
int wide, tall; |
|
GetSize( wide, tall ); |
|
|
|
DrawBoxFade( 0, 0, wide, tall, GetButtonBgColor(), 1.0f, 255, 0, true ); |
|
DrawBoxFade( 2, 2, wide - 4, tall - 4, Color( 0, 0, 0, 96 ), 1.0f, 255, 0, true ); |
|
} |
|
} |
|
|
|
void CGameMenuItem::SetRightAlignedText(bool state) |
|
{ |
|
m_bRightAligned = state; |
|
} |
|
|
|
class ImageButton : public vgui::Panel |
|
{ |
|
public: |
|
ImageButton(Panel *parent, const char *imageName) : Panel(parent) |
|
{ |
|
m_szUrl = NULL; |
|
|
|
m_textureID = vgui::surface()->CreateNewTextureID(); |
|
vgui::surface()->DrawSetTextureFile( m_textureID, imageName, true, false); |
|
m_bSelected = false; |
|
} |
|
|
|
virtual void Paint() |
|
{ |
|
if( GameUI().IsInLevel() ) return; |
|
|
|
int color = m_bSelected ? 120 : 160; |
|
|
|
vgui::surface()->DrawSetColor(color, color, color, 100); |
|
vgui::surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() ); |
|
vgui::surface()->DrawSetTexture( m_textureID ); |
|
|
|
vgui::surface()->DrawSetColor( 255, 255, 255, 255 ); |
|
vgui::surface()->DrawTexturedRect( 0, 0, GetWide(), GetTall() ); |
|
} |
|
|
|
virtual void OnMousePressed(MouseCode code) |
|
{ |
|
if( GameUI().IsInLevel() ) return; |
|
|
|
m_bSelected = true; |
|
input()->SetMouseCapture(GetVPanel()); |
|
} |
|
|
|
virtual void OnMouseReleased(MouseCode code) |
|
{ |
|
if( GameUI().IsInLevel() ) return; |
|
|
|
m_bSelected = false; |
|
#ifdef ANDROID |
|
if( m_szUrl ) SDL_OpenURL( m_szUrl ); |
|
#endif |
|
|
|
input()->SetMouseCapture(NULL); |
|
} |
|
|
|
void SetUrl( const char *url ) |
|
{ |
|
m_szUrl = url; |
|
} |
|
|
|
virtual void OnScreenSizeChanged( int nOldWidth, int nOldHeight ) |
|
{ |
|
int nw, nh; |
|
surface()->GetScreenSize(nw, nh); |
|
int scaled_w = scheme()->GetProportionalScaledValue(m_iOldW); |
|
|
|
Panel::SetPos(nw-scheme()->GetProportionalScaledValue(m_iOldX)-scaled_w, m_iOldY); |
|
Panel::SetSize(scaled_w, scheme()->GetProportionalScaledValue(m_iOldH)); |
|
} |
|
|
|
void SetBounds( int x, int y, int w, int h ) |
|
{ |
|
m_iOldX = x; m_iOldY = y; |
|
m_iOldW = w; m_iOldH = h; |
|
|
|
int nw, nh; |
|
surface()->GetScreenSize(nw, nh); |
|
int scaled_w = scheme()->GetProportionalScaledValue(m_iOldW); |
|
|
|
Panel::SetPos(nw-scheme()->GetProportionalScaledValue(m_iOldX)-scaled_w, m_iOldY); |
|
Panel::SetSize(scaled_w, scheme()->GetProportionalScaledValue(m_iOldH)); |
|
} |
|
|
|
private: |
|
int m_iOldX, m_iOldY; |
|
int m_iOldW, m_iOldH; |
|
|
|
bool m_bSelected; |
|
int m_textureID; |
|
const char *m_szUrl; |
|
}; |
|
|
|
void AddUrlButton(vgui::Panel *parent, const char *imgName, const char *url ) |
|
{ |
|
static int i = 0; |
|
ImageButton *panel = new ImageButton( parent, imgName ); |
|
panel->SetUrl( url ); |
|
panel->SetBounds( 15+i*52, 10, 48, 48 ); |
|
i++; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: General purpose 1 of N menu |
|
//----------------------------------------------------------------------------- |
|
class CGameMenu : public vgui::Menu |
|
{ |
|
public: |
|
DECLARE_CLASS_SIMPLE( CGameMenu, vgui::Menu ); |
|
|
|
CGameMenu(vgui::Panel *parent, const char *name) : BaseClass(parent, name) |
|
{ |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
// shows graphic button hints |
|
m_pConsoleFooter = new CFooterPanel( parent, "MainMenuFooter" ); |
|
|
|
int iFixedWidth = 245; |
|
|
|
#ifdef _X360 |
|
// In low def we need a smaller highlight |
|
XVIDEO_MODE videoMode; |
|
XGetVideoMode( &videoMode ); |
|
if ( !videoMode.fIsHiDef ) |
|
{ |
|
iFixedWidth = 240; |
|
} |
|
else |
|
{ |
|
iFixedWidth = 350; |
|
} |
|
#endif |
|
|
|
SetFixedWidth( iFixedWidth ); |
|
} |
|
else |
|
{ |
|
m_pConsoleFooter = NULL; |
|
} |
|
|
|
m_hMainMenuOverridePanel = NULL; |
|
} |
|
|
|
virtual void ApplySchemeSettings(IScheme *pScheme) |
|
{ |
|
BaseClass::ApplySchemeSettings(pScheme); |
|
|
|
int height = atoi(pScheme->GetResourceString("MainMenu.MenuItemHeight")); |
|
if( IsProportional() ) |
|
height = scheme()->GetProportionalScaledValue( height ); |
|
|
|
// make fully transparent |
|
SetMenuItemHeight(height); |
|
SetBgColor(Color(0, 0, 0, 0)); |
|
SetBorder(NULL); |
|
} |
|
|
|
virtual void LayoutMenuBorder() |
|
{ |
|
} |
|
|
|
void SetMainMenuOverride( vgui::VPANEL panel ) |
|
{ |
|
m_hMainMenuOverridePanel = panel; |
|
|
|
if ( m_hMainMenuOverridePanel ) |
|
{ |
|
// We've got an override panel. Nuke all our menu items. |
|
DeleteAllItems(); |
|
} |
|
} |
|
|
|
virtual void SetVisible(bool state) |
|
{ |
|
if ( m_hMainMenuOverridePanel ) |
|
{ |
|
// force to be always visible |
|
ipanel()->SetVisible( m_hMainMenuOverridePanel, true ); |
|
|
|
// move us to the back instead of going invisible |
|
if ( !state ) |
|
{ |
|
ipanel()->MoveToBack(m_hMainMenuOverridePanel); |
|
} |
|
} |
|
|
|
// force to be always visible |
|
BaseClass::SetVisible(true); |
|
|
|
// move us to the back instead of going invisible |
|
if (!state) |
|
{ |
|
ipanel()->MoveToBack(GetVPanel()); |
|
} |
|
} |
|
|
|
virtual int AddMenuItem(const char *itemName, const char *itemText, const char *command, Panel *target, KeyValues *userData = NULL) |
|
{ |
|
MenuItem *item = new CGameMenuItem(this, itemName); |
|
item->AddActionSignalTarget(target); |
|
item->SetCommand(command); |
|
item->SetText(itemText); |
|
item->SetUserData(userData); |
|
return BaseClass::AddMenuItem(item); |
|
} |
|
|
|
virtual int AddMenuItem(const char *itemName, wchar_t *itemText, const char *command, Panel *target, KeyValues *userData = NULL) |
|
{ |
|
MenuItem *item = new CGameMenuItem(this, itemName); |
|
item->AddActionSignalTarget(target); |
|
item->SetCommand(command); |
|
item->SetText(itemText); |
|
item->SetUserData(userData); |
|
return BaseClass::AddMenuItem(item); |
|
} |
|
|
|
virtual int AddMenuItem(const char *itemName, const char *itemText, KeyValues *command, Panel *target, KeyValues *userData = NULL) |
|
{ |
|
CGameMenuItem *item = new CGameMenuItem(this, itemName); |
|
item->AddActionSignalTarget(target); |
|
item->SetCommand(command); |
|
item->SetText(itemText); |
|
item->SetRightAlignedText(true); |
|
item->SetUserData(userData); |
|
return BaseClass::AddMenuItem(item); |
|
} |
|
|
|
virtual void SetMenuItemBlinkingState( const char *itemName, bool state ) |
|
{ |
|
for (int i = 0; i < GetChildCount(); i++) |
|
{ |
|
Panel *child = GetChild(i); |
|
MenuItem *menuItem = dynamic_cast<MenuItem *>(child); |
|
if (menuItem) |
|
{ |
|
if ( Q_strcmp( menuItem->GetCommand()->GetString("command", ""), itemName ) == 0 ) |
|
{ |
|
menuItem->SetBlink( state ); |
|
} |
|
} |
|
} |
|
InvalidateLayout(); |
|
} |
|
|
|
virtual void OnSetFocus() |
|
{ |
|
if ( m_hMainMenuOverridePanel ) |
|
{ |
|
Panel *pMainMenu = ipanel()->GetPanel( m_hMainMenuOverridePanel, "ClientDLL" ); |
|
if ( pMainMenu ) |
|
{ |
|
pMainMenu->PerformLayout(); |
|
} |
|
} |
|
|
|
BaseClass::OnSetFocus(); |
|
} |
|
|
|
virtual void OnCommand(const char *command) |
|
{ |
|
m_KeyRepeat.Reset(); |
|
|
|
|
|
if (!stricmp(command, "Open")) |
|
{ |
|
if ( m_hMainMenuOverridePanel ) |
|
{ |
|
// force to be always visible |
|
ipanel()->MoveToFront( m_hMainMenuOverridePanel ); |
|
ipanel()->RequestFocus( m_hMainMenuOverridePanel ); |
|
} |
|
else |
|
{ |
|
MoveToFront(); |
|
RequestFocus(); |
|
} |
|
} |
|
else |
|
{ |
|
BaseClass::OnCommand(command); |
|
} |
|
} |
|
|
|
virtual void OnKeyCodePressed( KeyCode code ) |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
if ( GetAlpha() != 255 ) |
|
{ |
|
SetEnabled( false ); |
|
// inhibit key activity during transitions |
|
return; |
|
} |
|
|
|
SetEnabled( true ); |
|
|
|
if ( code == KEY_XBUTTON_B || code == KEY_XBUTTON_START ) |
|
{ |
|
if ( GameUI().IsInLevel() ) |
|
{ |
|
GetParent()->OnCommand( "ResumeGame" ); |
|
} |
|
return; |
|
} |
|
} |
|
|
|
m_KeyRepeat.KeyDown( code ); |
|
|
|
int nDir = 0; |
|
|
|
switch ( code ) |
|
{ |
|
case KEY_XBUTTON_UP: |
|
case KEY_XSTICK1_UP: |
|
case KEY_XSTICK2_UP: |
|
case KEY_UP: |
|
case STEAMCONTROLLER_DPAD_UP: |
|
nDir = -1; |
|
break; |
|
|
|
case KEY_XBUTTON_DOWN: |
|
case KEY_XSTICK1_DOWN: |
|
case KEY_XSTICK2_DOWN: |
|
case KEY_DOWN: |
|
case STEAMCONTROLLER_DPAD_DOWN: |
|
nDir = 1; |
|
break; |
|
} |
|
|
|
if ( nDir != 0 ) |
|
{ |
|
CUtlSortVector< SortedPanel_t, CSortedPanelYLess > vecSortedButtons; |
|
VguiPanelGetSortedChildButtonList( this, (void*)&vecSortedButtons ); |
|
|
|
if ( VguiPanelNavigateSortedChildButtonList( (void*)&vecSortedButtons, nDir ) != -1 ) |
|
{ |
|
// Handled! |
|
return; |
|
} |
|
} |
|
else if ( code == KEY_XBUTTON_A || code == STEAMCONTROLLER_A ) |
|
{ |
|
CUtlSortVector< SortedPanel_t, CSortedPanelYLess > vecSortedButtons; |
|
VguiPanelGetSortedChildButtonList( this, (void*)&vecSortedButtons ); |
|
|
|
for ( int i = 0; i < vecSortedButtons.Count(); i++ ) |
|
{ |
|
if ( vecSortedButtons[ i ].pButton->IsArmed() ) |
|
{ |
|
vecSortedButtons[ i ].pButton->DoClick(); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
BaseClass::OnKeyCodePressed( code ); |
|
|
|
// HACK: Allow F key bindings to operate even here |
|
if ( IsPC() && code >= KEY_F1 && code <= KEY_F12 ) |
|
{ |
|
// See if there is a binding for the FKey |
|
const char *binding = gameuifuncs->GetBindingForButtonCode( code ); |
|
if ( binding && binding[0] ) |
|
{ |
|
// submit the entry as a console commmand |
|
char szCommand[256]; |
|
Q_strncpy( szCommand, binding, sizeof( szCommand ) ); |
|
engine->ClientCmd_Unrestricted( szCommand ); |
|
} |
|
} |
|
} |
|
|
|
void OnKeyCodeReleased( vgui::KeyCode code ) |
|
{ |
|
m_KeyRepeat.KeyUp( code ); |
|
|
|
BaseClass::OnKeyCodeReleased( code ); |
|
} |
|
|
|
void OnThink() |
|
{ |
|
vgui::KeyCode code = m_KeyRepeat.KeyRepeated(); |
|
if ( code ) |
|
{ |
|
OnKeyCodeTyped( code ); |
|
} |
|
|
|
BaseClass::OnThink(); |
|
} |
|
|
|
virtual void OnKillFocus() |
|
{ |
|
BaseClass::OnKillFocus(); |
|
|
|
if ( m_hMainMenuOverridePanel ) |
|
{ |
|
// force us to the rear when we lose focus (so it looks like the menu is always on the background) |
|
surface()->MovePopupToBack( m_hMainMenuOverridePanel ); |
|
} |
|
else |
|
{ |
|
// force us to the rear when we lose focus (so it looks like the menu is always on the background) |
|
surface()->MovePopupToBack(GetVPanel()); |
|
} |
|
|
|
m_KeyRepeat.Reset(); |
|
} |
|
|
|
void ShowFooter( bool bShow ) |
|
{ |
|
if ( m_pConsoleFooter ) |
|
{ |
|
m_pConsoleFooter->SetVisible( bShow ); |
|
} |
|
} |
|
|
|
void UpdateMenuItemState( bool isInGame, bool isMultiplayer, bool isInReplay, bool isVREnabled, bool isVRActive ) |
|
{ |
|
bool isSteam = IsPC() && ( CommandLine()->FindParm("-steam") != 0 ); |
|
bool bIsConsoleUI = GameUI().IsConsoleUI(); |
|
|
|
// disabled save button if we're not in a game |
|
for (int i = 0; i < GetChildCount(); i++) |
|
{ |
|
Panel *child = GetChild(i); |
|
MenuItem *menuItem = dynamic_cast<MenuItem *>(child); |
|
if (menuItem) |
|
{ |
|
bool shouldBeVisible = true; |
|
// filter the visibility |
|
KeyValues *kv = menuItem->GetUserData(); |
|
if (!kv) |
|
continue; |
|
|
|
if (!isInGame && kv->GetInt("OnlyInGame") ) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
if (!isInReplay && kv->GetInt("OnlyInReplay") ) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
else if (!isVREnabled && kv->GetInt("OnlyWhenVREnabled") ) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
else if ( ( !isVRActive || ShouldForceVRActive() ) && kv->GetInt( "OnlyWhenVRActive" ) ) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
else if (isVRActive && kv->GetInt("OnlyWhenVRInactive") ) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
else if (isMultiplayer && kv->GetInt("notmulti")) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
else if (isInGame && !isMultiplayer && kv->GetInt("notsingle")) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
else if (isSteam && kv->GetInt("notsteam")) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
else if ( !bIsConsoleUI && kv->GetInt( "ConsoleOnly" ) ) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
|
|
// If we're playing back a replay, hide everything else |
|
if ( isInReplay && !kv->GetInt("OnlyInReplay") ) |
|
{ |
|
shouldBeVisible = false; |
|
} |
|
|
|
menuItem->SetVisible( shouldBeVisible ); |
|
} |
|
} |
|
|
|
if ( !isInGame ) |
|
{ |
|
// Sort them into their original order |
|
for ( int j = 0; j < GetChildCount() - 2; j++ ) |
|
{ |
|
MoveMenuItem( j, j + 1 ); |
|
} |
|
} |
|
else |
|
{ |
|
// Sort them into their in game order |
|
for ( int i = 0; i < GetChildCount(); i++ ) |
|
{ |
|
for ( int j = i; j < GetChildCount() - 2; j++ ) |
|
{ |
|
int iID1 = GetMenuID( j ); |
|
int iID2 = GetMenuID( j + 1 ); |
|
|
|
MenuItem *menuItem1 = GetMenuItem( iID1 ); |
|
MenuItem *menuItem2 = GetMenuItem( iID2 ); |
|
|
|
KeyValues *kv1 = menuItem1->GetUserData(); |
|
KeyValues *kv2 = menuItem2->GetUserData(); |
|
|
|
if( !kv1 || !kv2 ) |
|
continue; |
|
|
|
if ( kv1->GetInt("InGameOrder") > kv2->GetInt("InGameOrder") ) |
|
MoveMenuItem( iID2, iID1 ); |
|
} |
|
} |
|
} |
|
|
|
InvalidateLayout(); |
|
|
|
if ( m_pConsoleFooter ) |
|
{ |
|
// update the console footer |
|
const char *pHelpName; |
|
if ( !isInGame ) |
|
pHelpName = "MainMenu"; |
|
else |
|
pHelpName = "GameMenu"; |
|
|
|
if ( !m_pConsoleFooter->GetHelpName() || V_stricmp( pHelpName, m_pConsoleFooter->GetHelpName() ) ) |
|
{ |
|
// game menu must re-establish its own help once it becomes re-active |
|
m_pConsoleFooter->SetHelpNameAndReset( pHelpName ); |
|
m_pConsoleFooter->AddNewButtonLabel( "#GameUI_Action", "#GameUI_Icons_A_BUTTON" ); |
|
if ( isInGame ) |
|
{ |
|
m_pConsoleFooter->AddNewButtonLabel( "#GameUI_Close", "#GameUI_Icons_B_BUTTON" ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
MESSAGE_FUNC_HANDLE( OnCursorEnteredMenuItem, "CursorEnteredMenuItem", menuItem); |
|
|
|
private: |
|
CFooterPanel *m_pConsoleFooter; |
|
vgui::CKeyRepeatHandler m_KeyRepeat; |
|
vgui::VPANEL m_hMainMenuOverridePanel; |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Respond to cursor entering a menuItem. |
|
//----------------------------------------------------------------------------- |
|
void CGameMenu::OnCursorEnteredMenuItem(VPANEL menuItem) |
|
{ |
|
MenuItem *item = static_cast<MenuItem *>(ipanel()->GetPanel(menuItem, GetModuleName())); |
|
KeyValues *pCommand = item->GetCommand(); |
|
if ( !pCommand->GetFirstSubKey() ) |
|
return; |
|
const char *pszCmd = pCommand->GetFirstSubKey()->GetString(); |
|
if ( !pszCmd || !pszCmd[0] ) |
|
return; |
|
|
|
BaseClass::OnCursorEnteredMenuItem( menuItem ); |
|
} |
|
|
|
static CBackgroundMenuButton* CreateMenuButton( CBasePanel *parent, const char *panelName, const wchar_t *panelText ) |
|
{ |
|
CBackgroundMenuButton *pButton = new CBackgroundMenuButton( parent, panelName ); |
|
pButton->SetCommand("OpenGameMenu"); |
|
pButton->SetText(panelText); |
|
|
|
return pButton; |
|
} |
|
|
|
bool g_bIsCreatingNewGameMenuForPreFetching = false; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CBasePanel::CBasePanel() : Panel(NULL, "BaseGameUIPanel") |
|
{ |
|
if( NeedProportional() ) |
|
SetProportional( true ); |
|
|
|
g_pBasePanel = this; |
|
m_bLevelLoading = false; |
|
m_eBackgroundState = BACKGROUND_INITIAL; |
|
m_flTransitionStartTime = 0.0f; |
|
m_flTransitionEndTime = 0.0f; |
|
m_flFrameFadeInTime = 0.5f; |
|
m_bRenderingBackgroundTransition = false; |
|
m_bFadingInMenus = false; |
|
m_bEverActivated = false; |
|
m_iGameMenuInset = 24; |
|
m_bPlatformMenuInitialized = false; |
|
m_bHaveDarkenedBackground = false; |
|
m_bHaveDarkenedTitleText = true; |
|
m_bForceTitleTextUpdate = true; |
|
m_BackdropColor = Color(0, 0, 0, 128); |
|
m_pConsoleAnimationController = NULL; |
|
m_pConsoleControlSettings = NULL; |
|
m_bCopyFrameBuffer = false; |
|
m_bUseRenderTargetImage = false; |
|
m_ExitingFrameCount = 0; |
|
m_bXUIVisible = false; |
|
m_bUseMatchmaking = false; |
|
m_bRestartFromInvite = false; |
|
m_bRestartSameGame = false; |
|
m_bUserRefusedSignIn = false; |
|
m_bUserRefusedStorageDevice = false; |
|
m_bWaitingForUserSignIn = false; |
|
m_bWaitingForStorageDeviceHandle = false; |
|
m_bNeedStorageDeviceHandle = false; |
|
m_bStorageBladeShown = false; |
|
m_iStorageID = XBX_INVALID_STORAGE_ID; |
|
m_pAsyncJob = NULL; |
|
m_pStorageDeviceValidatedNotify = NULL; |
|
|
|
m_iRenderTargetImageID = -1; |
|
m_iBackgroundImageID = -1; |
|
m_iProductImageID = -1; |
|
m_iLoadingImageID = -1; |
|
|
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
m_pConsoleAnimationController = new AnimationController( this ); |
|
m_pConsoleAnimationController->SetScriptFile( GetVPanel(), "scripts/GameUIAnimations.txt" ); |
|
m_pConsoleAnimationController->SetAutoReloadScript( IsDebug() ); |
|
|
|
m_pConsoleControlSettings = new KeyValues( "XboxDialogs.res" ); |
|
if ( !m_pConsoleControlSettings->LoadFromFile( g_pFullFileSystem, "resource/UI/XboxDialogs.res", "GAME" ) ) |
|
{ |
|
Error( "Failed to load UI control settings!\n" ); |
|
} |
|
else |
|
{ |
|
m_pConsoleControlSettings->ProcessResolutionKeys( surface()->GetResolutionKey() ); |
|
} |
|
|
|
#ifdef _X360 |
|
x360_audio_english.SetValue( XboxLaunch()->GetForceEnglish() ); |
|
#endif |
|
} |
|
|
|
m_pGameMenuButtons.AddToTail( CreateMenuButton( this, "GameMenuButton", ModInfo().GetGameTitle() ) ); |
|
m_pGameMenuButtons.AddToTail( CreateMenuButton( this, "GameMenuButton2", ModInfo().GetGameTitle2() ) ); |
|
#ifdef CS_BETA |
|
if ( !ModInfo().NoCrosshair() ) // hack to not show the BETA for HL2 or HL1Port |
|
{ |
|
m_pGameMenuButtons.AddToTail( CreateMenuButton( this, "BetaButton", L"BETA" ) ); |
|
} |
|
#endif // CS_BETA |
|
|
|
m_pGameMenu = NULL; |
|
m_pGameLogo = NULL; |
|
m_hMainMenuOverridePanel = NULL; |
|
|
|
if ( SteamClient() ) |
|
{ |
|
HSteamPipe steamPipe = SteamClient()->CreateSteamPipe(); |
|
ISteamUtils *pUtils = SteamClient()->GetISteamUtils( steamPipe, "SteamUtils002" ); |
|
if ( pUtils ) |
|
{ |
|
bSteamCommunityFriendsVersion = true; |
|
} |
|
|
|
SteamClient()->BReleaseSteamPipe( steamPipe ); |
|
} |
|
|
|
CreateGameMenu(); |
|
CreateGameLogo(); |
|
|
|
// Bonus maps menu blinks if something has been unlocked since the player last opened the menu |
|
// This is saved as persistant data, and here is where we check for that |
|
CheckBonusBlinkState(); |
|
|
|
// start the menus fully transparent |
|
SetMenuAlpha( 0 ); |
|
|
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
// do any costly resource prefetching now.... |
|
// force the new dialog to get all of its chapter pics |
|
g_bIsCreatingNewGameMenuForPreFetching = true; |
|
m_hNewGameDialog = new CNewGameDialog( this, false ); |
|
m_hNewGameDialog->MarkForDeletion(); |
|
g_bIsCreatingNewGameMenuForPreFetching = false; |
|
|
|
m_hOptionsDialog_Xbox = new COptionsDialogXbox( this ); |
|
m_hOptionsDialog_Xbox->MarkForDeletion(); |
|
|
|
m_hControllerDialog = new CControllerDialog( this ); |
|
m_hControllerDialog->MarkForDeletion(); |
|
|
|
ArmFirstMenuItem(); |
|
m_pConsoleAnimationController->StartAnimationSequence( "InitializeUILayout" ); |
|
} |
|
|
|
// Record data used for rich presence updates |
|
if ( IsX360() ) |
|
{ |
|
// Get our active mod directory name |
|
const char *pGameName = CommandLine()->ParmValue( "-game", "hl2" );; |
|
|
|
// Set the game we're playing |
|
m_iGameID = CONTEXT_GAME_GAME_HALF_LIFE_2; |
|
m_bSinglePlayer = true; |
|
if ( Q_stristr( pGameName, "episodic" ) ) |
|
{ |
|
m_iGameID = CONTEXT_GAME_GAME_EPISODE_ONE; |
|
} |
|
else if ( Q_stristr( pGameName, "ep2" ) ) |
|
{ |
|
m_iGameID = CONTEXT_GAME_GAME_EPISODE_TWO; |
|
} |
|
else if ( Q_stristr( pGameName, "portal" ) ) |
|
{ |
|
m_iGameID = CONTEXT_GAME_GAME_PORTAL; |
|
} |
|
else if ( Q_stristr( pGameName, "tf" ) ) |
|
{ |
|
m_iGameID = CONTEXT_GAME_GAME_TEAM_FORTRESS; |
|
m_bSinglePlayer = false; |
|
} |
|
} |
|
|
|
if( IsAndroid() ) |
|
{ |
|
AddUrlButton( this, "vgui/\x64\x69\x73\x63\x6f\x72\x64\x5f\x6c\x6f\x67\x6f", "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x64\x69\x73\x63\x6f\x72\x64\x2e\x67\x67\x2f\x68\x5a\x52\x42\x37\x57\x4d\x67\x47\x77" ); |
|
AddUrlButton( this, "vgui/\x74\x77\x69\x74\x74\x65\x72\x5f\x6c\x6f\x67\x6f", "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x74\x77\x69\x74\x74\x65\x72\x2e\x63\x6f\x6d\x2f\x6e\x69\x6c\x6c\x65\x72\x75\x73\x72" ); |
|
AddUrlButton( this, "vgui/\x74\x65\x6c\x65\x67\x72\x61\x6d\x5f\x6c\x6f\x67\x6f", "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x74\x2e\x6d\x65\x2f\x6e\x69\x6c\x6c\x65\x72\x75\x73\x72\x5f\x73\x6f\x75\x72\x63\x65" ); |
|
AddUrlButton( this, "vgui/\x67\x69\x74\x68\x75\x62\x5f\x6c\x6f\x67\x6f", "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x67\x69\x74\x68\x75\x62\x2e\x63\x6f\x6d\x2f\x6e\x69\x6c\x6c\x65\x72\x75\x73\x72\x2f\x73\x6f\x75\x72\x63\x65\x2d\x65\x6e\x67\x69\x6e\x65" ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Xbox 360 - Get the console UI keyvalues to pass to LoadControlSettings() |
|
//----------------------------------------------------------------------------- |
|
KeyValues *CBasePanel::GetConsoleControlSettings( void ) |
|
{ |
|
return m_pConsoleControlSettings; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Causes the first menu item to be armed |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::ArmFirstMenuItem( void ) |
|
{ |
|
UpdateGameMenus(); |
|
|
|
// Arm the first item in the menu |
|
for ( int i = 0; i < m_pGameMenu->GetItemCount(); ++i ) |
|
{ |
|
if ( m_pGameMenu->GetMenuItem( i )->IsVisible() ) |
|
{ |
|
m_pGameMenu->SetCurrentlyHighlightedItem( i ); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
CBasePanel::~CBasePanel() |
|
{ |
|
g_pBasePanel = NULL; |
|
|
|
if ( vgui::surface() ) |
|
{ |
|
if ( m_iRenderTargetImageID != -1 ) |
|
{ |
|
vgui::surface()->DestroyTextureID( m_iRenderTargetImageID ); |
|
m_iRenderTargetImageID = -1; |
|
} |
|
|
|
if ( m_iBackgroundImageID != -1 ) |
|
{ |
|
vgui::surface()->DestroyTextureID( m_iBackgroundImageID ); |
|
m_iBackgroundImageID = -1; |
|
} |
|
|
|
if ( m_iProductImageID != -1 ) |
|
{ |
|
vgui::surface()->DestroyTextureID( m_iProductImageID ); |
|
m_iProductImageID = -1; |
|
} |
|
|
|
if ( m_iLoadingImageID != -1 ) |
|
{ |
|
vgui::surface()->DestroyTextureID( m_iLoadingImageID ); |
|
m_iLoadingImageID = -1; |
|
} |
|
} |
|
} |
|
|
|
static const char *g_rgValidCommands[] = |
|
{ |
|
"OpenGameMenu", |
|
"OpenConsole", |
|
"OpenPlayerListDialog", |
|
"OpenNewGameDialog", |
|
"OpenLoadGameDialog", |
|
"OpenSaveGameDialog", |
|
"OpenCustomMapsDialog", |
|
"OpenOptionsDialog", |
|
"OpenBenchmarkDialog", |
|
"OpenServerBrowser", |
|
"OpenFriendsDialog", |
|
"OpenLoadDemoDialog", |
|
"OpenCreateMultiplayerGameDialog", |
|
"OpenChangeGameDialog", |
|
"OpenLoadCommentaryDialog", |
|
"Quit", |
|
"QuitNoConfirm", |
|
"ResumeGame", |
|
"Disconnect", |
|
}; |
|
|
|
static void CC_GameMenuCommand( const CCommand &args ) |
|
{ |
|
int c = args.ArgC(); |
|
if ( c < 2 ) |
|
{ |
|
Msg( "Usage: gamemenucommand <commandname>\n" ); |
|
return; |
|
} |
|
|
|
if ( !g_pBasePanel ) |
|
{ |
|
return; |
|
} |
|
|
|
vgui::ivgui()->PostMessage( g_pBasePanel->GetVPanel(), new KeyValues("Command", "command", args[1] ), NULL); |
|
} |
|
|
|
static int CC_GameMenuCompletionFunc( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ) |
|
{ |
|
char const *cmdname = "gamemenucommand"; |
|
|
|
char *substring = (char *)partial; |
|
if ( Q_strstr( partial, cmdname ) ) |
|
{ |
|
substring = (char *)partial + strlen( cmdname ) + 1; |
|
} |
|
|
|
int checklen = Q_strlen( substring ); |
|
|
|
CUtlRBTree< CUtlString > symbols( 0, 0, UtlStringLessFunc ); |
|
|
|
int i; |
|
int c = ARRAYSIZE( g_rgValidCommands ); |
|
for ( i = 0; i < c; ++i ) |
|
{ |
|
if ( Q_strnicmp( g_rgValidCommands[ i ], substring, checklen ) ) |
|
continue; |
|
|
|
CUtlString str; |
|
str = g_rgValidCommands[ i ]; |
|
|
|
symbols.Insert( str ); |
|
|
|
// Too many |
|
if ( symbols.Count() >= COMMAND_COMPLETION_MAXITEMS ) |
|
break; |
|
} |
|
|
|
// Now fill in the results |
|
int slot = 0; |
|
for ( i = symbols.FirstInorder(); i != symbols.InvalidIndex(); i = symbols.NextInorder( i ) ) |
|
{ |
|
char const *name = symbols[ i ].String(); |
|
|
|
char buf[ 512 ]; |
|
Q_strncpy( buf, name, sizeof( buf ) ); |
|
Q_strlower( buf ); |
|
|
|
Q_snprintf( commands[ slot++ ], COMMAND_COMPLETION_ITEM_LENGTH, "%s %s", |
|
cmdname, buf ); |
|
} |
|
|
|
return slot; |
|
} |
|
|
|
static ConCommand gamemenucommand( "gamemenucommand", CC_GameMenuCommand, "Issue game menu command.", 0, CC_GameMenuCompletionFunc ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: paints the main background image |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::PaintBackground() |
|
{ |
|
if ( !GameUI().IsInLevel() || g_hLoadingDialog.Get() || m_ExitingFrameCount ) |
|
{ |
|
// not in the game or loading dialog active or exiting, draw the ui background |
|
DrawBackgroundImage(); |
|
} |
|
else if ( IsX360() ) |
|
{ |
|
// only valid during loading from level to level |
|
m_bUseRenderTargetImage = false; |
|
} |
|
|
|
if ( m_flBackgroundFillAlpha ) |
|
{ |
|
int swide, stall; |
|
surface()->GetScreenSize(swide, stall); |
|
surface()->DrawSetColor(0, 0, 0, m_flBackgroundFillAlpha); |
|
surface()->DrawFilledRect(0, 0, swide, stall); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Updates which background state we should be in. |
|
// |
|
// NOTE: These states change at funny times and overlap. They CANNOT be |
|
// used to demarcate exact transitions. |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::UpdateBackgroundState() |
|
{ |
|
if ( m_ExitingFrameCount ) |
|
{ |
|
// trumps all, an exiting state must own the screen image |
|
// cannot be stopped |
|
SetBackgroundRenderState( BACKGROUND_EXITING ); |
|
} |
|
else if ( GameUI().IsInLevel() ) |
|
{ |
|
SetBackgroundRenderState( BACKGROUND_LEVEL ); |
|
} |
|
else if ( GameUI().IsInBackgroundLevel() && !m_bLevelLoading ) |
|
{ |
|
// 360 guarantees a progress bar |
|
// level loading is truly completed when the progress bar is gone, then transition to main menu |
|
if ( IsPC() || ( IsX360() && !g_hLoadingDialog.Get() ) ) |
|
{ |
|
SetBackgroundRenderState( BACKGROUND_MAINMENU ); |
|
} |
|
} |
|
else if ( m_bLevelLoading ) |
|
{ |
|
SetBackgroundRenderState( BACKGROUND_LOADING ); |
|
} |
|
else if ( m_bEverActivated && m_bPlatformMenuInitialized ) |
|
{ |
|
SetBackgroundRenderState( BACKGROUND_DISCONNECTED ); |
|
} |
|
|
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
if ( !m_ExitingFrameCount && !m_bLevelLoading && !g_hLoadingDialog.Get() && GameUI().IsInLevel() ) |
|
{ |
|
// paused |
|
if ( m_flBackgroundFillAlpha == 0.0f ) |
|
m_flBackgroundFillAlpha = 120.0f; |
|
} |
|
else |
|
{ |
|
m_flBackgroundFillAlpha = 0; |
|
} |
|
|
|
// console ui has completely different menu/dialog/fill/fading behavior |
|
return; |
|
} |
|
|
|
// don't evaluate the rest until we've initialized the menus |
|
if ( !m_bPlatformMenuInitialized ) |
|
return; |
|
|
|
// check for background fill |
|
// fill over the top if we have any dialogs up |
|
int i; |
|
bool bHaveActiveDialogs = false; |
|
bool bIsInLevel = GameUI().IsInLevel(); |
|
for ( i = 0; i < GetChildCount(); ++i ) |
|
{ |
|
VPANEL child = ipanel()->GetChild( GetVPanel(), i ); |
|
if ( child |
|
&& ipanel()->IsVisible( child ) |
|
&& ipanel()->IsPopup( child ) |
|
&& child != m_pGameMenu->GetVPanel() ) |
|
{ |
|
bHaveActiveDialogs = true; |
|
} |
|
} |
|
// see if the base gameui panel has dialogs hanging off it (engine stuff, console, bug reporter) |
|
VPANEL parent = GetVParent(); |
|
for ( i = 0; i < ipanel()->GetChildCount( parent ); ++i ) |
|
{ |
|
VPANEL child = ipanel()->GetChild( parent, i ); |
|
if ( child |
|
&& ipanel()->IsVisible( child ) |
|
&& ipanel()->IsPopup( child ) |
|
&& child != GetVPanel() ) |
|
{ |
|
bHaveActiveDialogs = true; |
|
} |
|
} |
|
|
|
// check to see if we need to fade in the background fill |
|
bool bNeedDarkenedBackground = (bHaveActiveDialogs || bIsInLevel); |
|
if ( m_bHaveDarkenedBackground != bNeedDarkenedBackground ) |
|
{ |
|
// fade in faster than we fade out |
|
float targetAlpha, duration; |
|
if ( bNeedDarkenedBackground ) |
|
{ |
|
// fade in background tint |
|
targetAlpha = m_BackdropColor[3]; |
|
duration = m_flFrameFadeInTime; |
|
} |
|
else |
|
{ |
|
// fade out background tint |
|
targetAlpha = 0.0f; |
|
duration = 2.0f; |
|
} |
|
|
|
m_bHaveDarkenedBackground = bNeedDarkenedBackground; |
|
vgui::GetAnimationController()->RunAnimationCommand( this, "m_flBackgroundFillAlpha", targetAlpha, 0.0f, duration, AnimationController::INTERPOLATOR_LINEAR ); |
|
} |
|
|
|
// check to see if the game title should be dimmed |
|
// don't transition on level change |
|
if ( m_bLevelLoading ) |
|
return; |
|
|
|
bool bNeedDarkenedTitleText = bHaveActiveDialogs; |
|
if (m_bHaveDarkenedTitleText != bNeedDarkenedTitleText || m_bForceTitleTextUpdate) |
|
{ |
|
float targetTitleAlpha, duration; |
|
if (bHaveActiveDialogs) |
|
{ |
|
// fade out title text |
|
duration = m_flFrameFadeInTime; |
|
targetTitleAlpha = 32.0f; |
|
} |
|
else |
|
{ |
|
// fade in title text |
|
duration = 2.0f; |
|
targetTitleAlpha = 255.0f; |
|
} |
|
|
|
if ( m_pGameLogo ) |
|
{ |
|
vgui::GetAnimationController()->RunAnimationCommand( m_pGameLogo, "alpha", targetTitleAlpha, 0.0f, duration, AnimationController::INTERPOLATOR_LINEAR ); |
|
} |
|
|
|
// Msg( "animating title (%d => %d at time %.2f)\n", m_pGameMenuButtons[0]->GetAlpha(), (int)targetTitleAlpha, engine->Time()); |
|
for ( i=0; i<m_pGameMenuButtons.Count(); ++i ) |
|
{ |
|
vgui::GetAnimationController()->RunAnimationCommand( m_pGameMenuButtons[i], "alpha", targetTitleAlpha, 0.0f, duration, AnimationController::INTERPOLATOR_LINEAR ); |
|
} |
|
m_bHaveDarkenedTitleText = bNeedDarkenedTitleText; |
|
m_bForceTitleTextUpdate = false; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: sets how the game background should render |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::SetBackgroundRenderState(EBackgroundState state) |
|
{ |
|
if ( state == m_eBackgroundState ) |
|
{ |
|
return; |
|
} |
|
|
|
// apply state change transition |
|
float frametime = engine->Time(); |
|
|
|
if ( m_eBackgroundState == BACKGROUND_INITIAL && ( state == BACKGROUND_DISCONNECTED || state == BACKGROUND_MAINMENU ) ) |
|
{ |
|
ConVar* dev_loadtime_mainmenu = cvar->FindVar( "dev_loadtime_mainmenu" ); |
|
if (dev_loadtime_mainmenu) { |
|
dev_loadtime_mainmenu->SetValue( frametime ); |
|
} |
|
} |
|
|
|
|
|
m_bRenderingBackgroundTransition = false; |
|
m_bFadingInMenus = false; |
|
|
|
CMatchmakingBasePanel *pPanel = GetMatchmakingBasePanel(); |
|
|
|
if ( pPanel ) |
|
{ |
|
if ( state == BACKGROUND_LOADING ) |
|
{ |
|
pPanel->SetVisible( false ); |
|
} |
|
else |
|
{ |
|
pPanel->SetVisible( true ); |
|
} |
|
} |
|
|
|
if ( state == BACKGROUND_EXITING ) |
|
{ |
|
// hide the menus |
|
m_bCopyFrameBuffer = false; |
|
} |
|
else if ( state == BACKGROUND_DISCONNECTED || state == BACKGROUND_MAINMENU ) |
|
{ |
|
// menu fading |
|
// make the menus visible |
|
m_bFadingInMenus = true; |
|
m_flFadeMenuStartTime = frametime; |
|
m_flFadeMenuEndTime = frametime + 3.0f; |
|
|
|
if ( state == BACKGROUND_MAINMENU ) |
|
{ |
|
// fade background into main menu |
|
m_bRenderingBackgroundTransition = true; |
|
m_flTransitionStartTime = frametime; |
|
m_flTransitionEndTime = frametime + 3.0f; |
|
} |
|
} |
|
else if ( state == BACKGROUND_LOADING ) |
|
{ |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
RunAnimationWithCallback( this, "InstantHideMainMenu", new KeyValues( "LoadMap" ) ); |
|
} |
|
|
|
// hide the menus |
|
SetMenuAlpha( 0 ); |
|
} |
|
else if ( state == BACKGROUND_LEVEL ) |
|
{ |
|
// show the menus |
|
SetMenuAlpha( 255 ); |
|
} |
|
|
|
m_eBackgroundState = state; |
|
} |
|
|
|
void CBasePanel::StartExitingProcess() |
|
{ |
|
// must let a non trivial number of screen swaps occur to stabilize image |
|
// ui runs in a constrained state, while shutdown is occurring |
|
m_flTransitionStartTime = engine->Time(); |
|
m_flTransitionEndTime = m_flTransitionStartTime + 0.5f; |
|
m_ExitingFrameCount = 30; |
|
g_pInputSystem->DetachFromWindow(); |
|
|
|
CMatchmakingBasePanel *pPanel = GetMatchmakingBasePanel(); |
|
if ( pPanel ) |
|
{ |
|
pPanel->CloseAllDialogs( false ); |
|
} |
|
|
|
engine->StartXboxExitingProcess(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Size should only change on first vgui frame after startup |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnSizeChanged( int newWide, int newTall ) |
|
{ |
|
// Recenter message dialogs |
|
m_MessageDialogHandler.PositionDialogs( newWide, newTall ); |
|
|
|
if ( m_hMatchmakingBasePanel.Get() ) |
|
{ |
|
m_hMatchmakingBasePanel->SetBounds( 0, 0, newWide, newTall ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: notifications |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnLevelLoadingStarted() |
|
{ |
|
m_bLevelLoading = true; |
|
|
|
m_pGameMenu->ShowFooter( false ); |
|
|
|
if ( m_hMatchmakingBasePanel.Get() ) |
|
{ |
|
m_hMatchmakingBasePanel->OnCommand( "LevelLoadingStarted" ); |
|
} |
|
|
|
if ( IsX360() && m_eBackgroundState == BACKGROUND_LEVEL ) |
|
{ |
|
// already in a level going to another level |
|
// frame buffer is about to be cleared, copy it off for ui backing purposes |
|
m_bCopyFrameBuffer = true; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: notification |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnLevelLoadingFinished() |
|
{ |
|
m_bLevelLoading = false; |
|
|
|
if ( m_hMatchmakingBasePanel.Get() ) |
|
{ |
|
m_hMatchmakingBasePanel->OnCommand( "LevelLoadingFinished" ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Draws the background image. |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::DrawBackgroundImage() |
|
{ |
|
if ( IsX360() && m_bCopyFrameBuffer ) |
|
{ |
|
// force the engine to do an image capture ONCE into this image's render target |
|
char filename[MAX_PATH]; |
|
surface()->DrawGetTextureFile( m_iRenderTargetImageID, filename, sizeof( filename ) ); |
|
engine->CopyFrameBufferToMaterial( filename ); |
|
m_bCopyFrameBuffer = false; |
|
m_bUseRenderTargetImage = true; |
|
} |
|
|
|
int wide, tall; |
|
GetSize( wide, tall ); |
|
|
|
float frametime = engine->Time(); |
|
|
|
// a background transition has a running map underneath it, so fade image out |
|
// otherwise, there is no map and the background image stays opaque |
|
int alpha = 255; |
|
if ( m_bRenderingBackgroundTransition ) |
|
{ |
|
// goes from [255..0] |
|
alpha = (m_flTransitionEndTime - frametime) / (m_flTransitionEndTime - m_flTransitionStartTime) * 255; |
|
alpha = clamp( alpha, 0, 255 ); |
|
} |
|
|
|
// an exiting process needs to opaquely cover everything |
|
if ( m_ExitingFrameCount ) |
|
{ |
|
// goes from [0..255] |
|
alpha = (m_flTransitionEndTime - frametime) / (m_flTransitionEndTime - m_flTransitionStartTime) * 255; |
|
alpha = 255 - clamp( alpha, 0, 255 ); |
|
} |
|
|
|
int iImageID = m_iBackgroundImageID; |
|
if ( IsX360() ) |
|
{ |
|
if ( m_ExitingFrameCount ) |
|
{ |
|
if ( !m_bRestartSameGame ) |
|
{ |
|
iImageID = m_iProductImageID; |
|
} |
|
} |
|
else if ( m_bUseRenderTargetImage ) |
|
{ |
|
// the render target image must be opaque, the alpha channel contents are unknown |
|
// it is strictly an opaque background image and never used as an overlay |
|
iImageID = m_iRenderTargetImageID; |
|
alpha = 255; |
|
} |
|
} |
|
|
|
surface()->DrawSetColor( 255, 255, 255, alpha ); |
|
surface()->DrawSetTexture( iImageID ); |
|
surface()->DrawTexturedRect( 0, 0, wide, tall ); |
|
|
|
if ( IsX360() && m_ExitingFrameCount ) |
|
{ |
|
// Make invisible when going back to appchooser |
|
m_pGameMenu->CGameMenu::BaseClass::SetVisible( false ); |
|
|
|
IScheme *pScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "SourceScheme" ) ); |
|
HFont hFont = pScheme->GetFont( "ChapterTitle" ); |
|
wchar_t *pString = g_pVGuiLocalize->Find( "#GameUI_Loading" ); |
|
int textWide, textTall; |
|
surface()->GetTextSize( hFont, pString, textWide, textTall ); |
|
surface()->DrawSetTextPos( ( wide - textWide )/2, tall * 0.50f ); |
|
surface()->DrawSetTextFont( hFont ); |
|
surface()->DrawSetTextColor( 255, 255, 255, alpha ); |
|
surface()->DrawPrintText( pString, wcslen( pString ) ); |
|
} |
|
|
|
// 360 always use the progress bar, TCR Requirement, and never this loading plaque |
|
if ( IsPC() && ( m_bRenderingBackgroundTransition || m_eBackgroundState == BACKGROUND_LOADING ) ) |
|
{ |
|
// draw the loading image over the top |
|
surface()->DrawSetColor(255, 255, 255, alpha); |
|
surface()->DrawSetTexture(m_iLoadingImageID); |
|
int twide, ttall; |
|
surface()->DrawGetTextureSize(m_iLoadingImageID, twide, ttall); |
|
surface()->DrawTexturedRect(wide - twide, tall - ttall, wide, tall); |
|
} |
|
|
|
// update the menu alpha |
|
if ( m_bFadingInMenus ) |
|
{ |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
m_pConsoleAnimationController->StartAnimationSequence( "OpenMainMenu" ); |
|
m_bFadingInMenus = false; |
|
} |
|
else |
|
{ |
|
// goes from [0..255] |
|
alpha = (frametime - m_flFadeMenuStartTime) / (m_flFadeMenuEndTime - m_flFadeMenuStartTime) * 255; |
|
alpha = clamp( alpha, 0, 255 ); |
|
m_pGameMenu->SetAlpha( alpha ); |
|
if ( alpha == 255 ) |
|
{ |
|
m_bFadingInMenus = false; |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::CreateGameMenu() |
|
{ |
|
// load settings from config file |
|
KeyValues *datafile = new KeyValues("GameMenu"); |
|
datafile->UsesEscapeSequences( true ); // VGUI uses escape sequences |
|
if (datafile->LoadFromFile( g_pFullFileSystem, "Resource/GameMenu.res" ) ) |
|
{ |
|
m_pGameMenu = RecursiveLoadGameMenu(datafile); |
|
} |
|
|
|
if ( !m_pGameMenu ) |
|
{ |
|
Error( "Could not load file Resource/GameMenu.res" ); |
|
} |
|
else |
|
{ |
|
// start invisible |
|
SETUP_PANEL( m_pGameMenu ); |
|
m_pGameMenu->SetAlpha( 0 ); |
|
} |
|
|
|
datafile->deleteThis(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::CreateGameLogo() |
|
{ |
|
if ( ModInfo().UseGameLogo() ) |
|
{ |
|
m_pGameLogo = new CMainMenuGameLogo( this, "GameLogo" ); |
|
|
|
if ( m_pGameLogo ) |
|
{ |
|
SETUP_PANEL( m_pGameLogo ); |
|
m_pGameLogo->InvalidateLayout( true, true ); |
|
|
|
// start invisible |
|
m_pGameLogo->SetAlpha( 0 ); |
|
} |
|
} |
|
else |
|
{ |
|
m_pGameLogo = NULL; |
|
} |
|
} |
|
|
|
void CBasePanel::CheckBonusBlinkState() |
|
{ |
|
#ifdef _X360 |
|
// On 360 if we have a storage device at this point and try to read the bonus data it can't find the bonus file! |
|
return; |
|
#endif |
|
|
|
if ( BonusMapsDatabase()->GetBlink() ) |
|
{ |
|
if ( GameUI().IsConsoleUI() ) |
|
SetMenuItemBlinkingState( "OpenNewGameDialog", true ); // Consoles integrate bonus maps menu into the new game menu |
|
else |
|
SetMenuItemBlinkingState( "OpenBonusMapsDialog", true ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Checks to see if menu items need to be enabled/disabled |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::UpdateGameMenus() |
|
{ |
|
// check our current state |
|
bool isInGame = GameUI().IsInLevel(); |
|
bool isMulti = isInGame && (engine->GetMaxClients() > 1); |
|
bool isInReplay = GameUI().IsInReplay(); |
|
bool isVREnabled = materials->GetCurrentConfigForVideoCard().m_nVRModeAdapter == materials->GetCurrentAdapter(); |
|
bool isVRActive = UseVR(); |
|
|
|
// iterate all the menu items |
|
m_pGameMenu->UpdateMenuItemState( isInGame, isMulti, isInReplay, isVREnabled, isVRActive ); |
|
|
|
if ( m_hMainMenuOverridePanel ) |
|
{ |
|
vgui::ivgui()->PostMessage( m_hMainMenuOverridePanel, new KeyValues( "UpdateMenu" ), NULL ); |
|
} |
|
|
|
// position the menu |
|
InvalidateLayout(); |
|
m_pGameMenu->SetVisible( true ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: sets up the game menu from the keyvalues |
|
// the game menu is hierarchial, so this is recursive |
|
//----------------------------------------------------------------------------- |
|
CGameMenu *CBasePanel::RecursiveLoadGameMenu(KeyValues *datafile) |
|
{ |
|
CGameMenu *menu = new CGameMenu(this, datafile->GetName()); |
|
|
|
wchar_t *pString = g_pVGuiLocalize->Find( "#GameUI_Console" ); |
|
|
|
if( pString ) |
|
menu->AddMenuItem("Console", V_wcsupr(pString), "OpenConsole", this); |
|
else |
|
menu->AddMenuItem("Console", "CONSOLE", "OpenConsole", this); |
|
|
|
bool bFoundServerBrowser = false; |
|
|
|
for (KeyValues *dat = datafile->GetFirstSubKey(); dat != NULL; dat = dat->GetNextKey()) |
|
{ |
|
const char *label = dat->GetString("label", "<unknown>"); |
|
const char *cmd = dat->GetString("command", NULL); |
|
const char *name = dat->GetString("name", label); |
|
|
|
if( cmd && Q_strcmp(cmd, "OpenServerBrowser") == 0 ) |
|
bFoundServerBrowser = true; |
|
} |
|
|
|
if( !bFoundServerBrowser && !ModInfo().IsSinglePlayerOnly() ) |
|
menu->AddMenuItem("AntiM*dG*yButton", "#GameUI_GameMenu_FindServers", "OpenServerBrowser", this); |
|
|
|
// loop through all the data adding items to the menu |
|
for (KeyValues *dat = datafile->GetFirstSubKey(); dat != NULL; dat = dat->GetNextKey()) |
|
{ |
|
const char *label = dat->GetString("label", "<unknown>"); |
|
const char *cmd = dat->GetString("command", NULL); |
|
const char *name = dat->GetString("name", label); |
|
|
|
if ( cmd && (!Q_stricmp( cmd, "OpenFriendsDialog" ) |
|
|| !Q_stricmp( cmd, "engine bug" )) ) |
|
continue; |
|
|
|
menu->AddMenuItem(name, label, cmd, this, dat); |
|
} |
|
|
|
return menu; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: update the taskbar a frame |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::RunFrame() |
|
{ |
|
InvalidateLayout(); |
|
vgui::GetAnimationController()->UpdateAnimations( engine->Time() ); |
|
|
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
// run the console ui animations |
|
m_pConsoleAnimationController->UpdateAnimations( engine->Time() ); |
|
|
|
if ( IsX360() && m_ExitingFrameCount && engine->Time() >= m_flTransitionEndTime ) |
|
{ |
|
if ( m_ExitingFrameCount > 1 ) |
|
{ |
|
m_ExitingFrameCount--; |
|
if ( m_ExitingFrameCount == 1 ) |
|
{ |
|
// enough frames have transpired, send the single shot quit command |
|
// If we kicked off this event from an invite, we need to properly setup the restart to account for that |
|
if ( m_bRestartFromInvite ) |
|
{ |
|
engine->ClientCmd_Unrestricted( "quit_x360 invite" ); |
|
} |
|
else if ( m_bRestartSameGame ) |
|
{ |
|
engine->ClientCmd_Unrestricted( "quit_x360 restart" ); |
|
} |
|
else |
|
{ |
|
// quits to appchooser |
|
engine->ClientCmd_Unrestricted( "quit_x360\n" ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
UpdateBackgroundState(); |
|
|
|
if ( !m_bPlatformMenuInitialized ) |
|
{ |
|
// check to see if the platform is ready to load yet |
|
if ( IsX360() || g_VModuleLoader.IsPlatformReady() ) |
|
{ |
|
m_bPlatformMenuInitialized = true; |
|
} |
|
} |
|
|
|
// Check to see if a pending async task has already finished |
|
if ( m_pAsyncJob && !m_pAsyncJob->m_hThreadHandle ) |
|
{ |
|
m_pAsyncJob->Completed(); |
|
delete m_pAsyncJob; |
|
m_pAsyncJob = NULL; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Tells XBox Live our user is in the current game's menu |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::UpdateRichPresenceInfo() |
|
{ |
|
#if defined( _X360 ) |
|
// For all other users logged into this console (not primary), set to idle to satisfy cert |
|
for( uint i = 0; i < XUSER_MAX_COUNT; ++i ) |
|
{ |
|
XUSER_SIGNIN_STATE State = XUserGetSigninState( i ); |
|
|
|
if( State != eXUserSigninState_NotSignedIn ) |
|
{ |
|
if ( i != XBX_GetPrimaryUserId() ) |
|
{ |
|
// Set rich presence as 'idle' for users logged in that can't participate in orange box. |
|
if ( !xboxsystem->UserSetContext( i, X_CONTEXT_PRESENCE, CONTEXT_PRESENCE_IDLE, true ) ) |
|
{ |
|
Warning( "BasePanel: UserSetContext failed.\n" ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
if ( !GameUI().IsInLevel() ) |
|
{ |
|
if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), CONTEXT_GAME, m_iGameID, true ) ) |
|
{ |
|
Warning( "BasePanel: UserSetContext failed.\n" ); |
|
} |
|
if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), X_CONTEXT_PRESENCE, CONTEXT_PRESENCE_MENU, true ) ) |
|
{ |
|
Warning( "BasePanel: UserSetContext failed.\n" ); |
|
} |
|
if ( m_bSinglePlayer ) |
|
{ |
|
if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), X_CONTEXT_GAME_MODE, CONTEXT_GAME_MODE_SINGLEPLAYER, true ) ) |
|
{ |
|
Warning( "BasePanel: UserSetContext failed.\n" ); |
|
} |
|
} |
|
} |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Lays out the position of the taskbar |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
// Get the screen size |
|
int wide, tall; |
|
vgui::surface()->GetScreenSize(wide, tall); |
|
|
|
// Get the size of the menu |
|
int menuWide, menuTall; |
|
m_pGameMenu->GetSize( menuWide, menuTall ); |
|
|
|
int idealMenuY = m_iGameMenuPos.y; |
|
if ( idealMenuY + menuTall + m_iGameMenuInset > tall ) |
|
{ |
|
idealMenuY = tall - menuTall - m_iGameMenuInset; |
|
} |
|
|
|
int yDiff = idealMenuY - m_iGameMenuPos.y; |
|
|
|
for ( int i=0; i<m_pGameMenuButtons.Count(); ++i ) |
|
{ |
|
// Get the size of the logo text |
|
// int textWide, textTall; |
|
m_pGameMenuButtons[i]->SizeToContents(); |
|
//vgui::surface()->GetTextSize( m_pGameMenuButtons[i]->GetFont(), ModInfo().GetGameTitle(), textWide, textTall ); |
|
|
|
// place menu buttons above middle of screen |
|
m_pGameMenuButtons[i]->SetPos(m_iGameTitlePos[i].x, m_iGameTitlePos[i].y + yDiff); |
|
//m_pGameMenuButtons[i]->SetSize(textWide + 4, textTall + 4); |
|
} |
|
|
|
if ( m_pGameLogo ) |
|
{ |
|
// move the logo to sit right on top of the menu |
|
m_pGameLogo->SetPos( m_iGameMenuPos.x + m_pGameLogo->GetOffsetX(), idealMenuY - m_pGameLogo->GetTall() + m_pGameLogo->GetOffsetY() ); |
|
} |
|
|
|
// position self along middle of screen |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
int posx, posy; |
|
m_pGameMenu->GetPos( posx, posy ); |
|
m_iGameMenuPos.x = posx; |
|
} |
|
m_pGameMenu->SetPos(m_iGameMenuPos.x, idealMenuY); |
|
|
|
UpdateGameMenus(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Loads scheme information |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::ApplySchemeSettings(IScheme *pScheme) |
|
{ |
|
int i; |
|
BaseClass::ApplySchemeSettings(pScheme); |
|
|
|
m_iGameMenuInset = atoi(pScheme->GetResourceString("MainMenu.Inset")); |
|
m_iGameMenuInset *= 2; |
|
|
|
IScheme *pClientScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetScheme( "ClientScheme" ) ); |
|
CUtlVector< Color > buttonColor; |
|
if ( pClientScheme ) |
|
{ |
|
m_iGameTitlePos.RemoveAll(); |
|
for ( i=0; i<m_pGameMenuButtons.Count(); ++i ) |
|
{ |
|
m_pGameMenuButtons[i]->SetFont(pClientScheme->GetFont("ClientTitleFont", true)); |
|
m_iGameTitlePos.AddToTail( coord() ); |
|
m_iGameTitlePos[i].x = atoi(pClientScheme->GetResourceString( CFmtStr( "Main.Title%d.X", i+1 ) ) ); |
|
m_iGameTitlePos[i].x = scheme()->GetProportionalScaledValue( m_iGameTitlePos[i].x ); |
|
m_iGameTitlePos[i].y = atoi(pClientScheme->GetResourceString( CFmtStr( "Main.Title%d.Y", i+1 ) ) ); |
|
m_iGameTitlePos[i].y = scheme()->GetProportionalScaledValue( m_iGameTitlePos[i].y ); |
|
|
|
if ( GameUI().IsConsoleUI() ) |
|
m_iGameTitlePos[i].x += MAIN_MENU_INDENT_X360; |
|
|
|
buttonColor.AddToTail( pClientScheme->GetColor( CFmtStr( "Main.Title%d.Color", i+1 ), Color(255, 255, 255, 255)) ); |
|
} |
|
#ifdef CS_BETA |
|
if ( !ModInfo().NoCrosshair() ) // hack to not show the BETA for HL2 or HL1Port |
|
{ |
|
m_pGameMenuButtons[m_pGameMenuButtons.Count()-1]->SetFont(pClientScheme->GetFont("BetaFont", true)); |
|
} |
|
#endif // CS_BETA |
|
|
|
m_iGameMenuPos.x = atoi(pClientScheme->GetResourceString("Main.Menu.X")); |
|
m_iGameMenuPos.x = scheme()->GetProportionalScaledValue( m_iGameMenuPos.x ); |
|
m_iGameMenuPos.y = atoi(pClientScheme->GetResourceString("Main.Menu.Y")); |
|
m_iGameMenuPos.y = scheme()->GetProportionalScaledValue( m_iGameMenuPos.y ); |
|
|
|
m_iGameMenuInset = atoi(pClientScheme->GetResourceString("Main.BottomBorder")); |
|
m_iGameMenuInset = scheme()->GetProportionalScaledValue( m_iGameMenuInset ); |
|
} |
|
else |
|
{ |
|
for ( i=0; i<m_pGameMenuButtons.Count(); ++i ) |
|
{ |
|
m_pGameMenuButtons[i]->SetFont(pScheme->GetFont("TitleFont")); |
|
buttonColor.AddToTail( Color( 255, 255, 255, 255 ) ); |
|
} |
|
} |
|
|
|
for ( i=0; i<m_pGameMenuButtons.Count(); ++i ) |
|
{ |
|
m_pGameMenuButtons[i]->SetDefaultColor(buttonColor[i], Color(0, 0, 0, 0)); |
|
m_pGameMenuButtons[i]->SetArmedColor(buttonColor[i], Color(0, 0, 0, 0)); |
|
m_pGameMenuButtons[i]->SetDepressedColor(buttonColor[i], Color(0, 0, 0, 0)); |
|
} |
|
|
|
m_flFrameFadeInTime = atof(pScheme->GetResourceString("Frame.TransitionEffectTime")); |
|
|
|
// work out current focus - find the topmost panel |
|
SetBgColor(Color(0, 0, 0, 0)); |
|
|
|
m_BackdropColor = pScheme->GetColor("mainmenu.backdrop", Color(0, 0, 0, 128)); |
|
|
|
char filename[MAX_PATH]; |
|
if ( IsX360() ) |
|
{ |
|
// 360 uses FullFrameFB1 RT for map to map transitioning |
|
if ( m_iRenderTargetImageID == -1 ) |
|
{ |
|
m_iRenderTargetImageID = surface()->CreateNewTextureID(); |
|
surface()->DrawSetTextureFile( m_iRenderTargetImageID, "console/rt_background", false, false ); |
|
} |
|
} |
|
|
|
int screenWide, screenTall; |
|
surface()->GetScreenSize( screenWide, screenTall ); |
|
float aspectRatio = (float)screenWide/(float)screenTall; |
|
bool bIsWidescreen = aspectRatio >= 1.5999f; |
|
|
|
// work out which background image to use |
|
if ( IsPC() || !IsX360() ) |
|
{ |
|
// pc uses blurry backgrounds based on the background level |
|
char background[MAX_PATH]; |
|
engine->GetMainMenuBackgroundName( background, sizeof(background) ); |
|
Q_snprintf( filename, sizeof( filename ), "console/%s%s", background, ( bIsWidescreen ? "_widescreen" : "" ) ); |
|
} |
|
else |
|
{ |
|
// 360 uses hi-res game specific backgrounds |
|
char gameName[MAX_PATH]; |
|
const char *pGameDir = engine->GetGameDirectory(); |
|
V_FileBase( pGameDir, gameName, sizeof( gameName ) ); |
|
V_snprintf( filename, sizeof( filename ), "vgui/appchooser/background_%s%s", gameName, ( bIsWidescreen ? "_widescreen" : "" ) ); |
|
} |
|
|
|
if ( m_iBackgroundImageID == -1 ) |
|
{ |
|
m_iBackgroundImageID = surface()->CreateNewTextureID(); |
|
} |
|
surface()->DrawSetTextureFile( m_iBackgroundImageID, filename, false, false ); |
|
|
|
if ( IsX360() ) |
|
{ |
|
// 360 uses a product image during application exit |
|
V_snprintf( filename, sizeof( filename ), "vgui/appchooser/background_orange%s", ( bIsWidescreen ? "_widescreen" : "" ) ); |
|
|
|
if ( m_iProductImageID == -1 ) |
|
{ |
|
m_iProductImageID = surface()->CreateNewTextureID(); |
|
} |
|
surface()->DrawSetTextureFile( m_iProductImageID, filename, false, false ); |
|
} |
|
|
|
if ( IsPC() ) |
|
{ |
|
// load the loading icon |
|
if ( m_iLoadingImageID == -1 ) |
|
{ |
|
const char* loading = "console/startup_loading"; |
|
if ( IsSteamDeck() ) |
|
loading = "gamepadui/game_logo"; |
|
m_iLoadingImageID = surface()->CreateNewTextureID(); |
|
surface()->DrawSetTextureFile( m_iLoadingImageID, loading, false, false ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: message handler for platform menu; activates the selected module |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnActivateModule(int moduleIndex) |
|
{ |
|
g_VModuleLoader.ActivateModule(moduleIndex); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Animates menus on gameUI being shown |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnGameUIActivated() |
|
{ |
|
// If the load failed, we're going to bail out here |
|
if ( engine->MapLoadFailed() ) |
|
{ |
|
// Don't display this again until it happens again |
|
engine->SetMapLoadFailed( false ); |
|
ShowMessageDialog( MD_LOAD_FAILED_WARNING ); |
|
} |
|
|
|
|
|
if ( !m_bEverActivated ) |
|
{ |
|
// Layout the first time to avoid focus issues (setting menus visible will grab focus) |
|
UpdateGameMenus(); |
|
m_bEverActivated = true; |
|
|
|
#if defined( _X360 ) |
|
|
|
// Open all active containers if we have a valid storage device |
|
if ( XBX_GetPrimaryUserId() != XBX_INVALID_USER_ID && XBX_GetStorageDeviceId() != XBX_INVALID_STORAGE_ID && XBX_GetStorageDeviceId() != XBX_STORAGE_DECLINED ) |
|
{ |
|
// Open user settings and save game container here |
|
uint nRet = engine->OnStorageDeviceAttached(); |
|
if ( nRet != ERROR_SUCCESS ) |
|
{ |
|
// Invalidate the device |
|
XBX_SetStorageDeviceId( XBX_INVALID_STORAGE_ID ); |
|
|
|
// FIXME: We don't know which device failed! |
|
// Pop a dialog explaining that the user's data is corrupt |
|
BasePanel()->ShowMessageDialog( MD_STORAGE_DEVICES_CORRUPT ); |
|
} |
|
} |
|
|
|
// determine if we're starting up because of a cross-game invite |
|
int fLaunchFlags = XboxLaunch()->GetLaunchFlags(); |
|
if ( fLaunchFlags & LF_INVITERESTART ) |
|
{ |
|
XNKID nSessionID; |
|
XboxLaunch()->GetInviteSessionID( &nSessionID ); |
|
matchmaking->JoinInviteSessionByID( nSessionID ); |
|
} |
|
#endif |
|
|
|
// Brute force check to open tf matchmaking ui. |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
const char *pGame = engine->GetGameDirectory(); |
|
if ( !Q_stricmp( Q_UnqualifiedFileName( pGame ), "tf" ) ) |
|
{ |
|
m_bUseMatchmaking = true; |
|
RunMenuCommand( "OpenMatchmakingBasePanel" ); |
|
} |
|
} |
|
} |
|
|
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
ArmFirstMenuItem(); |
|
} |
|
if ( GameUI().IsInLevel() ) |
|
{ |
|
if ( !m_bUseMatchmaking ) |
|
{ |
|
OnCommand( "OpenPauseMenu" ); |
|
} |
|
else |
|
{ |
|
RunMenuCommand( "OpenMatchmakingBasePanel" ); |
|
} |
|
|
|
if ( m_hAchievementsDialog.Get() ) |
|
{ |
|
// Achievement dialog refreshes it's data if the player looks at the pause menu |
|
m_hAchievementsDialog->OnCommand( "OnGameUIActivated" ); |
|
} |
|
} |
|
else // not the pause menu, update presence |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
UpdateRichPresenceInfo(); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: executes a menu command |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::RunMenuCommand(const char *command) |
|
{ |
|
if ( !Q_stricmp( command, "OpenGameMenu" ) ) |
|
{ |
|
if ( m_pGameMenu ) |
|
{ |
|
PostMessage( m_pGameMenu, new KeyValues("Command", "command", "Open") ); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "OpenPlayerListDialog" ) ) |
|
{ |
|
OnOpenPlayerListDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenNewGameDialog" ) ) |
|
{ |
|
OnOpenNewGameDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenConsole" ) ) |
|
{ |
|
GameConsole().Activate(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenLoadGameDialog" ) ) |
|
{ |
|
if ( !GameUI().IsConsoleUI() ) |
|
{ |
|
OnOpenLoadGameDialog(); |
|
} |
|
else |
|
{ |
|
OnOpenLoadGameDialog_Xbox(); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "OpenSaveGameDialog" ) ) |
|
{ |
|
if ( !GameUI().IsConsoleUI() ) |
|
{ |
|
OnOpenSaveGameDialog(); |
|
} |
|
else |
|
{ |
|
OnOpenSaveGameDialog_Xbox(); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "OpenBonusMapsDialog" ) ) |
|
{ |
|
OnOpenBonusMapsDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenOptionsDialog" ) ) |
|
{ |
|
if ( !GameUI().IsConsoleUI() ) |
|
{ |
|
OnOpenOptionsDialog(); |
|
} |
|
else |
|
{ |
|
OnOpenOptionsDialog_Xbox(); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "OpenControllerDialog" ) ) |
|
{ |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
OnOpenControllerDialog(); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "OpenBenchmarkDialog" ) ) |
|
{ |
|
OnOpenBenchmarkDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenServerBrowser" ) ) |
|
{ |
|
OnOpenServerBrowser(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenFriendsDialog" ) ) |
|
{ |
|
OnOpenFriendsDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenLoadDemoDialog" ) ) |
|
{ |
|
OnOpenDemoDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenCreateMultiplayerGameDialog" ) ) |
|
{ |
|
OnOpenCreateMultiplayerGameDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenChangeGameDialog" ) ) |
|
{ |
|
OnOpenChangeGameDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenLoadCommentaryDialog" ) ) |
|
{ |
|
OnOpenLoadCommentaryDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenLoadSingleplayerCommentaryDialog" ) ) |
|
{ |
|
OpenLoadSingleplayerCommentaryDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenMatchmakingBasePanel" ) ) |
|
{ |
|
OnOpenMatchmakingBasePanel(); |
|
} |
|
else if ( !Q_stricmp( command, "OpenAchievementsDialog" ) ) |
|
{ |
|
if ( IsPC() ) |
|
{ |
|
#ifndef NO_STEAM |
|
if ( !steamapicontext->SteamUser() || !steamapicontext->SteamUser()->BLoggedOn() ) |
|
{ |
|
vgui::MessageBox *pMessageBox = new vgui::MessageBox("#GameUI_Achievements_SteamRequired_Title", "#GameUI_Achievements_SteamRequired_Message", this); |
|
pMessageBox->DoModal(); |
|
return; |
|
} |
|
#endif |
|
OnOpenAchievementsDialog(); |
|
} |
|
else |
|
{ |
|
OnOpenAchievementsDialog_Xbox(); |
|
} |
|
} |
|
//============================================================================= |
|
// HPE_BEGIN: |
|
// [dwenger] Use cs-specific achievements dialog |
|
//============================================================================= |
|
|
|
else if ( !Q_stricmp( command, "OpenCSAchievementsDialog" ) ) |
|
{ |
|
if ( IsPC() ) |
|
{ |
|
if ( !steamapicontext->SteamUser() || !steamapicontext->SteamUser()->BLoggedOn() ) |
|
{ |
|
vgui::MessageBox *pMessageBox = new vgui::MessageBox("#GameUI_Achievements_SteamRequired_Title", "#GameUI_Achievements_SteamRequired_Message", this ); |
|
pMessageBox->DoModal(); |
|
return; |
|
} |
|
|
|
OnOpenCSAchievementsDialog(); |
|
} |
|
} |
|
//============================================================================= |
|
// HPE_END |
|
//============================================================================= |
|
|
|
else if ( !Q_stricmp( command, "AchievementsDialogClosing" ) ) |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
if ( m_hAchievementsDialog.Get() ) |
|
{ |
|
m_hAchievementsDialog->Close(); |
|
} |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "Quit" ) ) |
|
{ |
|
OnOpenQuitConfirmationDialog(); |
|
} |
|
else if ( !Q_stricmp( command, "QuitNoConfirm" ) ) |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
// start the shutdown process |
|
StartExitingProcess(); |
|
} |
|
else |
|
{ |
|
//============================================================================= |
|
// HPE_BEGIN: |
|
// [dwenger] Shut down achievements panel |
|
//============================================================================= |
|
|
|
if ( GameClientExports() ) |
|
{ |
|
GameClientExports()->ShutdownAchievementPanel(); |
|
} |
|
|
|
//============================================================================= |
|
// HPE_END |
|
//============================================================================= |
|
|
|
// hide everything while we quit |
|
SetVisible( false ); |
|
vgui::surface()->RestrictPaintToSinglePanel( GetVPanel() ); |
|
engine->ClientCmd_Unrestricted( "quit\n" ); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "QuitRestartNoConfirm" ) ) |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
// start the shutdown process |
|
m_bRestartSameGame = true; |
|
StartExitingProcess(); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "ResumeGame" ) ) |
|
{ |
|
GameUI().HideGameUI(); |
|
} |
|
else if ( !Q_stricmp( command, "Disconnect" ) ) |
|
{ |
|
if ( IsX360() ) |
|
{ |
|
OnOpenDisconnectConfirmationDialog(); |
|
} |
|
else |
|
{ |
|
engine->ClientCmd_Unrestricted( "disconnect" ); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "DisconnectNoConfirm" ) ) |
|
{ |
|
ConVarRef commentary( "commentary" ); |
|
if ( commentary.IsValid() && commentary.GetBool() ) |
|
{ |
|
engine->ClientCmd_Unrestricted( "disconnect" ); |
|
|
|
CMatchmakingBasePanel *pBase = GetMatchmakingBasePanel(); |
|
if ( pBase ) |
|
{ |
|
pBase->CloseAllDialogs( false ); |
|
pBase->OnCommand( "OpenWelcomeDialog" ); |
|
} |
|
} |
|
else |
|
{ |
|
// Leave our current session, if we have one |
|
matchmaking->KickPlayerFromSession( 0 ); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "ReleaseModalWindow" ) ) |
|
{ |
|
vgui::surface()->RestrictPaintToSinglePanel(NULL); |
|
} |
|
else if ( Q_stristr( command, "engine " ) ) |
|
{ |
|
const char *engineCMD = strstr( command, "engine " ) + strlen( "engine " ); |
|
if ( strlen( engineCMD ) > 0 ) |
|
{ |
|
engine->ClientCmd_Unrestricted( const_cast<char *>( engineCMD ) ); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "ShowSigninUI" ) ) |
|
{ |
|
m_bWaitingForUserSignIn = true; |
|
xboxsystem->ShowSigninUI( 1, 0 ); // One user, no special flags |
|
} |
|
else if ( !Q_stricmp( command, "ShowDeviceSelector" ) ) |
|
{ |
|
OnChangeStorageDevice(); |
|
} |
|
else if ( !Q_stricmp( command, "SignInDenied" ) ) |
|
{ |
|
// The user doesn't care, so re-send the command they wanted and mark that we want to skip checking |
|
m_bUserRefusedSignIn = true; |
|
if ( m_strPostPromptCommand.IsEmpty() == false ) |
|
{ |
|
OnCommand( m_strPostPromptCommand ); |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "RequiredSignInDenied" ) ) |
|
{ |
|
m_strPostPromptCommand = ""; |
|
} |
|
else if ( !Q_stricmp( command, "RequiredStorageDenied" ) ) |
|
{ |
|
m_strPostPromptCommand = ""; |
|
} |
|
else if ( !Q_stricmp( command, "StorageDeviceDenied" ) ) |
|
{ |
|
// The user doesn't care, so re-send the command they wanted and mark that we want to skip checking |
|
m_bUserRefusedStorageDevice = true; |
|
IssuePostPromptCommand(); |
|
|
|
// Set us as declined |
|
XBX_SetStorageDeviceId( XBX_STORAGE_DECLINED ); |
|
m_iStorageID = XBX_INVALID_STORAGE_ID; |
|
|
|
if ( m_pStorageDeviceValidatedNotify ) |
|
{ |
|
*m_pStorageDeviceValidatedNotify = 2; |
|
m_pStorageDeviceValidatedNotify = NULL; |
|
} |
|
} |
|
else if ( !Q_stricmp( command, "clear_storage_deviceID" ) ) |
|
{ |
|
XBX_SetStorageDeviceId( XBX_STORAGE_DECLINED ); |
|
} |
|
else if ( !Q_stricmp( command, "RestartWithNewLanguage" ) ) |
|
{ |
|
if ( !IsX360() ) |
|
{ |
|
char szSteamURL[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) |
|
V_snprintf( szSteamURL, sizeof(szSteamURL), "steam://run/%d/%s", engine->GetAppID(), COptionsSubAudio::GetUpdatedAudioLanguage() ); |
|
|
|
// 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 |
|
#if defined( WIN32 ) && !defined( _X360 ) |
|
HKEY hKey; |
|
|
|
if ( IsPC() && RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Valve\\Source", NULL, KEY_WRITE, &hKey) == ERROR_SUCCESS ) |
|
{ |
|
RegSetValueEx( hKey, "Relaunch URL", 0, REG_SZ, (const unsigned char *)szSteamURL, sizeof( szSteamURL ) ); |
|
|
|
RegCloseKey(hKey); |
|
} |
|
#elif defined( OSX ) || defined( LINUX ) || defined(PLATFORM_BSD) |
|
FILE *fp = fopen( "/tmp/hl2_relaunch", "w+" ); |
|
if ( fp ) |
|
{ |
|
fprintf( fp, "%s\n", szSteamURL ); |
|
} |
|
fclose( fp ); |
|
#elif defined( _X360 ) |
|
#else |
|
#error |
|
#endif |
|
} |
|
} |
|
else |
|
{ |
|
BaseClass::OnCommand( command); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Queue a command to be run when XUI Closes |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::QueueCommand( const char *pCommand ) |
|
{ |
|
if ( m_bXUIVisible ) |
|
{ |
|
m_CommandQueue.AddToTail( CUtlString( pCommand ) ); |
|
} |
|
else |
|
{ |
|
OnCommand( pCommand ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Run all the commands in the queue |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::RunQueuedCommands() |
|
{ |
|
for ( int i = 0; i < m_CommandQueue.Count(); ++i ) |
|
{ |
|
OnCommand( m_CommandQueue[i] ); |
|
} |
|
ClearQueuedCommands(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Clear all queued commands |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::ClearQueuedCommands() |
|
{ |
|
m_CommandQueue.Purge(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Whether this command should cause us to prompt the user if they're not signed in and do not have a storage device |
|
//----------------------------------------------------------------------------- |
|
bool CBasePanel::IsPromptableCommand( const char *command ) |
|
{ |
|
// Blech! |
|
if ( !Q_stricmp( command, "OpenNewGameDialog" ) || |
|
!Q_stricmp( command, "OpenLoadGameDialog" ) || |
|
!Q_stricmp( command, "OpenSaveGameDialog" ) || |
|
!Q_stricmp( command, "OpenBonusMapsDialog" ) || |
|
!Q_stricmp( command, "OpenOptionsDialog" ) || |
|
!Q_stricmp( command, "OpenControllerDialog" ) || |
|
!Q_stricmp( command, "OpenLoadCommentaryDialog" ) || |
|
!Q_stricmp( command, "OpenLoadSingleplayerCommentaryDialog" ) || |
|
!Q_stricmp( command, "OpenAchievementsDialog" ) || |
|
|
|
//============================================================================= |
|
// HPE_BEGIN: |
|
// [dwenger] Use cs-specific achievements dialog |
|
//============================================================================= |
|
|
|
!Q_stricmp( command, "OpenCSAchievementsDialog" ) ) |
|
|
|
//============================================================================= |
|
// HPE_END |
|
//============================================================================= |
|
|
|
{ |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
#ifdef _WIN32 |
|
//------------------------- |
|
// Purpose: Job wrapper |
|
//------------------------- |
|
static uintp PanelJobWrapperFn( void *pvContext ) |
|
{ |
|
CBasePanel::CAsyncJobContext *pAsync = reinterpret_cast< CBasePanel::CAsyncJobContext * >( pvContext ); |
|
|
|
float const flTimeStart = Plat_FloatTime(); |
|
|
|
pAsync->ExecuteAsync(); |
|
|
|
float const flElapsedTime = Plat_FloatTime() - flTimeStart; |
|
|
|
if ( flElapsedTime < pAsync->m_flLeastExecuteTime ) |
|
{ |
|
ThreadSleep( ( pAsync->m_flLeastExecuteTime - flElapsedTime ) * 1000 ); |
|
} |
|
|
|
ReleaseThreadHandle( ( ThreadHandle_t ) pAsync->m_hThreadHandle ); |
|
pAsync->m_hThreadHandle = NULL; |
|
|
|
return 0; |
|
} |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Enqueues a job function to be called on a separate thread |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::ExecuteAsync( CAsyncJobContext *pAsync ) |
|
{ |
|
Assert( !m_pAsyncJob ); |
|
Assert( pAsync && !pAsync->m_hThreadHandle ); |
|
m_pAsyncJob = pAsync; |
|
|
|
#ifdef _WIN32 |
|
ThreadHandle_t hHandle = CreateSimpleThread( PanelJobWrapperFn, reinterpret_cast< void * >( pAsync ) ); |
|
pAsync->m_hThreadHandle = hHandle; |
|
|
|
#ifdef _X360 |
|
ThreadSetAffinity( hHandle, XBOX_PROCESSOR_3 ); |
|
#endif |
|
|
|
#else |
|
pAsync->ExecuteAsync(); |
|
#endif |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Whether this command requires the user be signed in |
|
//----------------------------------------------------------------------------- |
|
bool CBasePanel::CommandRequiresSignIn( const char *command ) |
|
{ |
|
// Blech again! |
|
if ( !Q_stricmp( command, "OpenAchievementsDialog" ) || |
|
|
|
//============================================================================= |
|
// HPE_BEGIN: |
|
// [dwenger] Use cs-specific achievements dialog |
|
//============================================================================= |
|
|
|
!Q_stricmp( command, "OpenCSAchievementsDialog" ) || |
|
|
|
//============================================================================= |
|
// HPE_END |
|
//============================================================================= |
|
|
|
!Q_stricmp( command, "OpenLoadGameDialog" ) || |
|
!Q_stricmp( command, "OpenSaveGameDialog" ) || |
|
!Q_stricmp( command, "OpenRankingsDialog" ) ) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Whether the command requires the user to have a valid storage device |
|
//----------------------------------------------------------------------------- |
|
bool CBasePanel::CommandRequiresStorageDevice( const char *command ) |
|
{ |
|
// Anything which touches the storage device must prompt |
|
if ( !Q_stricmp( command, "OpenSaveGameDialog" ) || |
|
!Q_stricmp( command, "OpenLoadGameDialog" ) ) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Whether the command requires the user to have a valid profile selected |
|
//----------------------------------------------------------------------------- |
|
bool CBasePanel::CommandRespectsSignInDenied( const char *command ) |
|
{ |
|
// Anything which touches the user profile must prompt |
|
if ( !Q_stricmp( command, "OpenOptionsDialog" ) || |
|
!Q_stricmp( command, "OpenControllerDialog" ) ) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: A storage device has been connected, update our settings and anything else |
|
//----------------------------------------------------------------------------- |
|
|
|
class CAsyncCtxOnDeviceAttached : public CBasePanel::CAsyncJobContext |
|
{ |
|
public: |
|
CAsyncCtxOnDeviceAttached(); |
|
~CAsyncCtxOnDeviceAttached(); |
|
virtual void ExecuteAsync(); |
|
virtual void Completed(); |
|
uint GetContainerOpenResult( void ) { return m_ContainerOpenResult; } |
|
|
|
private: |
|
uint m_ContainerOpenResult; |
|
}; |
|
|
|
CAsyncCtxOnDeviceAttached::CAsyncCtxOnDeviceAttached() : |
|
CBasePanel::CAsyncJobContext( 3.0f ), // Storage device info for at least 3 seconds |
|
m_ContainerOpenResult( ERROR_SUCCESS ) |
|
{ |
|
BasePanel()->ShowMessageDialog( MD_CHECKING_STORAGE_DEVICE ); |
|
} |
|
|
|
CAsyncCtxOnDeviceAttached::~CAsyncCtxOnDeviceAttached() |
|
{ |
|
BasePanel()->CloseMessageDialog( 0 ); |
|
} |
|
|
|
void CAsyncCtxOnDeviceAttached::ExecuteAsync() |
|
{ |
|
// Asynchronously do the tasks that don't interact with the command buffer |
|
|
|
// Open user settings and save game container here |
|
m_ContainerOpenResult = engine->OnStorageDeviceAttached(); |
|
if ( m_ContainerOpenResult != ERROR_SUCCESS ) |
|
return; |
|
|
|
// Make the QOS system initialized for multiplayer games |
|
if ( !ModInfo().IsSinglePlayerOnly() ) |
|
{ |
|
#if defined( _X360 ) |
|
( void ) matchmaking->GetQosWithLIVE(); |
|
#endif |
|
} |
|
} |
|
|
|
void CAsyncCtxOnDeviceAttached::Completed() |
|
{ |
|
BasePanel()->OnCompletedAsyncDeviceAttached( this ); |
|
} |
|
|
|
|
|
void CBasePanel::OnDeviceAttached( void ) |
|
{ |
|
ExecuteAsync( new CAsyncCtxOnDeviceAttached ); |
|
} |
|
|
|
void CBasePanel::OnCompletedAsyncDeviceAttached( CAsyncCtxOnDeviceAttached *job ) |
|
{ |
|
uint nRet = job->GetContainerOpenResult(); |
|
if ( nRet != ERROR_SUCCESS ) |
|
{ |
|
// Invalidate the device |
|
XBX_SetStorageDeviceId( XBX_INVALID_STORAGE_ID ); |
|
|
|
// FIXME: We don't know which device failed! |
|
// Pop a dialog explaining that the user's data is corrupt |
|
BasePanel()->ShowMessageDialog( MD_STORAGE_DEVICES_CORRUPT ); |
|
} |
|
|
|
// First part of the device checking completed asynchronously, |
|
// perform the rest of duties that require to run on main thread. |
|
engine->ReadConfiguration(); |
|
engine->ExecuteClientCmd( "refreshplayerstats" ); |
|
|
|
BonusMapsDatabase()->ReadBonusMapSaveData(); |
|
|
|
if ( m_hSaveGameDialog_Xbox.Get() ) |
|
{ |
|
m_hSaveGameDialog_Xbox->OnCommand( "RefreshSaveGames" ); |
|
} |
|
if ( m_hLoadGameDialog_Xbox.Get() ) |
|
{ |
|
m_hLoadGameDialog_Xbox->OnCommand( "RefreshSaveGames" ); |
|
} |
|
if ( m_hOptionsDialog_Xbox.Get() ) |
|
{ |
|
m_hOptionsDialog_Xbox->OnCommand( "RefreshOptions" ); |
|
} |
|
if ( m_pStorageDeviceValidatedNotify ) |
|
{ |
|
*m_pStorageDeviceValidatedNotify = 1; |
|
m_pStorageDeviceValidatedNotify = NULL; |
|
} |
|
|
|
// Finish their command |
|
IssuePostPromptCommand(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: FIXME: Only TF takes this path... |
|
//----------------------------------------------------------------------------- |
|
bool CBasePanel::ValidateStorageDevice( void ) |
|
{ |
|
if ( m_bUserRefusedStorageDevice == false ) |
|
{ |
|
#if defined( _X360 ) |
|
if ( XBX_GetStorageDeviceId() == XBX_INVALID_STORAGE_ID ) |
|
{ |
|
// Try to discover content on the user's storage devices |
|
DWORD nFoundDevice = xboxsystem->DiscoverUserData( XBX_GetPrimaryUserId(), COM_GetModDirectory() ); |
|
if ( nFoundDevice == XBX_INVALID_STORAGE_ID ) |
|
{ |
|
// They don't have a device, so ask for one |
|
ShowMessageDialog( MD_PROMPT_STORAGE_DEVICE ); |
|
return false; |
|
} |
|
else |
|
{ |
|
// Take this device |
|
XBX_SetStorageDeviceId( nFoundDevice ); |
|
OnDeviceAttached(); |
|
} |
|
// Fall through |
|
} |
|
#endif |
|
} |
|
return true; |
|
} |
|
|
|
bool CBasePanel::ValidateStorageDevice( int *pStorageDeviceValidated ) |
|
{ |
|
if ( m_pStorageDeviceValidatedNotify ) |
|
{ |
|
if ( pStorageDeviceValidated != m_pStorageDeviceValidatedNotify ) |
|
{ |
|
*m_pStorageDeviceValidatedNotify = -1; |
|
m_pStorageDeviceValidatedNotify = NULL; |
|
} |
|
else |
|
{ |
|
return false; |
|
} |
|
} |
|
|
|
if ( pStorageDeviceValidated ) |
|
{ |
|
if ( HandleStorageDeviceRequest( "" ) ) |
|
return true; |
|
|
|
m_pStorageDeviceValidatedNotify = pStorageDeviceValidated; |
|
return false; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Monitor commands for certain necessary cases |
|
// Input : *command - What menu command we're policing |
|
//----------------------------------------------------------------------------- |
|
bool CBasePanel::HandleSignInRequest( const char *command ) |
|
{ |
|
#ifdef _X360 |
|
// If we have a post-prompt command, we're coming back into the call from that prompt |
|
bool bQueuedCall = ( m_strPostPromptCommand.IsEmpty() == false ); |
|
|
|
XUSER_SIGNIN_INFO info; |
|
bool bValidUser = ( XUserGetSigninInfo( XBX_GetPrimaryUserId(), 0, &info ) == ERROR_SUCCESS ); |
|
|
|
if ( bValidUser ) |
|
return true; |
|
|
|
// Queued command means we're returning from a prompt or blade |
|
if ( bQueuedCall ) |
|
{ |
|
// Blade has returned with nothing |
|
if ( m_bUserRefusedSignIn ) |
|
return true; |
|
|
|
// User has not denied the storage device, so ask |
|
ShowMessageDialog( MD_PROMPT_SIGNIN ); |
|
m_strPostPromptCommand = command; |
|
|
|
// Do not run command |
|
return false; |
|
} |
|
else |
|
{ |
|
// If the user refused the sign-in and we respect that on this command, we're done |
|
if ( m_bUserRefusedSignIn && CommandRespectsSignInDenied( command ) ) |
|
return true; |
|
|
|
// If the message is required first, then do that instead |
|
if ( CommandRequiresSignIn( command ) ) |
|
{ |
|
ShowMessageDialog( MD_PROMPT_SIGNIN_REQUIRED ); |
|
m_strPostPromptCommand = command; |
|
return false; |
|
} |
|
|
|
// Pop a blade out |
|
xboxsystem->ShowSigninUI( 1, 0 ); |
|
m_strPostPromptCommand = command; |
|
m_bWaitingForUserSignIn = true; |
|
m_bUserRefusedSignIn = false; |
|
return false; |
|
} |
|
#endif // _X360 |
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *command - |
|
//----------------------------------------------------------------------------- |
|
bool CBasePanel::HandleStorageDeviceRequest( const char *command ) |
|
{ |
|
// If we don't have a valid sign-in, then we do nothing! |
|
if ( m_bUserRefusedSignIn ) |
|
return true; |
|
|
|
// If we have a valid storage device, there's nothing to prompt for |
|
if ( XBX_GetStorageDeviceId() != XBX_INVALID_STORAGE_ID && XBX_GetStorageDeviceId() != XBX_STORAGE_DECLINED ) |
|
return true; |
|
|
|
// If we have a post-prompt command, we're coming back into the call from that prompt |
|
bool bQueuedCall = ( m_strPostPromptCommand.IsEmpty() == false ); |
|
|
|
// Are we returning from a prompt? |
|
if ( bQueuedCall && m_bStorageBladeShown ) |
|
{ |
|
// User has declined |
|
if ( m_bUserRefusedStorageDevice ) |
|
return true; |
|
|
|
// Prompt them |
|
ShowMessageDialog( MD_PROMPT_STORAGE_DEVICE ); |
|
m_strPostPromptCommand = command; |
|
|
|
// Do not run the command |
|
return false; |
|
} |
|
else |
|
{ |
|
// If the user refused the sign-in and we respect that on this command, we're done |
|
if ( m_bUserRefusedStorageDevice && CommandRespectsSignInDenied( command ) ) |
|
return true; |
|
|
|
#if 0 // This attempts to find user data, but may not be cert-worthy even though it's a bit nicer for the user |
|
// Attempt to automatically find a device |
|
DWORD nFoundDevice = xboxsystem->DiscoverUserData( XBX_GetPrimaryUserId(), COM_GetModDirectory() ); |
|
if ( nFoundDevice != XBX_INVALID_STORAGE_ID ) |
|
{ |
|
// Take this device |
|
XBX_SetStorageDeviceId( nFoundDevice ); |
|
OnDeviceAttached(); |
|
return true; |
|
} |
|
#endif // |
|
|
|
// If the message is required first, then do that instead |
|
if ( CommandRequiresStorageDevice( command ) ) |
|
{ |
|
ShowMessageDialog( MD_PROMPT_STORAGE_DEVICE_REQUIRED ); |
|
m_strPostPromptCommand = command; |
|
return false; |
|
} |
|
|
|
// This is a misnomer of the first order! |
|
OnChangeStorageDevice(); |
|
m_strPostPromptCommand = command; |
|
m_bStorageBladeShown = true; |
|
m_bUserRefusedStorageDevice = false; |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Clear the command we've queued once it has succeeded in being called |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::ClearPostPromptCommand( const char *pCompletedCommand ) |
|
{ |
|
if ( !Q_stricmp( m_strPostPromptCommand, pCompletedCommand ) ) |
|
{ |
|
// All commands are executed, so stop holding this |
|
m_strPostPromptCommand = ""; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Issue our queued command to either the base panel or the matchmaking panel |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::IssuePostPromptCommand( void ) |
|
{ |
|
// The device is valid, so launch any pending commands |
|
if ( m_strPostPromptCommand.IsEmpty() == false ) |
|
{ |
|
if ( m_bSinglePlayer ) |
|
{ |
|
OnCommand( m_strPostPromptCommand ); |
|
} |
|
else |
|
{ |
|
CMatchmakingBasePanel *pMatchMaker = GetMatchmakingBasePanel(); |
|
if ( pMatchMaker ) |
|
{ |
|
pMatchMaker->OnCommand( m_strPostPromptCommand ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: message handler for menu selections |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnCommand( const char *command ) |
|
{ |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
#if defined( _X360 ) |
|
|
|
// See if this is a command we need to intercept |
|
if ( IsPromptableCommand( command ) ) |
|
{ |
|
// Handle the sign in case |
|
if ( HandleSignInRequest( command ) == false ) |
|
return; |
|
|
|
// Handle storage |
|
if ( HandleStorageDeviceRequest( command ) == false ) |
|
return; |
|
|
|
// If we fall through, we'll need to track this again |
|
m_bStorageBladeShown = false; |
|
|
|
// Fall through |
|
} |
|
#endif // _X360 |
|
|
|
RunAnimationWithCallback( this, command, new KeyValues( "RunMenuCommand", "command", command ) ); |
|
|
|
// Clear our pending command if we just executed it |
|
ClearPostPromptCommand( command ); |
|
} |
|
else |
|
{ |
|
RunMenuCommand( command ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: runs an animation sequence, then calls a message mapped function |
|
// when the animation is complete. |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::RunAnimationWithCallback( vgui::Panel *parent, const char *animName, KeyValues *msgFunc ) |
|
{ |
|
if ( !m_pConsoleAnimationController ) |
|
return; |
|
|
|
m_pConsoleAnimationController->StartAnimationSequence( animName ); |
|
float sequenceLength = m_pConsoleAnimationController->GetAnimationSequenceLength( animName ); |
|
if ( sequenceLength ) |
|
{ |
|
sequenceLength += g_flAnimationPadding; |
|
} |
|
if ( parent && msgFunc ) |
|
{ |
|
PostMessage( parent, msgFunc, sequenceLength ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: trinary choice query "save & quit", "quit", "cancel" |
|
//----------------------------------------------------------------------------- |
|
class CSaveBeforeQuitQueryDialog : public vgui::Frame |
|
{ |
|
DECLARE_CLASS_SIMPLE( CSaveBeforeQuitQueryDialog, vgui::Frame ); |
|
public: |
|
CSaveBeforeQuitQueryDialog(vgui::Panel *parent, const char *name) : BaseClass(parent, name) |
|
{ |
|
LoadControlSettings("resource/SaveBeforeQuitDialog.res"); |
|
SetDeleteSelfOnClose(true); |
|
SetSizeable(false); |
|
} |
|
|
|
void DoModal() |
|
{ |
|
BaseClass::Activate(); |
|
input()->SetAppModalSurface(GetVPanel()); |
|
MoveToCenterOfScreen(); |
|
vgui::surface()->RestrictPaintToSinglePanel(GetVPanel()); |
|
|
|
GameUI().PreventEngineHideGameUI(); |
|
} |
|
|
|
void OnKeyCodeTyped(KeyCode code) |
|
{ |
|
// ESC cancels |
|
if ( code == KEY_ESCAPE ) |
|
{ |
|
Close(); |
|
} |
|
else |
|
{ |
|
BaseClass::OnKeyCodeTyped(code); |
|
} |
|
} |
|
|
|
void OnKeyCodePressed(KeyCode code) |
|
{ |
|
// ESC cancels |
|
if ( code == KEY_XBUTTON_B || code == STEAMCONTROLLER_B || code == STEAMCONTROLLER_START ) |
|
{ |
|
Close(); |
|
} |
|
else if ( code == KEY_XBUTTON_A || code == STEAMCONTROLLER_A ) |
|
{ |
|
OnCommand( "SaveAndQuit" ); |
|
} |
|
else if ( code == KEY_XBUTTON_X || code == STEAMCONTROLLER_X ) |
|
{ |
|
OnCommand( "Quit" ); |
|
} |
|
else |
|
{ |
|
BaseClass::OnKeyCodePressed(code); |
|
} |
|
} |
|
|
|
virtual void OnCommand(const char *command) |
|
{ |
|
if (!Q_stricmp(command, "Quit")) |
|
{ |
|
PostMessage(GetVParent(), new KeyValues("Command", "command", "QuitNoConfirm")); |
|
} |
|
else if (!Q_stricmp(command, "SaveAndQuit")) |
|
{ |
|
// find a new name to save |
|
char saveName[128]; |
|
CSaveGameDialog::FindSaveSlot( saveName, sizeof(saveName) ); |
|
if ( saveName[ 0 ] ) |
|
{ |
|
// save the game |
|
char sz[ 256 ]; |
|
Q_snprintf(sz, sizeof( sz ), "save %s\n", saveName ); |
|
engine->ClientCmd_Unrestricted( sz ); |
|
} |
|
|
|
// quit |
|
PostMessage(GetVParent(), new KeyValues("Command", "command", "QuitNoConfirm")); |
|
} |
|
else if (!Q_stricmp(command, "Cancel")) |
|
{ |
|
Close(); |
|
} |
|
else |
|
{ |
|
BaseClass::OnCommand(command); |
|
} |
|
} |
|
|
|
virtual void OnClose() |
|
{ |
|
BaseClass::OnClose(); |
|
vgui::surface()->RestrictPaintToSinglePanel(NULL); |
|
GameUI().AllowEngineHideGameUI(); |
|
} |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: simple querybox that accepts escape |
|
//----------------------------------------------------------------------------- |
|
class CQuitQueryBox : public vgui::QueryBox |
|
{ |
|
DECLARE_CLASS_SIMPLE( CQuitQueryBox, vgui::QueryBox ); |
|
public: |
|
CQuitQueryBox(const char *title, const char *info, Panel *parent) : BaseClass( title, info, parent ) |
|
{ |
|
} |
|
|
|
void DoModal( Frame* pFrameOver ) |
|
{ |
|
BaseClass::DoModal( pFrameOver ); |
|
vgui::surface()->RestrictPaintToSinglePanel(GetVPanel()); |
|
GameUI().PreventEngineHideGameUI(); |
|
} |
|
|
|
void OnKeyCodeTyped(KeyCode code) |
|
{ |
|
// ESC cancels |
|
if (code == KEY_ESCAPE) |
|
{ |
|
Close(); |
|
} |
|
else |
|
{ |
|
BaseClass::OnKeyCodeTyped(code); |
|
} |
|
} |
|
|
|
void OnKeyCodePressed(KeyCode code) |
|
{ |
|
// ESC cancels |
|
if (code == KEY_XBUTTON_B || code == STEAMCONTROLLER_B) |
|
{ |
|
Close(); |
|
} |
|
else |
|
{ |
|
BaseClass::OnKeyCodePressed(code); |
|
} |
|
} |
|
|
|
virtual void OnClose() |
|
{ |
|
BaseClass::OnClose(); |
|
vgui::surface()->RestrictPaintToSinglePanel(NULL); |
|
GameUI().AllowEngineHideGameUI(); |
|
} |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: asks user how they feel about quiting |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenQuitConfirmationDialog() |
|
{ |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
if ( !GameUI().HasSavedThisMenuSession() && GameUI().IsInLevel() && engine->GetMaxClients() == 1 ) |
|
{ |
|
// single player, progress will be lost... |
|
ShowMessageDialog( MD_SAVE_BEFORE_QUIT ); |
|
} |
|
else |
|
{ |
|
if ( m_bUseMatchmaking ) |
|
{ |
|
ShowMessageDialog( MD_QUIT_CONFIRMATION_TF ); |
|
} |
|
else |
|
{ |
|
ShowMessageDialog( MD_QUIT_CONFIRMATION ); |
|
} |
|
} |
|
return; |
|
} |
|
|
|
|
|
if ( GameUI().IsInLevel() && engine->GetMaxClients() == 1 ) |
|
{ |
|
// prompt for saving current game before quiting |
|
CSaveBeforeQuitQueryDialog *box = new CSaveBeforeQuitQueryDialog(this, "SaveBeforeQuitQueryDialog"); |
|
box->DoModal(); |
|
} |
|
else |
|
{ |
|
// simple ok/cancel prompt |
|
QueryBox *box = new CQuitQueryBox("#GameUI_QuitConfirmationTitle", "#GameUI_QuitConfirmationText", this); |
|
box->SetOKButtonText("#GameUI_Quit"); |
|
box->SetOKCommand(new KeyValues("Command", "command", "QuitNoConfirm")); |
|
box->SetCancelCommand(new KeyValues("Command", "command", "ReleaseModalWindow")); |
|
box->AddActionSignalTarget(this); |
|
box->DoModal(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: asks user how they feel about disconnecting |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenDisconnectConfirmationDialog() |
|
{ |
|
// THis is for disconnecting from a multiplayer server |
|
Assert( m_bUseMatchmaking ); |
|
Assert( IsX360() ); |
|
|
|
if ( GameUI().IsConsoleUI() && GameUI().IsInLevel() ) |
|
{ |
|
if ( engine->GetLocalPlayer() == 1 ) |
|
{ |
|
ShowMessageDialog( MD_DISCONNECT_CONFIRMATION_HOST ); |
|
} |
|
else |
|
{ |
|
ShowMessageDialog( MD_DISCONNECT_CONFIRMATION ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenNewGameDialog(const char *chapter ) |
|
{ |
|
if ( !m_hNewGameDialog.Get() ) |
|
{ |
|
m_hNewGameDialog = new CNewGameDialog(this, false); |
|
PositionDialog( m_hNewGameDialog ); |
|
} |
|
|
|
if ( chapter ) |
|
{ |
|
((CNewGameDialog *)m_hNewGameDialog.Get())->SetSelectedChapter(chapter); |
|
} |
|
|
|
((CNewGameDialog *)m_hNewGameDialog.Get())->SetCommentaryMode( false ); |
|
m_hNewGameDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenBonusMapsDialog( void ) |
|
{ |
|
if ( !m_hBonusMapsDialog.Get() ) |
|
{ |
|
m_hBonusMapsDialog = new CBonusMapsDialog(this); |
|
PositionDialog( m_hBonusMapsDialog ); |
|
} |
|
|
|
m_hBonusMapsDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenLoadGameDialog() |
|
{ |
|
if ( !m_hLoadGameDialog.Get() ) |
|
{ |
|
m_hLoadGameDialog = new CLoadGameDialog(this); |
|
PositionDialog( m_hLoadGameDialog ); |
|
} |
|
m_hLoadGameDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenLoadGameDialog_Xbox() |
|
{ |
|
if ( !m_hLoadGameDialog_Xbox.Get() ) |
|
{ |
|
m_hLoadGameDialog_Xbox = new CLoadGameDialogXbox(this); |
|
PositionDialog( m_hLoadGameDialog_Xbox ); |
|
} |
|
m_hLoadGameDialog_Xbox->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenSaveGameDialog() |
|
{ |
|
if ( !m_hSaveGameDialog.Get() ) |
|
{ |
|
m_hSaveGameDialog = new CSaveGameDialog(this); |
|
PositionDialog( m_hSaveGameDialog ); |
|
} |
|
m_hSaveGameDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenSaveGameDialog_Xbox() |
|
{ |
|
if ( !m_hSaveGameDialog_Xbox.Get() ) |
|
{ |
|
m_hSaveGameDialog_Xbox = new CSaveGameDialogXbox(this); |
|
PositionDialog( m_hSaveGameDialog_Xbox ); |
|
} |
|
m_hSaveGameDialog_Xbox->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenOptionsDialog() |
|
{ |
|
if ( !m_hOptionsDialog.Get() ) |
|
{ |
|
m_hOptionsDialog = new COptionsDialog(this); |
|
g_hOptionsDialog = m_hOptionsDialog; |
|
PositionDialog( m_hOptionsDialog ); |
|
} |
|
|
|
m_hOptionsDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenOptionsDialog_Xbox() |
|
{ |
|
if ( !m_hOptionsDialog_Xbox.Get() ) |
|
{ |
|
m_hOptionsDialog_Xbox = new COptionsDialogXbox( this ); |
|
PositionDialog( m_hOptionsDialog_Xbox ); |
|
} |
|
|
|
m_hOptionsDialog_Xbox->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: forces any changed options dialog settings to be applied immediately, if it's open |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::ApplyOptionsDialogSettings() |
|
{ |
|
if (m_hOptionsDialog.Get()) |
|
{ |
|
m_hOptionsDialog->ApplyChanges(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenControllerDialog() |
|
{ |
|
if ( !m_hControllerDialog.Get() ) |
|
{ |
|
m_hControllerDialog = new CControllerDialog( this ); |
|
PositionDialog( m_hControllerDialog ); |
|
} |
|
|
|
m_hControllerDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenBenchmarkDialog() |
|
{ |
|
if (!m_hBenchmarkDialog.Get()) |
|
{ |
|
m_hBenchmarkDialog = new CBenchmarkDialog(this, "BenchmarkDialog"); |
|
PositionDialog( m_hBenchmarkDialog ); |
|
} |
|
m_hBenchmarkDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenServerBrowser() |
|
{ |
|
g_VModuleLoader.ActivateModule("Servers"); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenFriendsDialog() |
|
{ |
|
g_VModuleLoader.ActivateModule("Friends"); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenDemoDialog() |
|
{ |
|
/* if ( !m_hDemoPlayerDialog.Get() ) |
|
{ |
|
m_hDemoPlayerDialog = new CDemoPlayerDialog(this); |
|
PositionDialog( m_hDemoPlayerDialog ); |
|
} |
|
m_hDemoPlayerDialog->Activate();*/ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenCreateMultiplayerGameDialog() |
|
{ |
|
if (!m_hCreateMultiplayerGameDialog.Get()) |
|
{ |
|
m_hCreateMultiplayerGameDialog = new CCreateMultiplayerGameDialog(this); |
|
PositionDialog(m_hCreateMultiplayerGameDialog); |
|
} |
|
m_hCreateMultiplayerGameDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenChangeGameDialog() |
|
{ |
|
#ifdef POSIX |
|
// Alfred says this is old legacy code that allowed you to walk through looking for |
|
// gameinfos and switch and it's not needed anymore. So I'm killing this assert... |
|
#else |
|
if (!m_hChangeGameDialog.Get()) |
|
{ |
|
m_hChangeGameDialog = new CChangeGameDialog(this); |
|
PositionDialog(m_hChangeGameDialog); |
|
} |
|
m_hChangeGameDialog->Activate(); |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenPlayerListDialog() |
|
{ |
|
if (!m_hPlayerListDialog.Get()) |
|
{ |
|
m_hPlayerListDialog = new CPlayerListDialog(this); |
|
PositionDialog(m_hPlayerListDialog); |
|
} |
|
m_hPlayerListDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenLoadCommentaryDialog() |
|
{ |
|
if (!m_hPlayerListDialog.Get()) |
|
{ |
|
m_hLoadCommentaryDialog = new CLoadCommentaryDialog(this); |
|
PositionDialog(m_hLoadCommentaryDialog); |
|
} |
|
m_hLoadCommentaryDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OpenLoadSingleplayerCommentaryDialog() |
|
{ |
|
if ( !m_hNewGameDialog.Get() ) |
|
{ |
|
m_hNewGameDialog = new CNewGameDialog(this,true); |
|
PositionDialog( m_hNewGameDialog ); |
|
} |
|
|
|
((CNewGameDialog *)m_hNewGameDialog.Get())->SetCommentaryMode( true ); |
|
m_hNewGameDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenAchievementsDialog() |
|
{ |
|
if (!m_hAchievementsDialog.Get()) |
|
{ |
|
m_hAchievementsDialog = new CAchievementsDialog( this ); |
|
PositionDialog(m_hAchievementsDialog); |
|
} |
|
m_hAchievementsDialog->Activate(); |
|
} |
|
|
|
//============================================================================= |
|
// HPE_BEGIN: |
|
// [dwenger] Use cs-specific achievements dialog |
|
//============================================================================= |
|
|
|
void CBasePanel::OnOpenCSAchievementsDialog() |
|
{ |
|
if ( GameClientExports() ) |
|
{ |
|
int screenWide = 0; |
|
int screenHeight = 0; |
|
engine->GetScreenSize( screenWide, screenHeight ); |
|
|
|
// [smessick] For lower resolutions, open the Steam achievements instead of the CSS achievements screen. |
|
if ( screenWide < GameClientExports()->GetAchievementsPanelMinWidth() ) |
|
{ |
|
ISteamFriends *friends = steamapicontext->SteamFriends(); |
|
if ( friends ) |
|
{ |
|
friends->ActivateGameOverlay( "Achievements" ); |
|
} |
|
} |
|
else |
|
{ |
|
// Display the CSS achievements screen. |
|
GameClientExports()->CreateAchievementsPanel( this ); |
|
GameClientExports()->DisplayAchievementPanel(); |
|
} |
|
} |
|
} |
|
|
|
//============================================================================= |
|
// HPE_END |
|
//============================================================================= |
|
|
|
void CBasePanel::OnOpenAchievementsDialog_Xbox() |
|
{ |
|
if (!m_hAchievementsDialog.Get()) |
|
{ |
|
m_hAchievementsDialog = new CAchievementsDialog_XBox( this ); |
|
PositionDialog(m_hAchievementsDialog); |
|
} |
|
m_hAchievementsDialog->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnOpenMatchmakingBasePanel() |
|
{ |
|
if (!m_hMatchmakingBasePanel.Get()) |
|
{ |
|
m_hMatchmakingBasePanel = new CMatchmakingBasePanel( this ); |
|
int x, y, wide, tall; |
|
GetBounds( x, y, wide, tall ); |
|
m_hMatchmakingBasePanel->SetBounds( x, y, wide, tall ); |
|
} |
|
|
|
if ( m_pGameLogo ) |
|
{ |
|
m_pGameLogo->SetVisible( false ); |
|
} |
|
|
|
// Hide the standard game menu |
|
for ( int i = 0; i < m_pGameMenuButtons.Count(); ++i ) |
|
{ |
|
m_pGameMenuButtons[i]->SetVisible( false ); |
|
} |
|
|
|
// Hide the BasePanel's button footer |
|
m_pGameMenu->ShowFooter( false ); |
|
|
|
m_hMatchmakingBasePanel->SetVisible( true ); |
|
|
|
m_hMatchmakingBasePanel->Activate(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Helper function for this common operation |
|
//----------------------------------------------------------------------------- |
|
CMatchmakingBasePanel *CBasePanel::GetMatchmakingBasePanel() |
|
{ |
|
CMatchmakingBasePanel *pBase = NULL; |
|
if ( m_bUseMatchmaking ) |
|
{ |
|
pBase = dynamic_cast< CMatchmakingBasePanel* >( m_hMatchmakingBasePanel.Get() ); |
|
} |
|
return pBase; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: moves the game menu button to the right place on the taskbar |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::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)); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add an Xbox 360 message dialog to a dialog stack |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::ShowMessageDialog( const uint nType, vgui::Panel *pOwner ) |
|
{ |
|
if ( pOwner == NULL ) |
|
{ |
|
pOwner = this; |
|
} |
|
|
|
m_MessageDialogHandler.ShowMessageDialog( nType, pOwner ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add an Xbox 360 message dialog to a dialog stack |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::CloseMessageDialog( const uint nType ) |
|
{ |
|
m_MessageDialogHandler.CloseMessageDialog( nType ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Matchmaking notification from engine |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::SessionNotification( const int notification, const int param ) |
|
{ |
|
// This is a job for the matchmaking panel |
|
CMatchmakingBasePanel *pBase = GetMatchmakingBasePanel(); |
|
if ( pBase ) |
|
{ |
|
pBase->SessionNotification( notification, param ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: System notification from engine |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::SystemNotification( const int notification ) |
|
{ |
|
CMatchmakingBasePanel *pBase = GetMatchmakingBasePanel(); |
|
if ( pBase ) |
|
{ |
|
pBase->SystemNotification( notification ); |
|
} |
|
|
|
if ( notification == SYSTEMNOTIFY_USER_SIGNEDIN ) |
|
{ |
|
#if defined( _X360 ) |
|
// See if it was the active user who signed in |
|
uint state = XUserGetSigninState( XBX_GetPrimaryUserId() ); |
|
if ( state != eXUserSigninState_NotSignedIn ) |
|
{ |
|
// Reset a bunch of state |
|
m_bUserRefusedSignIn = false; |
|
m_bUserRefusedStorageDevice = false; |
|
m_bStorageBladeShown = false; |
|
} |
|
UpdateRichPresenceInfo(); |
|
engine->GetAchievementMgr()->DownloadUserData(); |
|
engine->GetAchievementMgr()->EnsureGlobalStateLoaded(); |
|
#endif |
|
} |
|
else if ( notification == SYSTEMNOTIFY_USER_SIGNEDOUT ) |
|
{ |
|
#if defined( _X360 ) |
|
// See if it was the active user who signed out |
|
uint state = XUserGetSigninState( XBX_GetPrimaryUserId() ); |
|
if ( state != eXUserSigninState_NotSignedIn ) |
|
{ |
|
return; |
|
} |
|
|
|
// Invalidate their storage ID |
|
engine->OnStorageDeviceDetached(); |
|
m_bUserRefusedStorageDevice = false; |
|
m_bUserRefusedSignIn = false; |
|
m_iStorageID = XBX_INVALID_STORAGE_ID; |
|
engine->GetAchievementMgr()->InitializeAchievements(); |
|
m_MessageDialogHandler.CloseAllMessageDialogs(); |
|
|
|
#endif |
|
if ( GameUI().IsInLevel() ) |
|
{ |
|
if ( m_pGameLogo ) |
|
{ |
|
m_pGameLogo->SetVisible( false ); |
|
} |
|
|
|
// Hide the standard game menu |
|
for ( int i = 0; i < m_pGameMenuButtons.Count(); ++i ) |
|
{ |
|
m_pGameMenuButtons[i]->SetVisible( false ); |
|
} |
|
|
|
// Hide the BasePanel's button footer |
|
m_pGameMenu->ShowFooter( false ); |
|
|
|
QueueCommand( "QuitNoConfirm" ); |
|
} |
|
else |
|
{ |
|
CloseBaseDialogs(); |
|
} |
|
|
|
OnCommand( "OpenMainMenu" ); |
|
} |
|
else if ( notification == SYSTEMNOTIFY_STORAGEDEVICES_CHANGED ) |
|
{ |
|
if ( m_hSaveGameDialog_Xbox.Get() ) |
|
m_hSaveGameDialog_Xbox->OnCommand( "RefreshSaveGames" ); |
|
if ( m_hLoadGameDialog_Xbox.Get() ) |
|
m_hLoadGameDialog_Xbox->OnCommand( "RefreshSaveGames" ); |
|
|
|
// FIXME: This code is incorrect, they do NOT need a storage device, it is only recommended that they do |
|
if ( GameUI().IsInLevel() ) |
|
{ |
|
// They wanted to use a storage device and are already playing! |
|
// They need a storage device now or we're quitting the game! |
|
m_bNeedStorageDeviceHandle = true; |
|
ShowMessageDialog( MD_STORAGE_DEVICES_NEEDED, this ); |
|
} |
|
else |
|
{ |
|
ShowMessageDialog( MD_STORAGE_DEVICES_CHANGED, this ); |
|
} |
|
} |
|
else if ( notification == SYSTEMNOTIFY_XUIOPENING ) |
|
{ |
|
m_bXUIVisible = true; |
|
} |
|
else if ( notification == SYSTEMNOTIFY_XUICLOSED ) |
|
{ |
|
m_bXUIVisible = false; |
|
|
|
if ( m_bWaitingForStorageDeviceHandle ) |
|
{ |
|
DWORD ret = xboxsystem->GetOverlappedResult( m_hStorageDeviceChangeHandle, NULL, true ); |
|
if ( ret != ERROR_IO_INCOMPLETE ) |
|
{ |
|
// Done waiting |
|
xboxsystem->ReleaseAsyncHandle( m_hStorageDeviceChangeHandle ); |
|
|
|
m_bWaitingForStorageDeviceHandle = false; |
|
|
|
// If we selected something, validate it |
|
if ( m_iStorageID != XBX_INVALID_STORAGE_ID ) |
|
{ |
|
// Check to see if there is enough room on this storage device |
|
if ( xboxsystem->DeviceCapacityAdequate( m_iStorageID, COM_GetModDirectory() ) == false ) |
|
{ |
|
ShowMessageDialog( MD_STORAGE_DEVICES_TOO_FULL, this ); |
|
m_bStorageBladeShown = false; // Show the blade again next time |
|
m_strPostPromptCommand = ""; // Clear the buffer, we can't return |
|
} |
|
else |
|
{ |
|
m_bNeedStorageDeviceHandle = false; |
|
|
|
// Set the storage device |
|
XBX_SetStorageDeviceId( m_iStorageID ); |
|
OnDeviceAttached(); |
|
} |
|
} |
|
else |
|
{ |
|
if ( m_pStorageDeviceValidatedNotify ) |
|
{ |
|
*m_pStorageDeviceValidatedNotify = 2; |
|
m_pStorageDeviceValidatedNotify = NULL; |
|
} |
|
else if ( m_bNeedStorageDeviceHandle ) |
|
{ |
|
// They didn't select a storage device! |
|
// Remind them that they must pick one or the game will shut down |
|
ShowMessageDialog( MD_STORAGE_DEVICES_NEEDED, this ); |
|
} |
|
else |
|
{ |
|
// Start off the command we queued up |
|
IssuePostPromptCommand(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
// If we're waiting for the user to sign in, and check if they selected a usable profile |
|
if ( m_bWaitingForUserSignIn ) |
|
{ |
|
// Done waiting |
|
m_bWaitingForUserSignIn = false; |
|
m_bUserRefusedSignIn = false; |
|
|
|
// The UI has closed, so go off and revalidate the state |
|
if ( m_strPostPromptCommand.IsEmpty() == false ) |
|
{ |
|
// Run the command again |
|
OnCommand( m_strPostPromptCommand ); |
|
} |
|
} |
|
|
|
RunQueuedCommands(); |
|
} |
|
else if ( notification == SYSTEMNOTIFY_INVITE_SHUTDOWN ) |
|
{ |
|
// Quit the current game without confirmation |
|
m_bRestartFromInvite = true; |
|
m_bXUIVisible = true; |
|
OnCommand( "QuitNoConfirm" ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Matchmaking notification that a player's info has changed |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::UpdatePlayerInfo( uint64 nPlayerId, const char *pName, int nTeam, byte cVoiceState, int nPlayersNeeded, bool bHost ) |
|
{ |
|
CMatchmakingBasePanel *pBase = GetMatchmakingBasePanel(); |
|
if ( pBase ) |
|
{ |
|
pBase->UpdatePlayerInfo( nPlayerId, pName, nTeam, cVoiceState, nPlayersNeeded, bHost ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Matchmaking notification to add a session to the browser |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::SessionSearchResult( int searchIdx, void *pHostData, XSESSION_SEARCHRESULT *pResult, int ping ) |
|
{ |
|
CMatchmakingBasePanel *pBase = GetMatchmakingBasePanel(); |
|
if ( pBase ) |
|
{ |
|
pBase->SessionSearchResult( searchIdx, pHostData, pResult, ping ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnChangeStorageDevice( void ) |
|
{ |
|
if ( m_bWaitingForStorageDeviceHandle == false ) |
|
{ |
|
m_bWaitingForStorageDeviceHandle = true; |
|
m_hStorageDeviceChangeHandle = xboxsystem->CreateAsyncHandle(); |
|
m_iStorageID = XBX_INVALID_STORAGE_ID; |
|
xboxsystem->ShowDeviceSelector( true, &m_iStorageID, &m_hStorageDeviceChangeHandle ); |
|
} |
|
} |
|
|
|
void CBasePanel::OnCreditsFinished( void ) |
|
{ |
|
if ( !IsX360() ) |
|
{ |
|
// valid for 360 only |
|
Assert( 0 ); |
|
return; |
|
} |
|
|
|
bool bExitToAppChooser = false; |
|
if ( bExitToAppChooser ) |
|
{ |
|
// unknown state from engine, force to a compliant exiting state |
|
// causes an complete exit out of the game back to the app launcher |
|
SetVisible( true ); |
|
m_pGameMenu->SetAlpha( 0 ); |
|
StartExitingProcess(); |
|
} |
|
else |
|
{ |
|
// expecting to transition from the credits back to the background map |
|
// prevent any possibility of using the last transition image |
|
m_bUseRenderTargetImage = false; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::OnGameUIHidden() |
|
{ |
|
if ( m_hOptionsDialog.Get() ) |
|
{ |
|
PostMessage( m_hOptionsDialog.Get(), new KeyValues( "GameUIHidden" ) ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Sets the alpha of the menu panels |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::SetMenuAlpha(int alpha) |
|
{ |
|
if ( GameUI().IsConsoleUI() ) |
|
{ |
|
// handled by animation, not code |
|
return; |
|
} |
|
|
|
m_pGameMenu->SetAlpha(alpha); |
|
|
|
if ( m_pGameLogo ) |
|
{ |
|
m_pGameLogo->SetAlpha( alpha ); |
|
} |
|
|
|
for ( int i=0; i<m_pGameMenuButtons.Count(); ++i ) |
|
{ |
|
m_pGameMenuButtons[i]->SetAlpha(alpha); |
|
} |
|
m_bForceTitleTextUpdate = true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CBasePanel::GetMenuAlpha( void ) |
|
{ |
|
return m_pGameMenu->GetAlpha(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::SetMainMenuOverride( vgui::VPANEL panel ) |
|
{ |
|
m_hMainMenuOverridePanel = panel; |
|
|
|
if ( m_pGameMenu ) |
|
{ |
|
m_pGameMenu->SetMainMenuOverride( panel ); |
|
} |
|
|
|
if ( m_hMainMenuOverridePanel ) |
|
{ |
|
// Parent it to this panel |
|
ipanel()->SetParent( m_hMainMenuOverridePanel, GetVPanel() ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: starts the game |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::FadeToBlackAndRunEngineCommand( const char *engineCommand ) |
|
{ |
|
KeyValues *pKV = new KeyValues( "RunEngineCommand", "command", engineCommand ); |
|
|
|
// execute immediately, with no delay |
|
PostMessage( this, pKV, 0 ); |
|
} |
|
|
|
void CBasePanel::SetMenuItemBlinkingState( const char *itemName, bool state ) |
|
{ |
|
for (int i = 0; i < GetChildCount(); i++) |
|
{ |
|
Panel *child = GetChild(i); |
|
CGameMenu *pGameMenu = dynamic_cast<CGameMenu *>(child); |
|
if ( pGameMenu ) |
|
{ |
|
pGameMenu->SetMenuItemBlinkingState( itemName, state ); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: runs an engine command, used for delays |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::RunEngineCommand(const char *command) |
|
{ |
|
engine->ClientCmd_Unrestricted(command); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: runs an animation to close a dialog and cleans up after close |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::RunCloseAnimation( const char *animName ) |
|
{ |
|
RunAnimationWithCallback( this, animName, new KeyValues( "FinishDialogClose" ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: cleans up after a menu closes |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::FinishDialogClose( void ) |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: xbox UI panel that displays button icons and help text for all menus |
|
//----------------------------------------------------------------------------- |
|
CFooterPanel::CFooterPanel( Panel *parent, const char *panelName ) : BaseClass( parent, panelName ) |
|
{ |
|
SetVisible( true ); |
|
SetAlpha( 0 ); |
|
m_pHelpName = NULL; |
|
|
|
m_pSizingLabel = new vgui::Label( this, "SizingLabel", "" ); |
|
m_pSizingLabel->SetVisible( false ); |
|
|
|
m_nButtonGap = 32; |
|
m_nButtonGapDefault = 32; |
|
m_ButtonPinRight = 100; |
|
m_FooterTall = 80; |
|
|
|
int wide, tall; |
|
surface()->GetScreenSize(wide, tall); |
|
|
|
if ( tall <= 480 ) |
|
{ |
|
m_FooterTall = 60; |
|
} |
|
|
|
m_ButtonOffsetFromTop = 0; |
|
m_ButtonSeparator = 4; |
|
m_TextAdjust = 0; |
|
|
|
m_bPaintBackground = false; |
|
m_bCenterHorizontal = false; |
|
|
|
m_szButtonFont[0] = '\0'; |
|
m_szTextFont[0] = '\0'; |
|
m_szFGColor[0] = '\0'; |
|
m_szBGColor[0] = '\0'; |
|
} |
|
|
|
CFooterPanel::~CFooterPanel() |
|
{ |
|
SetHelpNameAndReset( NULL ); |
|
|
|
delete m_pSizingLabel; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: apply scheme settings |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
m_hButtonFont = pScheme->GetFont( ( m_szButtonFont[0] != '\0' ) ? m_szButtonFont : "GameUIButtons" ); |
|
m_hTextFont = pScheme->GetFont( ( m_szTextFont[0] != '\0' ) ? m_szTextFont : "MenuLarge" ); |
|
|
|
SetFgColor( pScheme->GetColor( m_szFGColor, Color( 255, 255, 255, 255 ) ) ); |
|
SetBgColor( pScheme->GetColor( m_szBGColor, Color( 0, 0, 0, 255 ) ) ); |
|
|
|
int x, y, w, h; |
|
GetParent()->GetBounds( x, y, w, h ); |
|
SetBounds( x, h - m_FooterTall, w, m_FooterTall ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: apply settings |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::ApplySettings( KeyValues *inResourceData ) |
|
{ |
|
BaseClass::ApplySettings( inResourceData ); |
|
|
|
// gap between hints |
|
m_nButtonGap = inResourceData->GetInt( "buttongap", 32 ); |
|
m_nButtonGapDefault = m_nButtonGap; |
|
m_ButtonPinRight = inResourceData->GetInt( "button_pin_right", 100 ); |
|
m_FooterTall = inResourceData->GetInt( "tall", 80 ); |
|
m_ButtonOffsetFromTop = inResourceData->GetInt( "buttonoffsety", 0 ); |
|
m_ButtonSeparator = inResourceData->GetInt( "button_separator", 4 ); |
|
m_TextAdjust = inResourceData->GetInt( "textadjust", 0 ); |
|
|
|
m_bCenterHorizontal = ( inResourceData->GetInt( "center", 0 ) == 1 ); |
|
m_bPaintBackground = ( inResourceData->GetInt( "paintbackground", 0 ) == 1 ); |
|
|
|
// fonts for text and button |
|
Q_strncpy( m_szTextFont, inResourceData->GetString( "fonttext", "MenuLarge" ), sizeof( m_szTextFont ) ); |
|
Q_strncpy( m_szButtonFont, inResourceData->GetString( "fontbutton", "GameUIButtons" ), sizeof( m_szButtonFont ) ); |
|
|
|
// fg and bg colors |
|
Q_strncpy( m_szFGColor, inResourceData->GetString( "fgcolor", "White" ), sizeof( m_szFGColor ) ); |
|
Q_strncpy( m_szBGColor, inResourceData->GetString( "bgcolor", "Black" ), sizeof( m_szBGColor ) ); |
|
|
|
for ( KeyValues *pButton = inResourceData->GetFirstSubKey(); pButton != NULL; pButton = pButton->GetNextKey() ) |
|
{ |
|
const char *pName = pButton->GetName(); |
|
|
|
if ( !Q_stricmp( pName, "button" ) ) |
|
{ |
|
// Add a button to the footer |
|
const char *pText = pButton->GetString( "text", "NULL" ); |
|
const char *pIcon = pButton->GetString( "icon", "NULL" ); |
|
AddNewButtonLabel( pText, pIcon ); |
|
} |
|
} |
|
|
|
InvalidateLayout( false, true ); // force ApplySchemeSettings to run |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: adds button icons and help text to the footer panel when activating a menu |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::AddButtonsFromMap( vgui::Frame *pMenu ) |
|
{ |
|
SetHelpNameAndReset( pMenu->GetName() ); |
|
|
|
CControllerMap *pMap = dynamic_cast<CControllerMap*>( pMenu->FindChildByName( "ControllerMap" ) ); |
|
if ( pMap ) |
|
{ |
|
int buttonCt = pMap->NumButtons(); |
|
for ( int i = 0; i < buttonCt; ++i ) |
|
{ |
|
const char *pText = pMap->GetBindingText( i ); |
|
if ( pText ) |
|
{ |
|
AddNewButtonLabel( pText, pMap->GetBindingIcon( i ) ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CFooterPanel::SetStandardDialogButtons() |
|
{ |
|
SetHelpNameAndReset( "Dialog" ); |
|
AddNewButtonLabel( "#GameUI_Action", "#GameUI_Icons_A_BUTTON" ); |
|
AddNewButtonLabel( "#GameUI_Close", "#GameUI_Icons_B_BUTTON" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Caller must tag the button layout. May support reserved names |
|
// to provide stock help layouts trivially. |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::SetHelpNameAndReset( const char *pName ) |
|
{ |
|
if ( m_pHelpName ) |
|
{ |
|
free( m_pHelpName ); |
|
m_pHelpName = NULL; |
|
} |
|
|
|
if ( pName ) |
|
{ |
|
m_pHelpName = strdup( pName ); |
|
} |
|
|
|
ClearButtons(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Caller must tag the button layout |
|
//----------------------------------------------------------------------------- |
|
const char *CFooterPanel::GetHelpName() |
|
{ |
|
return m_pHelpName; |
|
} |
|
|
|
void CFooterPanel::ClearButtons( void ) |
|
{ |
|
m_ButtonLabels.PurgeAndDeleteElements(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: creates a new button label with icon and text |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::AddNewButtonLabel( const char *text, const char *icon ) |
|
{ |
|
ButtonLabel_t *button = new ButtonLabel_t; |
|
|
|
Q_strncpy( button->name, text, MAX_PATH ); |
|
button->bVisible = true; |
|
|
|
// Button icons are a single character |
|
wchar_t *pIcon = g_pVGuiLocalize->Find( icon ); |
|
if ( pIcon ) |
|
{ |
|
button->icon[0] = pIcon[0]; |
|
button->icon[1] = '\0'; |
|
} |
|
else |
|
{ |
|
button->icon[0] = '\0'; |
|
} |
|
|
|
// Set the help text |
|
wchar_t *pText = g_pVGuiLocalize->Find( text ); |
|
if ( pText ) |
|
{ |
|
wcsncpy( button->text, pText, wcslen( pText ) + 1 ); |
|
} |
|
else |
|
{ |
|
button->text[0] = '\0'; |
|
} |
|
|
|
m_ButtonLabels.AddToTail( button ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Shows/Hides a button label |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::ShowButtonLabel( const char *name, bool show ) |
|
{ |
|
for ( int i = 0; i < m_ButtonLabels.Count(); ++i ) |
|
{ |
|
if ( !Q_stricmp( m_ButtonLabels[ i ]->name, name ) ) |
|
{ |
|
m_ButtonLabels[ i ]->bVisible = show; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Changes a button's text |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::SetButtonText( const char *buttonName, const char *text ) |
|
{ |
|
for ( int i = 0; i < m_ButtonLabels.Count(); ++i ) |
|
{ |
|
if ( !Q_stricmp( m_ButtonLabels[ i ]->name, buttonName ) ) |
|
{ |
|
wchar_t *wtext = g_pVGuiLocalize->Find( text ); |
|
if ( text ) |
|
{ |
|
wcsncpy( m_ButtonLabels[ i ]->text, wtext, wcslen( wtext ) + 1 ); |
|
} |
|
else |
|
{ |
|
m_ButtonLabels[ i ]->text[ 0 ] = '\0'; |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Footer panel background rendering |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::PaintBackground( void ) |
|
{ |
|
if ( !m_bPaintBackground ) |
|
return; |
|
|
|
BaseClass::PaintBackground(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Footer panel rendering |
|
//----------------------------------------------------------------------------- |
|
void CFooterPanel::Paint( void ) |
|
{ |
|
// inset from right edge |
|
int wide = GetWide(); |
|
int right = wide - m_ButtonPinRight; |
|
|
|
// center the text within the button |
|
int buttonHeight = vgui::surface()->GetFontTall( m_hButtonFont ); |
|
int fontHeight = vgui::surface()->GetFontTall( m_hTextFont ); |
|
int textY = ( buttonHeight - fontHeight )/2 + m_TextAdjust; |
|
|
|
if ( textY < 0 ) |
|
{ |
|
textY = 0; |
|
} |
|
|
|
int y = m_ButtonOffsetFromTop; |
|
|
|
if ( !m_bCenterHorizontal ) |
|
{ |
|
// draw the buttons, right to left |
|
int x = right; |
|
|
|
for ( int i = 0; i < m_ButtonLabels.Count(); ++i ) |
|
{ |
|
ButtonLabel_t *pButton = m_ButtonLabels[i]; |
|
if ( !pButton->bVisible ) |
|
continue; |
|
|
|
// Get the string length |
|
m_pSizingLabel->SetFont( m_hTextFont ); |
|
m_pSizingLabel->SetText( pButton->text ); |
|
m_pSizingLabel->SizeToContents(); |
|
|
|
int iTextWidth = m_pSizingLabel->GetWide(); |
|
|
|
if ( iTextWidth == 0 ) |
|
x += m_nButtonGap; // There's no text, so remove the gap between buttons |
|
else |
|
x -= iTextWidth; |
|
|
|
// Draw the string |
|
vgui::surface()->DrawSetTextFont( m_hTextFont ); |
|
vgui::surface()->DrawSetTextColor( GetFgColor() ); |
|
vgui::surface()->DrawSetTextPos( x, y + textY ); |
|
vgui::surface()->DrawPrintText( pButton->text, wcslen( pButton->text ) ); |
|
|
|
// Draw the button |
|
// back up button width and a little extra to leave a gap between button and text |
|
x -= ( vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] ) + m_ButtonSeparator ); |
|
vgui::surface()->DrawSetTextFont( m_hButtonFont ); |
|
vgui::surface()->DrawSetTextColor( 255, 255, 255, 255 ); |
|
vgui::surface()->DrawSetTextPos( x, y ); |
|
vgui::surface()->DrawPrintText( pButton->icon, 1 ); |
|
|
|
// back up to next string |
|
x -= m_nButtonGap; |
|
} |
|
} |
|
else |
|
{ |
|
// center the buttons (as a group) |
|
int x = wide / 2; |
|
int totalWidth = 0; |
|
int i = 0; |
|
int nButtonCount = 0; |
|
|
|
// need to loop through and figure out how wide our buttons and text are (with gaps between) so we can offset from the center |
|
for ( i = 0; i < m_ButtonLabels.Count(); ++i ) |
|
{ |
|
ButtonLabel_t *pButton = m_ButtonLabels[i]; |
|
if ( !pButton->bVisible ) |
|
continue; |
|
|
|
// Get the string length |
|
m_pSizingLabel->SetFont( m_hTextFont ); |
|
m_pSizingLabel->SetText( pButton->text ); |
|
m_pSizingLabel->SizeToContents(); |
|
|
|
totalWidth += vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] ); |
|
totalWidth += m_ButtonSeparator; |
|
totalWidth += m_pSizingLabel->GetWide(); |
|
|
|
nButtonCount++; // keep track of how many active buttons we'll be drawing |
|
} |
|
|
|
totalWidth += ( nButtonCount - 1 ) * m_nButtonGap; // add in the gaps between the buttons |
|
x -= ( totalWidth / 2 ); |
|
|
|
for ( i = 0; i < m_ButtonLabels.Count(); ++i ) |
|
{ |
|
ButtonLabel_t *pButton = m_ButtonLabels[i]; |
|
if ( !pButton->bVisible ) |
|
continue; |
|
|
|
// Get the string length |
|
m_pSizingLabel->SetFont( m_hTextFont ); |
|
m_pSizingLabel->SetText( pButton->text ); |
|
m_pSizingLabel->SizeToContents(); |
|
|
|
int iTextWidth = m_pSizingLabel->GetWide(); |
|
|
|
// Draw the icon |
|
vgui::surface()->DrawSetTextFont( m_hButtonFont ); |
|
vgui::surface()->DrawSetTextColor( 255, 255, 255, 255 ); |
|
vgui::surface()->DrawSetTextPos( x, y ); |
|
vgui::surface()->DrawPrintText( pButton->icon, 1 ); |
|
x += vgui::surface()->GetCharacterWidth( m_hButtonFont, pButton->icon[0] ) + m_ButtonSeparator; |
|
|
|
// Draw the string |
|
vgui::surface()->DrawSetTextFont( m_hTextFont ); |
|
vgui::surface()->DrawSetTextColor( GetFgColor() ); |
|
vgui::surface()->DrawSetTextPos( x, y + textY ); |
|
vgui::surface()->DrawPrintText( pButton->text, wcslen( pButton->text ) ); |
|
|
|
x += iTextWidth + m_nButtonGap; |
|
} |
|
} |
|
} |
|
|
|
DECLARE_BUILD_FACTORY( CFooterPanel ); |
|
|
|
#ifdef _X360 |
|
//----------------------------------------------------------------------------- |
|
// Purpose: Reload the resource files on the Xbox 360 |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::Reload_Resources( const CCommand &args ) |
|
{ |
|
m_pConsoleControlSettings->Clear(); |
|
if ( m_pConsoleControlSettings->LoadFromFile( g_pFullFileSystem, "resource/UI/XboxDialogs.res" ) ) |
|
{ |
|
m_pConsoleControlSettings->ProcessResolutionKeys( surface()->GetResolutionKey() ); |
|
} |
|
} |
|
#endif |
|
|
|
|
|
// X360TBD: Move into a separate module when completed |
|
CMessageDialogHandler::CMessageDialogHandler() |
|
{ |
|
m_iDialogStackTop = -1; |
|
} |
|
void CMessageDialogHandler::ShowMessageDialog( int nType, vgui::Panel *pOwner ) |
|
{ |
|
int iSimpleFrame = 0; |
|
if ( ModInfo().IsSinglePlayerOnly() ) |
|
{ |
|
iSimpleFrame = MD_SIMPLEFRAME; |
|
} |
|
|
|
switch( nType ) |
|
{ |
|
case MD_SEARCHING_FOR_GAMES: |
|
CreateMessageDialog( MD_CANCEL|MD_RESTRICTPAINT, |
|
NULL, |
|
"#TF_Dlg_SearchingForGames", |
|
NULL, |
|
"CancelOperation", |
|
pOwner, |
|
true ); |
|
break; |
|
|
|
case MD_CREATING_GAME: |
|
CreateMessageDialog( MD_RESTRICTPAINT, |
|
NULL, |
|
"#TF_Dlg_CreatingGame", |
|
NULL, |
|
NULL, |
|
pOwner, |
|
true ); |
|
break; |
|
|
|
case MD_SESSION_SEARCH_FAILED: |
|
CreateMessageDialog( MD_YESNO|MD_RESTRICTPAINT, |
|
NULL, |
|
"#TF_Dlg_NoGamesFound", |
|
"ShowSessionOptionsDialog", |
|
"ReturnToMainMenu", |
|
pOwner ); |
|
break; |
|
|
|
case MD_SESSION_CREATE_FAILED: |
|
CreateMessageDialog( MD_OK, |
|
NULL, |
|
"#TF_Dlg_CreateFailed", |
|
"ReturnToMainMenu", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_SESSION_CONNECTING: |
|
CreateMessageDialog( 0, |
|
NULL, |
|
"#TF_Dlg_Connecting", |
|
NULL, |
|
NULL, |
|
pOwner, |
|
true ); |
|
break; |
|
|
|
case MD_SESSION_CONNECT_NOTAVAILABLE: |
|
CreateMessageDialog( MD_OK, |
|
NULL, |
|
"#TF_Dlg_JoinRefused", |
|
"ReturnToMainMenu", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_SESSION_CONNECT_SESSIONFULL: |
|
CreateMessageDialog( MD_OK, |
|
NULL, |
|
"#TF_Dlg_GameFull", |
|
"ReturnToMainMenu", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_SESSION_CONNECT_FAILED: |
|
CreateMessageDialog( MD_OK, |
|
NULL, |
|
"#TF_Dlg_JoinFailed", |
|
"ReturnToMainMenu", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_LOST_HOST: |
|
CreateMessageDialog( MD_OK|MD_RESTRICTPAINT, |
|
NULL, |
|
"#TF_Dlg_LostHost", |
|
"ReturnToMainMenu", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_LOST_SERVER: |
|
CreateMessageDialog( MD_OK|MD_RESTRICTPAINT, |
|
NULL, |
|
"#TF_Dlg_LostServer", |
|
"ReturnToMainMenu", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_MODIFYING_SESSION: |
|
CreateMessageDialog( MD_RESTRICTPAINT, |
|
NULL, |
|
"#TF_Dlg_ModifyingSession", |
|
NULL, |
|
NULL, |
|
pOwner, |
|
true ); |
|
break; |
|
|
|
case MD_SAVE_BEFORE_QUIT: |
|
CreateMessageDialog( MD_YESNO|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_QuitConfirmationTitle", |
|
"#GameUI_Console_QuitWarning", |
|
"QuitNoConfirm", |
|
"CloseQuitDialog_OpenMainMenu", |
|
pOwner ); |
|
break; |
|
|
|
case MD_QUIT_CONFIRMATION: |
|
CreateMessageDialog( MD_YESNO|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_QuitConfirmationTitle", |
|
"#GameUI_QuitConfirmationText", |
|
"QuitNoConfirm", |
|
"CloseQuitDialog_OpenMainMenu", |
|
pOwner ); |
|
break; |
|
|
|
case MD_QUIT_CONFIRMATION_TF: |
|
CreateMessageDialog( MD_YESNO|MD_RESTRICTPAINT, |
|
"#GameUI_QuitConfirmationTitle", |
|
"#GameUI_QuitConfirmationText", |
|
"QuitNoConfirm", |
|
"CloseQuitDialog_OpenMatchmakingMenu", |
|
pOwner ); |
|
break; |
|
|
|
case MD_DISCONNECT_CONFIRMATION: |
|
CreateMessageDialog( MD_YESNO|MD_RESTRICTPAINT, |
|
"", |
|
"#GameUI_DisconnectConfirmationText", |
|
"DisconnectNoConfirm", |
|
"close_dialog", |
|
pOwner ); |
|
break; |
|
|
|
case MD_DISCONNECT_CONFIRMATION_HOST: |
|
CreateMessageDialog( MD_YESNO|MD_RESTRICTPAINT, |
|
"", |
|
"#GameUI_DisconnectHostConfirmationText", |
|
"DisconnectNoConfirm", |
|
"close_dialog", |
|
pOwner ); |
|
break; |
|
|
|
case MD_KICK_CONFIRMATION: |
|
CreateMessageDialog( MD_YESNO, |
|
"", |
|
"#TF_Dlg_ConfirmKick", |
|
"KickPlayer", |
|
"close_dialog", |
|
pOwner ); |
|
break; |
|
|
|
case MD_CLIENT_KICKED: |
|
CreateMessageDialog( MD_OK|MD_RESTRICTPAINT, |
|
"", |
|
"#TF_Dlg_ClientKicked", |
|
"close_dialog", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_EXIT_SESSION_CONFIRMATION: |
|
CreateMessageDialog( MD_YESNO, |
|
"", |
|
"#TF_Dlg_ExitSessionText", |
|
"ReturnToMainMenu", |
|
"close_dialog", |
|
pOwner ); |
|
break; |
|
|
|
case MD_STORAGE_DEVICES_NEEDED: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|MD_COMMANDAFTERCLOSE|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_Console_StorageRemovedTitle", |
|
"#GameUI_Console_StorageNeededBody", |
|
"ShowDeviceSelector", |
|
"QuitNoConfirm", |
|
pOwner ); |
|
break; |
|
|
|
case MD_STORAGE_DEVICES_CHANGED: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|MD_COMMANDAFTERCLOSE|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_Console_StorageRemovedTitle", |
|
"#GameUI_Console_StorageRemovedBody", |
|
"ShowDeviceSelector", |
|
"clear_storage_deviceID", |
|
pOwner ); |
|
break; |
|
|
|
case MD_STORAGE_DEVICES_TOO_FULL: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|MD_COMMANDAFTERCLOSE|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_Console_StorageTooFullTitle", |
|
"#GameUI_Console_StorageTooFullBody", |
|
"ShowDeviceSelector", |
|
"StorageDeviceDenied", |
|
pOwner ); |
|
break; |
|
|
|
case MD_PROMPT_STORAGE_DEVICE: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|MD_COMMANDAFTERCLOSE|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_Console_NoStorageDeviceSelectedTitle", |
|
"#GameUI_Console_NoStorageDeviceSelectedBody", |
|
"ShowDeviceSelector", |
|
"StorageDeviceDenied", |
|
pOwner ); |
|
break; |
|
|
|
case MD_PROMPT_STORAGE_DEVICE_REQUIRED: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|MD_COMMANDAFTERCLOSE|MD_SIMPLEFRAME, |
|
"#GameUI_Console_NoStorageDeviceSelectedTitle", |
|
"#GameUI_Console_StorageDeviceRequiredBody", |
|
"ShowDeviceSelector", |
|
"RequiredStorageDenied", |
|
pOwner ); |
|
break; |
|
|
|
case MD_PROMPT_SIGNIN: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|MD_COMMANDAFTERCLOSE|iSimpleFrame, |
|
"#GameUI_Console_NoUserProfileSelectedTitle", |
|
"#GameUI_Console_NoUserProfileSelectedBody", |
|
"ShowSignInUI", |
|
"SignInDenied", |
|
pOwner ); |
|
break; |
|
|
|
case MD_PROMPT_SIGNIN_REQUIRED: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|MD_COMMANDAFTERCLOSE|iSimpleFrame, |
|
"#GameUI_Console_NoUserProfileSelectedTitle", |
|
"#GameUI_Console_UserProfileRequiredBody", |
|
"ShowSignInUI", |
|
"RequiredSignInDenied", |
|
pOwner ); |
|
break; |
|
|
|
case MD_NOT_ONLINE_ENABLED: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING, |
|
"", |
|
"#TF_Dlg_NotOnlineEnabled", |
|
"ShowSigninUI", |
|
"close_dialog", |
|
pOwner ); |
|
break; |
|
|
|
case MD_NOT_ONLINE_SIGNEDIN: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING, |
|
"", |
|
"#TF_Dlg_NotOnlineSignedIn", |
|
"ShowSigninUI", |
|
"close_dialog", |
|
pOwner ); |
|
break; |
|
|
|
case MD_DEFAULT_CONTROLS_CONFIRM: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_RestoreDefaults", |
|
"#GameUI_ControllerSettingsText", |
|
"DefaultControls", |
|
"close_dialog", |
|
pOwner ); |
|
break; |
|
|
|
case MD_AUTOSAVE_EXPLANATION: |
|
CreateMessageDialog( MD_OK|MD_WARNING|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_ConfirmNewGame_Title", |
|
"#GameUI_AutoSave_Console_Explanation", |
|
"StartNewGameNoCommentaryExplanation", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_COMMENTARY_EXPLANATION: |
|
CreateMessageDialog( MD_OK|MD_WARNING|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_CommentaryDialogTitle", |
|
"#GAMEUI_Commentary_Console_Explanation", |
|
"StartNewGameNoCommentaryExplanation", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_COMMENTARY_EXPLANATION_MULTI: |
|
CreateMessageDialog( MD_OK|MD_WARNING, |
|
"#GameUI_CommentaryDialogTitle", |
|
"#GAMEUI_Commentary_Console_Explanation", |
|
"StartNewGameNoCommentaryExplanation", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_COMMENTARY_CHAPTER_UNLOCK_EXPLANATION: |
|
CreateMessageDialog( MD_OK|MD_WARNING|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_CommentaryDialogTitle", |
|
"#GameUI_CommentaryUnlock", |
|
"close_dialog", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_SAVE_BEFORE_LANGUAGE_CHANGE: |
|
CreateMessageDialog( MD_YESNO|MD_WARNING|MD_SIMPLEFRAME|MD_COMMANDAFTERCLOSE|MD_RESTRICTPAINT, |
|
"#GameUI_ChangeLanguageRestart_Title", |
|
"#GameUI_ChangeLanguageRestart_Info", |
|
"AcceptVocalsLanguageChange", |
|
"CancelVocalsLanguageChange", |
|
pOwner ); |
|
|
|
case MD_SAVE_BEFORE_NEW_GAME: |
|
CreateMessageDialog( MD_OKCANCEL|MD_WARNING|iSimpleFrame|MD_COMMANDAFTERCLOSE|MD_RESTRICTPAINT, |
|
"#GameUI_ConfirmNewGame_Title", |
|
"#GameUI_NewGameWarning", |
|
"StartNewGame", |
|
"close_dialog", |
|
pOwner ); |
|
break; |
|
|
|
case MD_SAVE_BEFORE_LOAD: |
|
CreateMessageDialog( MD_OKCANCEL|MD_WARNING|iSimpleFrame|MD_COMMANDAFTERCLOSE|MD_RESTRICTPAINT, |
|
"#GameUI_ConfirmLoadGame_Title", |
|
"#GameUI_LoadWarning", |
|
"LoadGame", |
|
"LoadGameCancelled", |
|
pOwner ); |
|
break; |
|
|
|
case MD_DELETE_SAVE_CONFIRM: |
|
CreateMessageDialog( MD_OKCANCEL|MD_WARNING|iSimpleFrame|MD_COMMANDAFTERCLOSE, |
|
"#GameUI_ConfirmDeleteSaveGame_Title", |
|
"#GameUI_ConfirmDeleteSaveGame_Info", |
|
"DeleteGame", |
|
"DeleteGameCancelled", |
|
pOwner ); |
|
break; |
|
|
|
case MD_SAVE_OVERWRITE: |
|
CreateMessageDialog( MD_OKCANCEL|MD_WARNING|iSimpleFrame|MD_COMMANDAFTERCLOSE, |
|
"#GameUI_ConfirmOverwriteSaveGame_Title", |
|
"#GameUI_ConfirmOverwriteSaveGame_Info", |
|
"SaveGame", |
|
"OverwriteGameCancelled", |
|
pOwner ); |
|
break; |
|
|
|
case MD_SAVING_WARNING: |
|
CreateMessageDialog( MD_WARNING|iSimpleFrame|MD_COMMANDONFORCECLOSE, |
|
"", |
|
"#GameUI_SavingWarning", |
|
"SaveSuccess", |
|
NULL, |
|
pOwner, |
|
true); |
|
break; |
|
|
|
case MD_SAVE_COMPLETE: |
|
CreateMessageDialog( MD_OK|iSimpleFrame|MD_COMMANDAFTERCLOSE, |
|
"#GameUI_ConfirmOverwriteSaveGame_Title", |
|
"#GameUI_GameSaved", |
|
"CloseAndSelectResume", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_LOAD_FAILED_WARNING: |
|
CreateMessageDialog( MD_OK |MD_WARNING|iSimpleFrame, |
|
"#GameUI_LoadFailed", |
|
"#GameUI_LoadFailed_Description", |
|
"close_dialog", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_OPTION_CHANGE_FROM_X360_DASHBOARD: |
|
CreateMessageDialog( MD_OK|iSimpleFrame|MD_RESTRICTPAINT, |
|
"#GameUI_SettingChangeFromX360Dashboard_Title", |
|
"#GameUI_SettingChangeFromX360Dashboard_Info", |
|
"close_dialog", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_STANDARD_SAMPLE: |
|
CreateMessageDialog( MD_OK, |
|
"Standard Dialog", |
|
"This is a standard dialog", |
|
"close_dialog", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_WARNING_SAMPLE: |
|
CreateMessageDialog( MD_OK | MD_WARNING, |
|
"#GameUI_Dialog_Warning", |
|
"This is a warning dialog", |
|
"close_dialog", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_ERROR_SAMPLE: |
|
CreateMessageDialog( MD_OK | MD_ERROR, |
|
"Error Dialog", |
|
"This is an error dialog", |
|
"close_dialog", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_STORAGE_DEVICES_CORRUPT: |
|
CreateMessageDialog( MD_OK | MD_WARNING | iSimpleFrame | MD_RESTRICTPAINT, |
|
"", |
|
"#GameUI_Console_FileCorrupt", |
|
"close_dialog", |
|
NULL, |
|
pOwner ); |
|
break; |
|
|
|
case MD_CHECKING_STORAGE_DEVICE: |
|
CreateMessageDialog( iSimpleFrame | MD_RESTRICTPAINT, |
|
NULL, |
|
"#GameUI_Dlg_CheckingStorageDevice", |
|
NULL, |
|
NULL, |
|
pOwner, |
|
true ); |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
|
|
void CMessageDialogHandler::CloseAllMessageDialogs() |
|
{ |
|
for ( int i = 0; i < MAX_MESSAGE_DIALOGS; ++i ) |
|
{ |
|
CMessageDialog *pDlg = m_hMessageDialogs[i]; |
|
if ( pDlg ) |
|
{ |
|
vgui::surface()->RestrictPaintToSinglePanel(NULL); |
|
if ( vgui_message_dialog_modal.GetBool() ) |
|
{ |
|
vgui::input()->ReleaseAppModalSurface(); |
|
} |
|
|
|
pDlg->Close(); |
|
m_hMessageDialogs[i] = NULL; |
|
} |
|
} |
|
} |
|
|
|
void CMessageDialogHandler::CloseMessageDialog( const uint nType ) |
|
{ |
|
int nStackIdx = 0; |
|
if ( nType & MD_WARNING ) |
|
{ |
|
nStackIdx = DIALOG_STACK_IDX_WARNING; |
|
} |
|
else if ( nType & MD_ERROR ) |
|
{ |
|
nStackIdx = DIALOG_STACK_IDX_ERROR; |
|
} |
|
|
|
CMessageDialog *pDlg = m_hMessageDialogs[nStackIdx]; |
|
if ( pDlg ) |
|
{ |
|
vgui::surface()->RestrictPaintToSinglePanel(NULL); |
|
if ( vgui_message_dialog_modal.GetBool() ) |
|
{ |
|
vgui::input()->ReleaseAppModalSurface(); |
|
} |
|
|
|
pDlg->Close(); |
|
m_hMessageDialogs[nStackIdx] = NULL; |
|
} |
|
} |
|
|
|
void CMessageDialogHandler::CreateMessageDialog( const uint nType, const char *pTitle, const char *pMsg, const char *pCmdA, const char *pCmdB, vgui::Panel *pCreator, bool bShowActivity /*= false*/ ) |
|
{ |
|
int nStackIdx = 0; |
|
if ( nType & MD_WARNING ) |
|
{ |
|
nStackIdx = DIALOG_STACK_IDX_WARNING; |
|
} |
|
else if ( nType & MD_ERROR ) |
|
{ |
|
nStackIdx = DIALOG_STACK_IDX_ERROR; |
|
} |
|
|
|
// Can only show one dialog of each type at a time |
|
if ( m_hMessageDialogs[nStackIdx].Get() ) |
|
{ |
|
Warning( "Tried to create two dialogs of type %d\n", nStackIdx ); |
|
return; |
|
} |
|
|
|
// Show the new dialog |
|
m_hMessageDialogs[nStackIdx] = new CMessageDialog( BasePanel(), nType, pTitle, pMsg, pCmdA, pCmdB, pCreator, bShowActivity ); |
|
|
|
m_hMessageDialogs[nStackIdx]->SetControlSettingsKeys( BasePanel()->GetConsoleControlSettings()->FindKey( "MessageDialog.res" ) ); |
|
|
|
if ( nType & MD_RESTRICTPAINT ) |
|
{ |
|
vgui::surface()->RestrictPaintToSinglePanel( m_hMessageDialogs[nStackIdx]->GetVPanel() ); |
|
} |
|
|
|
ActivateMessageDialog( nStackIdx ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Activate a new message dialog |
|
//----------------------------------------------------------------------------- |
|
void CMessageDialogHandler::ActivateMessageDialog( int nStackIdx ) |
|
{ |
|
int x, y, wide, tall; |
|
vgui::surface()->GetWorkspaceBounds( x, y, wide, tall ); |
|
PositionDialog( m_hMessageDialogs[nStackIdx], wide, tall ); |
|
|
|
uint nType = m_hMessageDialogs[nStackIdx]->GetType(); |
|
if ( nType & MD_WARNING ) |
|
{ |
|
m_hMessageDialogs[nStackIdx]->SetZPos( 75 ); |
|
} |
|
else if ( nType & MD_ERROR ) |
|
{ |
|
m_hMessageDialogs[nStackIdx]->SetZPos( 100 ); |
|
} |
|
|
|
// Make sure the topmost item on the stack still has focus |
|
int idx = MAX_MESSAGE_DIALOGS - 1; |
|
for ( idx; idx >= nStackIdx; --idx ) |
|
{ |
|
CMessageDialog *pDialog = m_hMessageDialogs[idx]; |
|
if ( pDialog ) |
|
{ |
|
pDialog->Activate(); |
|
if ( vgui_message_dialog_modal.GetBool() ) |
|
{ |
|
vgui::input()->SetAppModalSurface( pDialog->GetVPanel() ); |
|
} |
|
m_iDialogStackTop = idx; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
void CMessageDialogHandler::PositionDialogs( int wide, int tall ) |
|
{ |
|
for ( int i = 0; i < MAX_MESSAGE_DIALOGS; ++i ) |
|
{ |
|
if ( m_hMessageDialogs[i].Get() ) |
|
{ |
|
PositionDialog( m_hMessageDialogs[i], wide, tall ); |
|
} |
|
} |
|
} |
|
|
|
void CMessageDialogHandler::PositionDialog( vgui::PHandle dlg, int wide, int tall ) |
|
{ |
|
int w, t; |
|
dlg->GetSize(w, t); |
|
dlg->SetPos( (wide - w) / 2, (tall - t) / 2 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Editable panel that can replace the GameMenuButtons in CBasePanel |
|
//----------------------------------------------------------------------------- |
|
CMainMenuGameLogo::CMainMenuGameLogo( vgui::Panel *parent, const char *name ) : vgui::EditablePanel( parent, name ) |
|
{ |
|
m_nOffsetX = 0; |
|
m_nOffsetY = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CMainMenuGameLogo::ApplySettings( KeyValues *inResourceData ) |
|
{ |
|
BaseClass::ApplySettings( inResourceData ); |
|
|
|
m_nOffsetX = inResourceData->GetInt( "offsetX", 0 ); |
|
m_nOffsetY = inResourceData->GetInt( "offsetY", 0 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CMainMenuGameLogo::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
KeyValues *pConditions = new KeyValues( "conditions" ); |
|
if ( pConditions ) |
|
{ |
|
char background[MAX_PATH]; |
|
engine->GetMainMenuBackgroundName( background, sizeof(background) ); |
|
|
|
KeyValues *pSubKey = new KeyValues( background ); |
|
if ( pSubKey ) |
|
{ |
|
pConditions->AddSubKey( pSubKey ); |
|
} |
|
} |
|
|
|
LoadControlSettings( "Resource/GameLogo.res", NULL, NULL, pConditions ); |
|
|
|
if ( pConditions ) |
|
{ |
|
pConditions->deleteThis(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBasePanel::CloseBaseDialogs( void ) |
|
{ |
|
if ( m_hNewGameDialog.Get() ) |
|
m_hNewGameDialog->Close(); |
|
|
|
if ( m_hAchievementsDialog.Get() ) |
|
m_hAchievementsDialog->Close(); |
|
|
|
if ( m_hBonusMapsDialog.Get() ) |
|
m_hBonusMapsDialog->Close(); |
|
|
|
if ( m_hControllerDialog.Get() ) |
|
m_hControllerDialog->Close(); |
|
|
|
if ( m_hLoadGameDialog_Xbox.Get() ) |
|
m_hLoadGameDialog_Xbox->Close(); |
|
|
|
if ( m_hOptionsDialog_Xbox.Get() ) |
|
m_hOptionsDialog_Xbox->Close(); |
|
|
|
if ( m_hSaveGameDialog_Xbox.Get() ) |
|
m_hSaveGameDialog_Xbox->Close(); |
|
|
|
if ( m_hLoadCommentaryDialog.Get() ) |
|
m_hLoadCommentaryDialog->Close(); |
|
|
|
if ( m_hCreateMultiplayerGameDialog.Get() ) |
|
m_hCreateMultiplayerGameDialog->Close(); |
|
} |
|
|
|
static void CC_GameUIShowDialog( const CCommand &args ) |
|
{ |
|
int c = args.ArgC(); |
|
|
|
if ( c < 2 ) |
|
{ |
|
Msg( "Usage: gamemenucommand <commandname>\n" ); |
|
return; |
|
} |
|
|
|
GameUI().ShowMessageDialog( atoi(args[1]) ); |
|
} |
|
static ConCommand gameui_show_dialog( "gameui_show_dialog", CC_GameUIShowDialog, "Show an arbitrary Dialog.", 0 ); |
|
|
|
static void CC_GameUIHideDialog( const CCommand &args ) |
|
{ |
|
int c = args.ArgC(); |
|
if ( c < 1 ) |
|
{ |
|
Msg( "Usage: gamemenucommand <commandname>\n" ); |
|
return; |
|
} |
|
|
|
GameUI().CloseMessageDialog( 0 ); |
|
} |
|
static ConCommand gameui_hide_dialog( "gameui_hide_dialog", CC_GameUIHideDialog, "asdf", 0 ); |
|
|
|
static void RefreshOptionsDialog( const CCommand &args ) |
|
{ |
|
if ( g_hOptionsDialog ) |
|
{ |
|
CBasePanel* pBasePanel = (CBasePanel*) g_hOptionsDialog->GetParent(); |
|
g_hOptionsDialog->Close(); |
|
delete g_hOptionsDialog.Get(); |
|
if ( pBasePanel ) |
|
{ |
|
pBasePanel->OnOpenOptionsDialog(); |
|
COptionsDialog *pOptionsDialog = dynamic_cast<COptionsDialog*>( g_hOptionsDialog.Get() ); |
|
if ( pOptionsDialog ) |
|
{ |
|
pOptionsDialog->GetPropertySheet()->SetActivePage( pOptionsDialog->GetOptionsSubMultiplayer() ); |
|
} |
|
} |
|
} |
|
} |
|
static ConCommand refresh_options_dialog( "refresh_options_dialog", RefreshOptionsDialog, "Refresh the options dialog.", 0 );
|
|
|