|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "tf_party.h"
#include "vgui_controls/PropertySheet.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "tf_lobbypanel_comp.h"
#include "tf_lobby_container_frame_comp.h"
#include "vgui/ISystem.h"
#include "tf_streams.h"
#include "tf_badge_panel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
ConVar tf_mm_ladder_ui_last_rating_change( "tf_mm_ladder_ui_last_rating_change", "0", FCVAR_HIDDEN | FCVAR_ARCHIVE, "Track last match skillrating change for UI." ); ConVar tf_mm_ladder_ui_last_rating_time( "tf_mm_ladder_ui_last_rating_time", "-1", FCVAR_HIDDEN | FCVAR_ARCHIVE, "Track last match skillrating change time for UI." );
class CLobbyPanel_Comp;
#include "iclientmode.h"
#include <vgui_controls/AnimationController.h>
class CMatchHistoryEntryPanel : public CExpandablePanel { public: DECLARE_CLASS_SIMPLE( CMatchHistoryEntryPanel, CExpandablePanel ); CMatchHistoryEntryPanel( Panel* pParent, const char *pszPanelname ) : BaseClass( pParent, pszPanelname ) {}
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE { BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/MatchHistoryEntryPanel.res" ); }
void SetMatchData( const CSOTFMatchResultPlayerStats& stats ) { EditablePanel* pContainer = FindControl< EditablePanel >( "Container" ); if ( !pContainer ) return;
// Match date
CRTime matchdate( stats.endtime() ); char rtime_buf[k_RTimeRenderBufferSize]; matchdate.Render( rtime_buf ); pContainer->SetDialogVariable( "match_date", rtime_buf );
// Map name
const MapDef_t* pMapDef = GetItemSchema()->GetMasterMapDefByIndex( stats.map_index() ); const char* pszMapToken = "#TF_Map_Unknown"; if ( pMapDef ) { pszMapToken = pMapDef->pszMapNameLocKey; } pContainer->SetDialogVariable( "map_name", g_pVGuiLocalize->Find( pszMapToken ) );
// KD ratio
float flKDRatio = stats.kills(); if ( stats.deaths() > 0 ) { flKDRatio /= (float)stats.deaths(); } pContainer->SetDialogVariable( "kd_ratio", CFmtStr( "%.1f", flKDRatio ) );
pContainer->SetControlVisible( "WinLabel", stats.display_rating_change() > 0 ); pContainer->SetControlVisible( "LossLabel", stats.display_rating_change() < 0 );
EditablePanel* pStatsContainer = FindControl< EditablePanel >( "SlidingStatsContainer", true ); if ( pStatsContainer ) { pStatsContainer->SetDialogVariable( "stat_kills", LocalizeNumberWithToken( "TF_Competitive_Kills", stats.kills() ) ); pStatsContainer->SetDialogVariable( "stat_deaths", LocalizeNumberWithToken( "TF_Competitive_Deaths", stats.deaths() ) ); pStatsContainer->SetDialogVariable( "stat_damage", LocalizeNumberWithToken( "TF_Competitive_Damage", stats.damage() ) ); pStatsContainer->SetDialogVariable( "stat_healing", LocalizeNumberWithToken( "TF_Competitive_Healing", stats.healing() ) ); pStatsContainer->SetDialogVariable( "stat_support", LocalizeNumberWithToken( "TF_Competitive_Support", stats.support() ) ); pStatsContainer->SetDialogVariable( "stat_score", LocalizeNumberWithToken( "TF_Competitive_Score", stats.score() ) );
ScalableImagePanel* pMapImage = pStatsContainer->FindControl< ScalableImagePanel >( "BGImage", true ); if ( pMapImage && pMapDef ) { char imagename[ 512 ]; Q_snprintf( imagename, sizeof( imagename ), "..\\vgui\\maps\\menu_thumb_%s", pMapDef->pszMapName ); pMapImage->SetImage( imagename ); }
// Lambdas, wherefore art thou...
SetupClassIcon( pStatsContainer, "scout", TF_CLASS_SCOUT, stats ); SetupClassIcon( pStatsContainer, "soldier", TF_CLASS_SOLDIER, stats ); SetupClassIcon( pStatsContainer, "pyro", TF_CLASS_PYRO, stats ); SetupClassIcon( pStatsContainer, "demo", TF_CLASS_DEMOMAN, stats ); SetupClassIcon( pStatsContainer, "heavy", TF_CLASS_HEAVYWEAPONS, stats ); SetupClassIcon( pStatsContainer, "engineer", TF_CLASS_ENGINEER, stats ); SetupClassIcon( pStatsContainer, "medic", TF_CLASS_MEDIC, stats ); SetupClassIcon( pStatsContainer, "sniper", TF_CLASS_SNIPER, stats ); SetupClassIcon( pStatsContainer, "spy", TF_CLASS_SPY, stats );
SetupMedalForStat( pStatsContainer, stats.kills_medal(), "kills" ); SetupMedalForStat( pStatsContainer, stats.damage_medal(), "damage" ); SetupMedalForStat( pStatsContainer, stats.healing_medal(), "healing" ); SetupMedalForStat( pStatsContainer, stats.support_medal(), "support" ); SetupMedalForStat( pStatsContainer, stats.score_medal(), "score" ); } } private:
void SetupMedalForStat( EditablePanel* pParent, int nStat, const char* pszStatName ) { ScalableImagePanel* pMedalImage = pParent->FindControl< ScalableImagePanel >( CFmtStr( "%sMedal", pszStatName ) ); if ( pMedalImage ) { if ( nStat != StatMedal_None ) { pMedalImage->SetImage( g_pszCompetitiveMedalImages[ nStat ] ); } pMedalImage->SetVisible( nStat != StatMedal_None ); } }
void SetupClassIcon( EditablePanel* pParent, const char* pszClassName, int nBit, const CSOTFMatchResultPlayerStats& stats ) { ScalableImagePanel* pClassIcon = pParent->FindControl< ScalableImagePanel >( CFmtStr( "%sIcon", pszClassName ), true ); if( pClassIcon ) { pClassIcon->SetImage( stats.classes_played() & (1<<nBit) ? CFmtStr( "class_icons/filter_%s_on", pszClassName ) : CFmtStr( "class_icons/filter_%s", pszClassName ) ); } } };
DECLARE_BUILD_FACTORY( CMatchHistoryEntryPanel );
extern Color s_colorChallengeHeader;
DECLARE_BUILD_FACTORY( CLadderLobbyLeaderboard ); //-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CLadderLobbyLeaderboard::CLadderLobbyLeaderboard( Panel *pParent, const char *pszPanelName ) : CTFLeaderboardPanel( pParent, pszPanelName ) { m_pScoreList = new vgui::EditablePanel( this, "ScoreList" ); m_pScoreListScroller = new vgui::ScrollableEditablePanel( this, m_pScoreList, "ScoreListScroller" ); m_pScoreListScroller->AddActionSignalTarget( this );
m_pszLeaderboardName = "tf2_ladder_6v6";
for ( int i = 0; i < 100; ++i ) { vgui::EditablePanel *pEntryUI = new vgui::EditablePanel( m_pScoreList, "LeaderboardEntry" ); m_vecLeaderboardEntries.AddToTail( pEntryUI ); }
m_pToolTip = new CTFTextToolTip( this ); m_pToolTipEmbeddedPanel = new vgui::EditablePanel( this, "TooltipPanel" ); m_pToolTipEmbeddedPanel->SetKeyBoardInputEnabled( false ); m_pToolTipEmbeddedPanel->SetMouseInputEnabled( false ); m_pToolTip->SetEmbeddedPanel( m_pToolTipEmbeddedPanel ); m_pToolTip->SetTooltipDelay( 0 );
m_bIsDataValid = false; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLadderLobbyLeaderboard::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/econ/LobbyLeaderboard.res" );
FOR_EACH_VEC( m_vecLeaderboardEntries, i ) { m_vecLeaderboardEntries[i]->ApplySchemeSettings( pScheme ); m_vecLeaderboardEntries[i]->LoadControlSettings( "Resource/UI/LeaderboardEntryRank.res" ); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLadderLobbyLeaderboard::PerformLayout() { BaseClass::PerformLayout();
UpdateLeaderboards(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLadderLobbyLeaderboard::OnCommand( const char *command ) { if ( Q_strnicmp( command, "stream", 6 ) == 0 ) { vgui::system()->ShellExecute( "open", command + 7 ); return; } else if ( FStrEq( "global", command ) ) { if ( m_bGlobal != true ) { m_bGlobal = true; UpdateLeaderboards(); }
return; } else if ( FStrEq( "local", command ) ) { if ( m_bGlobal == true ) { m_bGlobal = false; UpdateLeaderboards(); } }
BaseClass::OnCommand( command ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CLadderLobbyLeaderboard::GetLeaderboardData( CUtlVector< LeaderboardEntry_t* >& scores ) { CUtlVector< LeaderboardEntry_t* > vecLadderScores; if ( Leaderboards_GetLadderLeaderboard( vecLadderScores, m_pszLeaderboardName, m_bGlobal ) ) { scores.AddVectorToTail( vecLadderScores ); return true; }
return false; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CLadderLobbyLeaderboard::UpdateLeaderboards() { CUtlVector< LeaderboardEntry_t* > scores; m_bIsDataValid = GetLeaderboardData( scores ); if ( !m_bIsDataValid ) return false;
int nScoreListHeight = scores.Count() * m_yEntryStep; int nScrollerWidth, nScrollerHeight; m_pScoreListScroller->GetSize( nScrollerWidth, nScrollerHeight );
m_pScoreList->SetSize( nScrollerWidth, Max( nScoreListHeight, nScrollerHeight ) );
m_pScoreList->InvalidateLayout( true ); m_pScoreListScroller->InvalidateLayout( true ); m_pScoreListScroller->GetScrollbar()->InvalidateLayout( true ); static int nScrollWidth = m_pScoreListScroller->GetScrollbar()->GetWide(); m_pScoreListScroller->GetScrollbar()->SetWide( nScrollWidth>>1 ); if ( m_pScoreListScroller->GetScrollbar()->GetButton( 0 ) && m_pScoreListScroller->GetScrollbar()->GetButton( 1 ) ) { m_pScoreListScroller->GetScrollbar()->GetButton( 0 )->SetVisible( false ); m_pScoreListScroller->GetScrollbar()->GetButton( 1 )->SetVisible( false ); }
FOR_EACH_VEC( m_vecLeaderboardEntries, i ) { EditablePanel *pContainer = dynamic_cast< EditablePanel* >( m_vecLeaderboardEntries[i] ); if ( !pContainer ) continue;
Color colorToUse = i % 2 == 1 ? m_OddTextColor : m_EvenTextColor;
bool bIsEntryVisible = i < scores.Count(); pContainer->SetVisible( bIsEntryVisible ); pContainer->SetPos( 0, i * m_yEntryStep ); if ( bIsEntryVisible ) { const LeaderboardEntry_t *pLeaderboardEntry = scores[i]; const CSteamID &steamID = pLeaderboardEntry->m_steamIDUser;
#ifdef TWITCH_LEADERBOARD
TwitchTvAccountInfo_t *pTwitchInfo = StreamManager()->GetTwitchTvAccountInfo( steamID.ConvertToUint64() ); ETwitchTvState_t twitchState = pTwitchInfo ? pTwitchInfo->m_eTwitchTvState : k_ETwitchTvState_Error; // still waiting for twitch info to load
if ( twitchState <= k_ETwitchTvState_Loading ) return false; #endif // TWITCH_LEADERBOARD
bool bIsLocalPlayer = steamapicontext && steamapicontext->SteamUser() && steamapicontext->SteamUser()->GetSteamID() == steamID; pContainer->SetDialogVariable( "position", m_bGlobal ? CFmtStr( "%d.", pLeaderboardEntry->m_nGlobalRank ) : "" ); pContainer->SetDialogVariable( "username", InventoryManager()->PersonaName_Get( steamID.GetAccountID() ) );
CExLabel *pNameText = dynamic_cast< CExLabel* >( pContainer->FindChildByName( "UserName" ) ); if ( pNameText ) { pNameText->SetColorStr( bIsLocalPlayer ? m_LocalPlayerTextColor : colorToUse ); }
CAvatarImagePanel *pAvatar = dynamic_cast< CAvatarImagePanel* >( pContainer->FindChildByName( "AvatarImage" ) ); if ( pAvatar ) { pAvatar->SetShouldDrawFriendIcon( false ); pAvatar->SetPlayer( steamID, k_EAvatarSize32x32 ); }
CTFBadgePanel *pRankImage = dynamic_cast< CTFBadgePanel* >( pContainer->FindChildByName( "RankImage" ) ); if ( pRankImage ) { const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( k_nMatchGroup_Ladder_6v6 ); const LevelInfo_t& levelInfo = pMatchDesc->m_pProgressionDesc->GetLevelForExperience( pLeaderboardEntry->m_nScore ); pRankImage->SetupBadge( pMatchDesc->m_pProgressionDesc, levelInfo );
wchar_t wszOutString[ 128 ]; char szLocalized[512]; wchar_t wszCount[ 16 ]; _snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", levelInfo.m_nLevelNum ); const wchar_t *wpszFormat = g_pVGuiLocalize->Find( pMatchDesc->m_pProgressionDesc->m_pszLevelToken ); g_pVGuiLocalize->ConstructString_safe( wszOutString, wpszFormat, 2, wszCount, g_pVGuiLocalize->Find( levelInfo.m_pszLevelTitle ) ); g_pVGuiLocalize->ConvertUnicodeToANSI( wszOutString, szLocalized, sizeof( szLocalized ) );
pRankImage->SetMouseInputEnabled( true ); pRankImage->SetVisible( true ); pRankImage->SetTooltip( m_pToolTip, szLocalized ); }
CExImageButton *pStreamImage = dynamic_cast< CExImageButton* >( pContainer->FindChildByName( "StreamImageButton" ) ); if ( pStreamImage ) { #ifdef TWITCH_LEADERBOARD
if ( twitchState == k_ETwitchTvState_Linked ) { pStreamImage->SetVisible( true ); pStreamImage->SetCommand( CFmtStr( "stream %s", pTwitchInfo->m_sTwitchTvChannel.String() ) ); } else #endif // TWITCH_LEADERBOARD
{ pStreamImage->SetVisible( false ); pStreamImage->SetCommand( "" ); } } } }
return true; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLadderLobbyLeaderboard::SetLeaderboard( const char *pszLeaderboardName, bool bGlobal ) { m_pszLeaderboardName = pszLeaderboardName; m_bGlobal = bGlobal;
UpdateLeaderboards(); }
static void GetPlayerNameForSteamID( wchar_t *wCharPlayerName, int nBufSizeBytes, const CSteamID &steamID ) { const char *pszName = steamapicontext->SteamFriends()->GetFriendPersonaName( steamID ); V_UTF8ToUnicode( pszName, wCharPlayerName, nBufSizeBytes ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CLobbyPanel_Comp::CLobbyPanel_Comp( vgui::Panel *pParent, CBaseLobbyContainerFrame* pLobbyContainer ) : CBaseLobbyPanel( pParent, pLobbyContainer ) , m_pCompetitiveModeLeaderboard( NULL ) , m_pMatchHistoryScroller( NULL ) , m_eMatchSortMethod( SORT_BY_DATE ) , m_bDescendingMatchHistorySort( true ) { // Comp
m_fontMedalsCount = 0;
m_flCompetitiveRankProgress = -1.f; m_flCompetitiveRankPrevProgress = -1.f; m_flRefreshPlayerListTime = -1.f; m_bCompetitiveRankChangePlayedSound = false; m_bMatchHistoryLoaded = false; m_bMatchDataForLocalPlayerDirty = true;
ListenForGameEvent( "gc_new_session" ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CLobbyPanel_Comp::~CLobbyPanel_Comp() { delete m_pImageList; m_pImageList = NULL; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::OnCommand( const char *command ) {
if ( FStrEq( command, "medals_help" ) ) { CExplanationPopup *pPopup = dynamic_cast< CExplanationPopup* >( GetParent()->FindChildByName( "MedalsHelp" ) ); if ( pPopup ) { pPopup->Popup(); } return; } else if ( FStrEq( command, "show_leaderboards" ) ) { if ( m_pCompetitiveModeLeaderboard ) { m_pCompetitiveModeLeaderboard->SetVisible( true ); } SetControlVisible( "MatchHistoryCategories", false, true ); SetControlVisible( "MatchHistoryContainer", false, true );
return; } else if ( FStrEq( command, "show_match_history" ) ) { m_bMatchDataForLocalPlayerDirty = true;
if ( m_pCompetitiveModeLeaderboard ) { m_pCompetitiveModeLeaderboard->SetVisible( false ); }
SetControlVisible( "MatchHistoryCategories", true, true ); SetControlVisible( "MatchHistoryContainer", true, true ); return; } else if ( !Q_strncmp( "sort", command, 4 ) ) { EMatchHistorySortMethods_t eNewMethod = (EMatchHistorySortMethods_t)atoi( command + 4 );
if ( eNewMethod == m_eMatchSortMethod ) { m_bDescendingMatchHistorySort = !m_bDescendingMatchHistorySort; } else { m_eMatchSortMethod = eNewMethod; m_bDescendingMatchHistorySort = true; }
m_bMatchDataForLocalPlayerDirty = true;
return; }
BaseClass::OnCommand( command ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CLobbyPanel_Comp::ShouldShowLateJoin() const { return false; // For now
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::ApplyChatUserSettings( const CBaseLobbyPanel::LobbyPlayerInfo &player, KeyValues *pKV ) const { pKV->SetInt( "has_ticket", 0 ); pKV->SetInt( "squad_surplus", 0 ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::WriteGameSettingsControls() { BaseClass::WriteGameSettingsControls();
// Make sure we want to be in matchmaking. (If we don't, the frame should hide us pretty quickly.)
// We might get an event or something right at the transition point occasionally when the UI should
// not be visible
if ( GTFGCClientSystem()->GetMatchmakingUIState() == eMatchmakingUIState_Inactive ) { return; }
++m_iWritingPanel;
m_pContainer->SetNextButtonEnabled( true );
SetControlVisible( "ScrollableContainer", GTFGCClientSystem()->GetWizardStep()== TF_Matchmaking_WizardStep_LADDER ); --m_iWritingPanel; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CLobbyPanel_Comp::GetMedalCountForStat( EMatchGroup unLadderType, RankStatType_t nStatType, int nMedalLevel ) { CSOTFLadderData *pData = GetLocalPlayerLadderData( unLadderType ); if ( !pData ) return 0;
switch ( nStatType ) { case RankStat_Score: if ( nMedalLevel == StatMedal_Bronze ) { return pData->Obj().score_bronze(); } else if ( nMedalLevel == StatMedal_Silver ) { return pData->Obj().score_silver(); } else if ( nMedalLevel == StatMedal_Gold ) { return pData->Obj().score_gold(); } break; case RankStat_Kills: if ( nMedalLevel == StatMedal_Bronze ) { return pData->Obj().kills_bronze(); } else if ( nMedalLevel == StatMedal_Silver ) { return pData->Obj().kills_silver(); } else if ( nMedalLevel == StatMedal_Gold ) { return pData->Obj().kills_gold(); } break; case RankStat_Damage: if ( nMedalLevel == StatMedal_Bronze ) { return pData->Obj().damage_bronze(); } else if ( nMedalLevel == StatMedal_Silver ) { return pData->Obj().damage_silver(); } else if ( nMedalLevel == StatMedal_Gold ) { return pData->Obj().damage_gold(); } break; case RankStat_Healing: if ( nMedalLevel == StatMedal_Bronze ) { return pData->Obj().healing_bronze(); } else if ( nMedalLevel == StatMedal_Silver ) { return pData->Obj().healing_silver(); } else if ( nMedalLevel == StatMedal_Gold ) { return pData->Obj().healing_gold(); } break; case RankStat_Support: if ( nMedalLevel == StatMedal_Bronze ) { return pData->Obj().support_bronze(); } else if ( nMedalLevel == StatMedal_Silver ) { return pData->Obj().support_silver(); } else if ( nMedalLevel == StatMedal_Gold ) { return pData->Obj().support_gold(); } break; case RankStat_Deaths: // Not supported
break; default: Assert( 0 ); }
return 0; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::OnThink() { BaseClass::OnThink();
if ( m_bMatchDataForLocalPlayerDirty ) { UpdateMatchDataForLocalPlayer(); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::FireGameEvent( IGameEvent *event ) { const char *pszEventname = event->GetName(); if ( !Q_stricmp( pszEventname, "gc_new_session" ) ) { // This is loaded on demand by the GC - if we have a new session, we need to re-request
if ( m_bMatchHistoryLoaded ) { m_bMatchHistoryLoaded = false; m_bMatchDataForLocalPlayerDirty = true; } }
BaseClass::FireGameEvent( event ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
EMatchGroup CLobbyPanel_Comp::GetMatchGroup( void ) const { return k_nMatchGroup_Ladder_6v6; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::SOCreated( const CSteamID & steamIDOwner, const CSharedObject *pObject, ESOCacheEvent eEvent ) { if ( pObject->GetTypeID() != CSOTFMatchResultPlayerInfo::k_nTypeID ) return;
m_bMatchDataForLocalPlayerDirty = true; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::SOUpdated( const CSteamID & steamIDOwner, const CSharedObject *pObject, ESOCacheEvent eEvent ) { if ( pObject->GetTypeID() != CSOTFMatchResultPlayerInfo::k_nTypeID ) return;
m_bMatchDataForLocalPlayerDirty = true; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::PerformLayout() { BaseClass::PerformLayout();
m_bMatchDataForLocalPlayerDirty = true; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLobbyPanel_Comp::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme );
EditablePanel* pPlaylistBGPanel = FindControl< EditablePanel >( "PlaylistBGPanel", true ); m_pCompetitiveModeLeaderboard = pPlaylistBGPanel->FindControl< CLadderLobbyLeaderboard >( "Leaderboard", true );
m_pMatchHistoryScroller = pPlaylistBGPanel->FindControl< CScrollableList >( "MatchHistoryContainer" );
int nAvatarWidth = ( ( m_iAvatarWidth * 5 / 4 ) + 1 ); int nExtraWidth = ( m_pChatPlayerList->GetWide() - ( 2 * nAvatarWidth ) - m_iPlayerNameWidth - m_iBannedWidth - m_iHasPassWidth );
m_pChatPlayerList->AddColumnToSection( 0, "avatar", "#TF_Players", vgui::SectionedListPanel::COLUMN_IMAGE, nAvatarWidth ); m_pChatPlayerList->AddColumnToSection( 0, "name", "", 0, m_iPlayerNameWidth + nExtraWidth ); m_pChatPlayerList->AddColumnToSection( 0, "is_banned", "", vgui::SectionedListPanel::COLUMN_IMAGE | vgui::SectionedListPanel::COLUMN_CENTER, m_iBannedWidth ); m_pChatPlayerList->AddColumnToSection( 0, "has_competitive_access", "", vgui::SectionedListPanel::COLUMN_IMAGE | vgui::SectionedListPanel::COLUMN_CENTER, m_iHasPassWidth ); m_pChatPlayerList->AddColumnToSection( 0, "rank", "", vgui::SectionedListPanel::COLUMN_IMAGE | vgui::SectionedListPanel::COLUMN_CENTER, nAvatarWidth ); m_pChatPlayerList->SetDrawHeaders( false ); m_fontMedalsCount = pScheme->GetFont( "HudFontSmallestBold", true ); }
static int SortResult( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ) { return a->display_rating_change() < b->display_rating_change(); }
static int SortDate( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ) { return a->endtime() < b->endtime(); }
static int SortMap( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ) { const MapDef_t* pMapDef = GetItemSchema()->GetMasterMapDefByIndex( a->map_index() ); const wchar_t* pszAMapName = g_pVGuiLocalize->Find( pMapDef ? pMapDef->pszMapNameLocKey : "#TF_Map_Unknown" );
pMapDef = GetItemSchema()->GetMasterMapDefByIndex( b->map_index() ); const wchar_t* pszBMapName = g_pVGuiLocalize->Find( pMapDef ? pMapDef->pszMapNameLocKey : "#TF_Map_Unknown" );
return wcscoll( pszAMapName, pszBMapName ); }
static int SortKDR( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ) { float flAKDRatio = a->kills(); if ( a->deaths() > 0 ) { flAKDRatio /= (float)a->deaths(); }
float flBKDRatio = b->kills(); if ( b->deaths() > 0 ) { flBKDRatio /= (float)b->deaths(); }
return ( flBKDRatio - flAKDRatio ) * 1000.f; }
void CLobbyPanel_Comp::UpdateMatchDataForLocalPlayer() { m_bMatchDataForLocalPlayerDirty = false;
CUtlVector < CSOTFMatchResultPlayerStats > vecMatches; GetLocalPlayerMatchHistory( GetMatchGroup(), vecMatches );
if ( !m_bMatchHistoryLoaded ) { GCSDK::CProtoBufMsg< CMsgGCMatchHistoryLoad > msg( k_EMsgGCMatchHistoryLoad ); GCClientSystem()->BSendMessage( msg );
m_bMatchHistoryLoaded = true; }
if ( m_pMatchHistoryScroller ) { m_pMatchHistoryScroller->ClearAutoLayoutPanels();
typedef int (*MatchSortFunc)( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b );
struct SortMethodData_t { MatchSortFunc m_pfnSort; CExButton* m_pSortButton; };
EditablePanel* pPlaylistBGPanel = FindControl< EditablePanel >( "PlaylistBGPanel", true ); Assert( pPlaylistBGPanel ); if ( !pPlaylistBGPanel ) return;
SortMethodData_t sortMethods[ NUM_SORT_METHODS ] = { { &SortResult, pPlaylistBGPanel->FindControl< CExButton >( "ResultButton", true ) } , { &SortDate, pPlaylistBGPanel->FindControl< CExButton >( "DateButton", true ) } , { &SortMap, pPlaylistBGPanel->FindControl< CExButton >( "MapButton", true ) } , { &SortKDR, pPlaylistBGPanel->FindControl< CExButton >( "KDRButton", true ) } };
// Sort
vecMatches.Sort( sortMethods[ m_eMatchSortMethod ].m_pfnSort );
Label* pSortArrow = pPlaylistBGPanel->FindControl< Label >( "SortArrow", true ); Assert( pSortArrow ); if ( !pSortArrow ) return;
// Update controls
for( int i=0; i<ARRAYSIZE( sortMethods ); ++i ) { if( sortMethods[ i ].m_pSortButton ) { bool bSelected = i == m_eMatchSortMethod; sortMethods[ i ].m_pSortButton->SetSelected( bSelected );
if ( bSelected ) { int nDummy, nX; sortMethods[ i ].m_pSortButton->GetContentSize( nX, nDummy ); // Move the sort arrow to the right edge of the selected panel
pSortArrow->SetPos( sortMethods[ i ].m_pSortButton->GetXPos() + nX , pSortArrow->GetYPos() ); // Fixup the label to be an up or down arrow
pSortArrow->SetText( m_bDescendingMatchHistorySort ? L"6" : L"5" ); } } }
// Potentially go backwards
if ( m_bDescendingMatchHistorySort ) { FOR_EACH_VEC( vecMatches, i ) { CMatchHistoryEntryPanel* pMatchEntryPanel = new CMatchHistoryEntryPanel( m_pMatchHistoryScroller, "MatchEntry" ); pMatchEntryPanel->MakeReadyForUse(); pMatchEntryPanel->SetMatchData( vecMatches[ i ] ); m_pMatchHistoryScroller->AddPanel( pMatchEntryPanel, 5 ); } } else { FOR_EACH_VEC_BACK( vecMatches, i ) { CMatchHistoryEntryPanel* pMatchEntryPanel = new CMatchHistoryEntryPanel( m_pMatchHistoryScroller, "MatchEntry" ); pMatchEntryPanel->MakeReadyForUse(); pMatchEntryPanel->SetMatchData( vecMatches[ i ] ); m_pMatchHistoryScroller->AddPanel( pMatchEntryPanel, 5 ); } }
m_pMatchHistoryScroller->MakeReadyForUse(); } }
|