source-engine/gameui/matchmaking/sessionbrowserdialog.cpp

324 lines
8.6 KiB
C++
Raw Permalink Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Present a list of sessions from which the player can choose a game to join.
//
//=============================================================================//
#include "sessionbrowserdialog.h"
#include "engine/imatchmaking.h"
#include "EngineInterface.h"
#include "vgui_controls/ImagePanel.h"
#include "vgui_controls/Label.h"
#include "KeyValues.h"
#include "vgui/ISurface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CSessionBrowserDialog *g_pBrowserDialog;
//--------------------------------
// CSessionBrowserDialog
//--------------------------------
CSessionBrowserDialog::CSessionBrowserDialog( vgui::Panel *pParent, KeyValues *pDialogKeys ) : BaseClass( pParent, "" )
{
g_pBrowserDialog = this;
m_pDialogKeys = pDialogKeys;
SetDeleteSelfOnClose( true );
}
CSessionBrowserDialog::~CSessionBrowserDialog()
{
m_pScenarioInfos.PurgeAndDeleteElements();
}
//---------------------------------------------------------------------
// Purpose: Center the dialog on the screen
//---------------------------------------------------------------------
void CSessionBrowserDialog::PerformLayout()
{
BaseClass::PerformLayout();
MoveToCenterOfScreen();
UpdateScenarioDisplay();
}
//---------------------------------------------------------------------
// Purpose: Parse session properties and contexts from the resource file
//---------------------------------------------------------------------
void CSessionBrowserDialog::ApplySettings( KeyValues *pResourceData )
{
BaseClass::ApplySettings( pResourceData );
KeyValues *pScenarios = pResourceData->FindKey( "ScenarioInfoPanels" );
if ( pScenarios )
{
for ( KeyValues *pScenario = pScenarios->GetFirstSubKey(); pScenario != NULL; pScenario = pScenario->GetNextKey() )
{
CScenarioInfoPanel *pScenarioInfo = new CScenarioInfoPanel( this, "ScenarioInfoPanel" );
SETUP_PANEL( pScenarioInfo );
pScenarioInfo->m_pTitle->SetText( pScenario->GetString( "title" ) );
pScenarioInfo->m_pSubtitle->SetText( pScenario->GetString( "subtitle" ) );
pScenarioInfo->m_pMapImage->SetImage( pScenario->GetString( "image" ) );
int nTall = pScenario->GetInt( "tall", -1 );
if ( nTall > 0 )
{
pScenarioInfo->SetTall( nTall );
}
int nXPos = pScenario->GetInt( "xpos", -1 );
if ( nXPos >= 0 )
{
int x, y;
pScenarioInfo->GetPos( x, y );
pScenarioInfo->SetPos( nXPos, y );
}
int nDescOneYpos = pScenario->GetInt( "descOneY", -1 );
if ( nDescOneYpos > 0 )
{
int x, y;
pScenarioInfo->m_pDescOne->GetPos( x, y );
pScenarioInfo->m_pDescOne->SetPos( x, nDescOneYpos );
}
int nDescTwoYpos = pScenario->GetInt( "descTwoY", -1 );
if ( nDescTwoYpos > 0 )
{
int x, y;
pScenarioInfo->m_pDescTwo->GetPos( x, y );
pScenarioInfo->m_pDescTwo->SetPos( x, nDescTwoYpos );
}
m_pScenarioInfos.AddToTail( pScenarioInfo );
}
}
}
//---------------------------------------------------------------------
// Purpose: Set up colors and other such stuff
//---------------------------------------------------------------------
void CSessionBrowserDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
for ( int i = 0; i < m_pScenarioInfos.Count(); ++i )
{
m_pScenarioInfos[i]->SetBgColor( pScheme->GetColor( "TanDark", Color( 0, 0, 0, 255 ) ) );
}
}
//---------------------------------------------------------------------
// Purpose: Info about a session, sent from matchmaking
//---------------------------------------------------------------------
void CSessionBrowserDialog::SessionSearchResult( int searchIdx, void *pHostData, XSESSION_SEARCHRESULT *pResult, int ping )
{
char *pPing;
switch ( ping )
{
case 0:
pPing = "#TF_Icon_Ping_Green";
break;
case 1:
pPing = "#TF_Icon_Ping_Yellow";
break;
case 2:
default:
pPing = "#TF_Icon_Ping_Red";
break;
}
int nScenarioId = 0;
uint nContextId = m_pDialogKeys->GetInt( "scenario", -1 );
for ( uint i = 0; i < pResult->cContexts; ++i )
{
if ( pResult->pContexts[i].dwContextId == nContextId )
{
nScenarioId = pResult->pContexts[i].dwValue;
break;
}
}
hostData_s *pData = (hostData_s*)pHostData;
int filledSlots = pResult->dwFilledPublicSlots + pResult->dwFilledPrivateSlots;
int totalSlots = filledSlots + pResult->dwOpenPublicSlots + pResult->dwOpenPrivateSlots;
m_GameStates.AddToTail( pData->gameState );
m_GameTimes.AddToTail( pData->gameTime );
m_XUIDs.AddToTail( pData->xuid );
char szSlots[16] = {0};
Q_snprintf( szSlots, sizeof( szSlots ), "%d/%d", filledSlots, totalSlots );
int ct = 0;
const char *ppStrings[4];
ppStrings[ct++] = pData->hostName;
ppStrings[ct++] = szSlots;
ppStrings[ct++] = pData->scenario;
if ( ping != -1 )
{
ppStrings[ct++] = pPing;
}
m_Menu.AddSectionedItem( ppStrings, ct );
m_ScenarioIndices.AddToTail( nScenarioId );
m_SearchIndices.AddToTail( searchIdx );
if ( m_Menu.GetItemCount() == 1 )
{
m_Menu.SetFocus( 0 );
}
UpdateScenarioDisplay();
}
//-----------------------------------------------------------------
// Purpose: Show the correct scenario image and text
//-----------------------------------------------------------------
void CSessionBrowserDialog::UpdateScenarioDisplay( void )
{
if ( !m_ScenarioIndices.Count() )
return;
// Check if the selected map has changed (first menu item)
int idx = m_Menu.GetActiveItemIndex();
for ( int i = 0; i < m_pScenarioInfos.Count(); ++i )
{
m_pScenarioInfos[i]->SetVisible( i == m_ScenarioIndices[idx] );
}
// Get the screen size
int wide, tall;
vgui::surface()->GetScreenSize(wide, tall);
bool bLodef = ( tall <= 480 );
const char *pState = "";
switch( m_GameStates[idx] )
{
case 0:
if ( bLodef )
{
pState = "#TF_GameState_InLobby_lodef";
}
else
{
pState = "#TF_GameState_InLobby";
}
break;
case 1:
if ( bLodef )
{
pState = "#TF_GameState_GameInProgress_lodef";
}
else
{
pState = "#TF_GameState_GameInProgress";
}
break;
}
char szTime[32] = {0};
if ( m_GameTimes[idx] >= NO_TIME_LIMIT )
{
Q_strncpy( szTime, "#TF_NoTimeLimit", sizeof( szTime) );
}
else
{
Q_snprintf( szTime, sizeof( szTime), "%d:00", m_GameTimes[idx] );
}
if ( !m_pScenarioInfos.IsValidIndex( m_ScenarioIndices[idx] ) )
return;
CScenarioInfoPanel *pPanel = m_pScenarioInfos[ m_ScenarioIndices[idx] ];
pPanel->m_pDescOne->SetText( pState );
pPanel->m_pDescTwo->SetText( szTime );
}
//-----------------------------------------------------------------
// helper to swap two ints in a utlvector
//-----------------------------------------------------------------
static void Swap( CUtlVector< int > &vec, int iOne, int iTwo )
{
int temp = vec[iOne];
vec[iOne] = vec[iTwo];
vec[iTwo] = temp;
}
//-----------------------------------------------------------------
// Purpose: Swap the order of two menu items
//-----------------------------------------------------------------
void CSessionBrowserDialog::SwapMenuItems( int iOne, int iTwo )
{
Swap( m_ScenarioIndices, iOne, iTwo );
Swap( m_SearchIndices, iOne, iTwo );
Swap( m_GameStates, iOne, iTwo );
Swap( m_GameTimes, iOne, iTwo );
// swap the XUIDs, too
XUID temp = m_XUIDs[iOne];
m_XUIDs[iOne] = m_XUIDs[iTwo];
m_XUIDs[iTwo] = temp;
}
//-----------------------------------------------------------------
// Purpose: Handle commands from the dialog menu
//-----------------------------------------------------------------
void CSessionBrowserDialog::OnCommand( const char *pCommand )
{
if ( !Q_stricmp( pCommand, "SelectSession" ) )
{
int idx = m_SearchIndices[ m_Menu.GetActiveItemIndex() ];
matchmaking->SelectSession( idx );
}
m_pParent->OnCommand( pCommand );
}
//-----------------------------------------------------------------
// Purpose: Send key presses to the dialog's menu
//-----------------------------------------------------------------
void CSessionBrowserDialog::OnKeyCodePressed( vgui::KeyCode code )
{
switch( code )
{
case KEY_XBUTTON_B:
matchmaking->KickPlayerFromSession( 0 );
break;
case KEY_XBUTTON_X:
#ifdef _X360
int idx = m_Menu.GetActiveItemIndex();
if ( m_XUIDs.IsValidIndex( idx ) )
{
XShowGamerCardUI( XBX_GetPrimaryUserId(), m_XUIDs[idx] );
}
#endif
break;
}
BaseClass::OnKeyCodePressed( code );
// Selected session may have been updated
UpdateScenarioDisplay();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSessionBrowserDialog::OnThink()
{
vgui::KeyCode code = m_KeyRepeat.KeyRepeated();
if ( code )
{
m_Menu.HandleKeyCode( code );
UpdateScenarioDisplay();
}
BaseClass::OnThink();
}