Team Fortress 2 Source Code as on 22/4/2020
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.

621 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "tf_party.h"
  8. #include "vgui_controls/PropertySheet.h"
  9. #include "vgui_controls/ScrollableEditablePanel.h"
  10. #include "iclientmode.h"
  11. #include <vgui_controls/AnimationController.h>
  12. #include "tf_lobbypanel_casual.h"
  13. #include "tf_lobby_container_frame_casual.h"
  14. #include "tf_matchmaking_shared.h"
  15. #include "tf_hud_mainmenuoverride.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include <tier0/memdbgon.h>
  18. extern Color s_colorChallengeForegroundEnabled;
  19. extern Color s_colorChallengeForegroundDisabled;
  20. extern Color s_colorChallengeHeader;
  21. extern const char *s_pszMatchGroups[];
  22. ConVar tf_show_maps_details_explanation_session( "tf_show_maps_details_explanation_session", "0", FCVAR_HIDDEN );
  23. ConVar tf_show_maps_details_explanation_count( "tf_show_maps_details_explanation_count", "2", FCVAR_ARCHIVE | FCVAR_HIDDEN );
  24. class CLobbyPanel_Casual;
  25. class CCasualCategory : public CExpandablePanel
  26. {
  27. DECLARE_CLASS_SIMPLE( CCasualCategory, CExpandablePanel );
  28. public:
  29. CCasualCategory( Panel *parent, const char *panelName, EGameCategory eCategory, Panel* pSignalHandler )
  30. : BaseClass( parent, panelName )
  31. , m_eCategory( eCategory )
  32. , pToggleButton( NULL )
  33. , m_mapMapPanels( DefLessFunc( uint32 ) )
  34. , m_pSignalHandler( pSignalHandler )
  35. {}
  36. ~CCasualCategory()
  37. {
  38. // Clear out the old map entries
  39. ClearMapEntries();
  40. }
  41. virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE
  42. {
  43. BaseClass::ApplySchemeSettings( pScheme );
  44. LoadControlSettings( "resource/ui/MatchmakingCategoryPanel.res" );
  45. const SchemaGameCategory_t* pCategory = GetItemSchema()->GetGameCategory( m_eCategory );
  46. Assert( pCategory );
  47. if ( !pCategory )
  48. return;
  49. EditablePanel* pTopContainer = FindControl< EditablePanel >( "TopContainer", true );
  50. if ( pTopContainer )
  51. {
  52. // Set our dialog variables
  53. pTopContainer->SetDialogVariable( "title_token", g_pVGuiLocalize->Find( pCategory->m_pszLocalizedName ) );
  54. pTopContainer->SetDialogVariable( "desc_token", g_pVGuiLocalize->Find( pCategory->m_pszLocalizedDesc ) );
  55. }
  56. ImagePanel* pImagePanel = FindControl< ImagePanel >( "BGImage", true );
  57. if ( pImagePanel && pCategory && pCategory->m_pszListImage )
  58. {
  59. pImagePanel->SetImage( pCategory->m_pszListImage );
  60. }
  61. // Clear out the old map entries
  62. ClearMapEntries();
  63. EditablePanel* pMapsContainer = FindControl< EditablePanel >( "MapsContainer", true );
  64. if ( pMapsContainer )
  65. {
  66. int nYPos = 16;
  67. FOR_EACH_VEC( pCategory->m_vecEnabledMaps, i )
  68. {
  69. const MapDef_t* pMap = pCategory->m_vecEnabledMaps[ i ];
  70. // Load control settings
  71. EditablePanel* pMapEntry = new EditablePanel( pMapsContainer, "MatchmakingCategoryMapPanel" );
  72. pMapEntry->LoadControlSettings( "resource/ui/MatchmakingCategoryMapPanel.res" );
  73. pMapEntry->SetAutoDelete( false );
  74. CExCheckButton* pCheckButton = pMapEntry->FindControl< CExCheckButton >( "MapCheckbutton" );
  75. if ( pCheckButton )
  76. {
  77. KeyValues* pKVData = new KeyValues( "data" );
  78. pKVData->SetInt( "map_index", pMap->m_nDefIndex );
  79. pCheckButton->SetData( pKVData );
  80. pCheckButton->AddActionSignalTarget( m_pSignalHandler );
  81. }
  82. // Add to map so we can look it up
  83. m_mapMapPanels.Insert( pMap->m_nDefIndex, pMapEntry );
  84. // Update label
  85. pMapEntry->SetDialogVariable( "title_token", g_pVGuiLocalize->Find( pMap->pszMapNameLocKey ) );
  86. bool bOdd = i % 2 == 1;
  87. int nXPos = bOdd ? GetWide() * 0.5f : 0;
  88. pMapEntry->SetPos( nXPos, nYPos );
  89. nYPos += bOdd || i == pCategory->m_vecEnabledMaps.Count() - 1 ? pMapEntry->GetTall() : 0;
  90. }
  91. pMapsContainer->SetTall( nYPos + 10 );
  92. pMapsContainer->SetAutoResize( PIN_BOTTOMRIGHT, Panel::AUTORESIZE_NO, 0, 0, 0, 0 );
  93. // We want to be able to expand to this height
  94. m_nExpandedHeight = nYPos + m_nCollapsedHeight;
  95. }
  96. // Snag the button for later
  97. pToggleButton = FindControl< CExImageButton >( "EntryToggleButton", true );
  98. }
  99. virtual void OnToggleCollapse( bool bIsExpanded ) OVERRIDE
  100. {
  101. if ( bIsExpanded && !tf_show_maps_details_explanation_session.GetBool() && tf_show_maps_details_explanation_count.GetInt() > 0 )
  102. {
  103. tf_show_maps_details_explanation_count.SetValue( tf_show_maps_details_explanation_count.GetInt() - 1 );
  104. tf_show_maps_details_explanation_session.SetValue( true );
  105. // I dont care anymore
  106. GetParent()->GetParent()->GetParent()->GetParent()->GetParent()->GetParent()->OnCommand( "show_maps_details_explanation" );
  107. }
  108. BaseClass::OnToggleCollapse( bIsExpanded );
  109. }
  110. virtual void PerformLayout() OVERRIDE
  111. {
  112. BaseClass::PerformLayout();
  113. SetControlVisible( "EntryToggleButtonCollapsed", !BIsExpanded(), true );
  114. SetControlVisible( "EntryToggleButtonExpanded", BIsExpanded(), true );
  115. if ( pToggleButton )
  116. {
  117. pToggleButton->SetImageArmed( BIsExpanded() ? "/pve/sell_selected" : "/pve/buy_selected" );
  118. pToggleButton->SetImageDefault( BIsExpanded() ? "/pve/sell_disabled" : "/pve/buy_disabled" );
  119. }
  120. // Update progress bars
  121. FOR_EACH_MAP_FAST( m_mapMapPanels, i )
  122. {
  123. int nMapIndex = m_mapMapPanels.Key( i );
  124. auto healthData = GTFGCClientSystem()->GetHealthDataForMap( nMapIndex );
  125. // Update bars with latest health data
  126. ProgressBar* pProgress = m_mapMapPanels[ i ]->FindControl< ProgressBar >( "HealthProgressBar", true );
  127. if ( pProgress )
  128. {
  129. pProgress->SetProgress( healthData.m_flRatio );
  130. pProgress->SetFgColor( healthData.m_colorBar );
  131. }
  132. }
  133. }
  134. void SetCheckButtonState( uint32 nMapDefIndex, bool bSelected, bool bClickable )
  135. {
  136. auto idx = m_mapMapPanels.Find( nMapDefIndex );
  137. if ( idx != m_mapMapPanels.InvalidIndex() )
  138. {
  139. EditablePanel* pMapEntry = m_mapMapPanels[ idx ];
  140. CExCheckButton* pMapCheckButton = pMapEntry->FindControl< CExCheckButton >( "MapCheckbutton", true );
  141. if ( pMapCheckButton )
  142. {
  143. // Update button state without sending signals
  144. pMapCheckButton->SetSilentMode( true );
  145. pMapCheckButton->SetCheckButtonCheckable( true );
  146. pMapCheckButton->SetSelected( bSelected );
  147. pMapCheckButton->SetCheckButtonCheckable( bClickable );
  148. pMapCheckButton->SetSilentMode( false );
  149. }
  150. if ( g_pClientMode && g_pClientMode->GetViewport() )
  151. {
  152. if ( bSelected )
  153. {
  154. g_pClientMode->GetViewportAnimationController()->StopAnimationSequence( pMapEntry, "HealthProgressBar_NotSelected" );
  155. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( pMapEntry, "HealthProgressBar_Selected" );
  156. }
  157. else
  158. {
  159. g_pClientMode->GetViewportAnimationController()->StopAnimationSequence( pMapEntry, "HealthProgressBar_Selected" );
  160. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( pMapEntry, "HealthProgressBar_NotSelected" );
  161. }
  162. }
  163. }
  164. }
  165. private:
  166. void ClearMapEntries()
  167. {
  168. // Clear out the old map entries
  169. FOR_EACH_MAP_FAST( m_mapMapPanels, i )
  170. {
  171. m_mapMapPanels[ i ]->MarkForDeletion();
  172. }
  173. m_mapMapPanels.Purge();
  174. }
  175. const EGameCategory m_eCategory;
  176. CExImageButton* pToggleButton;
  177. Panel* m_pSignalHandler;
  178. CUtlMap< uint32, EditablePanel* > m_mapMapPanels;
  179. };
  180. static void GetPlayerNameForSteamID( wchar_t *wCharPlayerName, int nBufSizeBytes, const CSteamID &steamID )
  181. {
  182. const char *pszName = steamapicontext->SteamFriends()->GetFriendPersonaName( steamID );
  183. V_UTF8ToUnicode( pszName, wCharPlayerName, nBufSizeBytes );
  184. }
  185. CLobbyPanel_Casual::CLobbyPanel_Casual( vgui::Panel *pParent, CBaseLobbyContainerFrame* pLobbyContainer )
  186. : CBaseLobbyPanel( pParent, pLobbyContainer )
  187. , m_fontCategoryListItem( 0 )
  188. , m_fontGroupHeader( 0 )
  189. , m_flCompetitiveRankProgress( -1.f )
  190. , m_flCompetitiveRankPrevProgress( -1.f )
  191. , m_flRefreshPlayerListTime( -1.f )
  192. , m_bCompetitiveRankChangePlayedSound( false )
  193. , m_mapGroupPanels( DefLessFunc( EMatchmakingGroupType ) )
  194. , m_mapCategoryPanels( DefLessFunc( EGameCategory ) )
  195. , m_flNextCasualStatsUpdateTime( 0.f )
  196. , m_bCriteriaDirty( true )
  197. {
  198. GTFGCClientSystem()->LoadCasualSearchCriteria();
  199. ListenForGameEvent( "matchmaker_stats_updated" );
  200. }
  201. CLobbyPanel_Casual::~CLobbyPanel_Casual()
  202. {
  203. delete m_pImageList;
  204. m_pImageList = NULL;
  205. }
  206. bool CLobbyPanel_Casual::ShouldShowLateJoin() const
  207. {
  208. return false; // We force the option on, so no need to show the checkbox
  209. }
  210. void CLobbyPanel_Casual::ApplyChatUserSettings( const CBaseLobbyPanel::LobbyPlayerInfo &player, KeyValues *pKV ) const
  211. {
  212. pKV->SetInt( "has_ticket", 0 );
  213. pKV->SetInt( "squad_surplus", 0 );
  214. }
  215. void CLobbyPanel_Casual::WriteGameSettingsControls()
  216. {
  217. BaseClass::WriteGameSettingsControls();
  218. // Make sure we want to be in matchmaking. (If we don't, the frame should hide us pretty quickly.)
  219. // We might get an event or something right at the transition point occasionally when the UI should
  220. // not be visible
  221. if ( GTFGCClientSystem()->GetMatchmakingUIState() == eMatchmakingUIState_Inactive )
  222. {
  223. return;
  224. }
  225. ++m_iWritingPanel;
  226. TF_Matchmaking_WizardStep eWizardStep = GTFGCClientSystem()->GetWizardStep();
  227. m_bCriteriaDirty = true;
  228. // competitive
  229. SetControlVisible( "GameModesContainer", eWizardStep == TF_Matchmaking_WizardStep_CASUAL );
  230. --m_iWritingPanel;
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Purpose:
  234. //-----------------------------------------------------------------------------
  235. EMatchGroup CLobbyPanel_Casual::GetMatchGroup( void ) const
  236. {
  237. return k_nMatchGroup_Casual_12v12; // Force to 12v12 for now
  238. }
  239. //-----------------------------------------------------------------------------
  240. // Purpose:
  241. //-----------------------------------------------------------------------------
  242. void CLobbyPanel_Casual::OnThink()
  243. {
  244. BaseClass::OnThink();
  245. if ( Plat_FloatTime() > m_flNextCasualStatsUpdateTime )
  246. {
  247. m_flNextCasualStatsUpdateTime = Plat_FloatTime() + 60.f;
  248. GTFGCClientSystem()->RequestMatchMakerStats();
  249. }
  250. if ( m_bCriteriaDirty )
  251. {
  252. WriteCategories();
  253. }
  254. }
  255. void CLobbyPanel_Casual::FireGameEvent( IGameEvent *event )
  256. {
  257. if ( FStrEq( event->GetName(), "matchmaker_stats_updated" ) )
  258. {
  259. m_bCriteriaDirty = true;
  260. return;
  261. }
  262. BaseClass::FireGameEvent( event );
  263. }
  264. //-----------------------------------------------------------------------------
  265. void CLobbyPanel_Casual::PerformLayout()
  266. {
  267. BaseClass::PerformLayout();
  268. CHudMainMenuOverride *pMMOverride = (CHudMainMenuOverride*)( gViewPortInterface->FindPanelByName( PANEL_MAINMENUOVERRIDE ) );
  269. if ( pMMOverride )
  270. {
  271. CLobbyContainerFrame_Casual *pCasualFrame = pMMOverride->GetCasualLobbyPanel();
  272. if ( pCasualFrame )
  273. {
  274. CMainMenuToolTip *pToolTip = pCasualFrame->GetTooltipPanel();
  275. if ( pToolTip )
  276. {
  277. CExImageButton *pButton = FindControl<CExImageButton>( "RestoreCasualSearchCriteria", true );
  278. if ( pButton )
  279. {
  280. pButton->SetTooltip( pToolTip, "#TF_Casual_Tip_Restore" );
  281. }
  282. pButton = FindControl<CExImageButton>( "SaveCasualSearchCriteria", true );
  283. if ( pButton )
  284. {
  285. pButton->SetTooltip( pToolTip, "#TF_Casual_Tip_Save" );
  286. }
  287. }
  288. }
  289. }
  290. }
  291. //-----------------------------------------------------------------------------
  292. void CLobbyPanel_Casual::ApplySchemeSettings( vgui::IScheme *pScheme )
  293. {
  294. m_mapGroupPanels.Purge();
  295. m_mapCategoryPanels.Purge();
  296. BaseClass::ApplySchemeSettings( pScheme );
  297. int nAvatarWidth = ( ( m_iAvatarWidth * 5 / 4 ) + 1 );
  298. int nExtraWidth = ( m_pChatPlayerList->GetWide() - ( 2 * nAvatarWidth ) - m_iPlayerNameWidth - m_iBannedWidth );
  299. m_pChatPlayerList->AddColumnToSection( 0, "avatar", "#TF_Players", vgui::SectionedListPanel::COLUMN_IMAGE, nAvatarWidth );
  300. m_pChatPlayerList->AddColumnToSection( 0, "name", "", 0, m_iPlayerNameWidth + nExtraWidth );
  301. m_pChatPlayerList->AddColumnToSection( 0, "is_banned", "", vgui::SectionedListPanel::COLUMN_IMAGE | vgui::SectionedListPanel::COLUMN_CENTER, m_iBannedWidth );
  302. m_pChatPlayerList->AddColumnToSection( 0, "rank", "", vgui::SectionedListPanel::COLUMN_IMAGE | vgui::SectionedListPanel::COLUMN_CENTER, nAvatarWidth );
  303. m_pChatPlayerList->SetDrawHeaders( false );
  304. m_fontCategoryListItem = pScheme->GetFont( "HudFontSmallest", true );
  305. m_fontGroupHeader = pScheme->GetFont( "HudFontSmallestBold", true );
  306. }
  307. void SelectCategory( EGameCategory eCategory, bool bSelected )
  308. {
  309. auto pCat = GetItemSchema()->GetGameCategory( eCategory );
  310. if ( pCat )
  311. {
  312. FOR_EACH_VEC( pCat->m_vecEnabledMaps, i )
  313. {
  314. if ( pCat->m_vecEnabledMaps[ i ] )
  315. {
  316. GTFGCClientSystem()->SelectCasualMap( pCat->m_vecEnabledMaps[ i ]->m_nDefIndex, bSelected );
  317. }
  318. }
  319. }
  320. }
  321. void SelectGroup( EMatchmakingGroupType eGroup, bool bSelected )
  322. {
  323. auto pGroup = GetItemSchema()->GetMMGroup( eGroup );
  324. if ( pGroup )
  325. {
  326. FOR_EACH_VEC( pGroup->m_vecModes, i )
  327. {
  328. SelectCategory( pGroup->m_vecModes[ i ]->m_eGameCategory, bSelected );
  329. }
  330. }
  331. }
  332. //-----------------------------------------------------------------------------
  333. // Purpose: A check box got checked! Search criteria
  334. //-----------------------------------------------------------------------------
  335. void CLobbyPanel_Casual::OnCheckButtonChecked( vgui::Panel* panel )
  336. {
  337. if ( m_iWritingPanel > 0 )
  338. return;
  339. CExCheckButton* pCheckButton = dynamic_cast< CExCheckButton* >( panel );
  340. if ( pCheckButton )
  341. {
  342. bool bSelected = pCheckButton->IsSelected();
  343. pCheckButton->RemoveActionSignalTarget( this );
  344. pCheckButton->SetSelected( false );
  345. pCheckButton->AddActionSignalTarget( this );
  346. if ( BIsPartyLeader() && BIsPartyInUIState() )
  347. {
  348. int nMapIndex = pCheckButton->GetData()->GetInt( "map_index", -1 );
  349. int nCategoryIndex = pCheckButton->GetData()->GetInt( "category_index", -1 );
  350. int nGroupIndex = pCheckButton->GetData()->GetInt( "group_index", -1 );
  351. Assert( nCategoryIndex >= 0 || nGroupIndex >= 0 || nMapIndex >= 0 );
  352. if ( nGroupIndex >= 0 )
  353. {
  354. EMatchmakingGroupType eGroup = EMatchmakingGroupType( nGroupIndex );
  355. SelectGroup( eGroup, bSelected );
  356. }
  357. else if ( nCategoryIndex >= 0 )
  358. {
  359. EGameCategory eCategory = EGameCategory( nCategoryIndex );
  360. SelectCategory( eCategory, bSelected );
  361. }
  362. else if ( nMapIndex >= 0 )
  363. {
  364. GTFGCClientSystem()->SelectCasualMap( nMapIndex, bSelected );
  365. }
  366. }
  367. m_bCriteriaDirty = true;
  368. }
  369. BaseClass::OnCheckButtonChecked( panel );
  370. }
  371. //-----------------------------------------------------------------------------
  372. // Purpose: Write all the category controls settings
  373. //-----------------------------------------------------------------------------
  374. void CLobbyPanel_Casual::WriteCategories( void )
  375. {
  376. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
  377. if ( !m_bCriteriaDirty )
  378. return;
  379. m_bCriteriaDirty = false;
  380. bool bLeader = BIsPartyLeader();
  381. bool bInUIState = BIsPartyInUIState();
  382. bool bClickable = bLeader && bInUIState;
  383. m_bHasAMapSelected = false;
  384. CScrollableList* pScrollableList = FindControl< CScrollableList >( "GameModesList", true );
  385. if ( !pScrollableList )
  386. return;
  387. CUtlVector< const MapDef_t* > vecSelectedMaps;
  388. pScrollableList->SetMouseInputEnabled( true );
  389. const MMGroupMap_t& mapMMGroups = GetItemSchema()->GetMMGroupMap();
  390. int nCategory = 0;
  391. // Go through every MM group, and create a label for it and all its categories underneath
  392. FOR_EACH_MAP( mapMMGroups, i )
  393. {
  394. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - FOR_EACH_MAP( mapMMGroups, i )", __FUNCTION__ );
  395. const SchemaMMGroup_t* pCat = mapMMGroups[ i ];
  396. if ( !pCat->m_bitsValidMMGroups.IsBitSet( GetMatchGroup() ) )
  397. {
  398. continue;
  399. }
  400. if ( !pCat->IsCategoryValid() )
  401. {
  402. continue;
  403. }
  404. ++nCategory;
  405. bool bGroupSelected = false;
  406. EditablePanel* pGroupPanel = NULL;
  407. CExCheckButton* pTitleLabel = NULL;
  408. auto idx = m_mapGroupPanels.Find( pCat->m_eMMGroup );
  409. // Create the check button/label if not created yet
  410. if ( idx == m_mapGroupPanels.InvalidIndex() )
  411. {
  412. pGroupPanel = new EditablePanel( pScrollableList, "MatchmakingGroupPanel" );
  413. pGroupPanel->LoadControlSettings( "resource/ui/MatchMakingGroupPanel.res" );
  414. pTitleLabel = pGroupPanel->FindControl< CExCheckButton >( "Checkbutton" );
  415. pTitleLabel->SetText( pCat->m_pszLocalizedName );
  416. KeyValues* pKVData = new KeyValues( "data" );
  417. pKVData->SetInt( "group_index", pCat->m_eMMGroup );
  418. pTitleLabel->SetData( pKVData );
  419. pScrollableList->AddPanel( pGroupPanel, nCategory > 1 ? 2 : -4 );
  420. m_mapGroupPanels.Insert( pCat->m_eMMGroup, pGroupPanel );
  421. }
  422. else
  423. {
  424. pGroupPanel = (EditablePanel*)m_mapGroupPanels[ idx ];
  425. pTitleLabel = pGroupPanel->FindControl< CExCheckButton >( "Checkbutton" );
  426. }
  427. // Category items.
  428. FOR_EACH_VEC( pCat->m_vecModes, j )
  429. {
  430. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - FOR_EACH_VEC( pCat->m_vecModes, j )", __FUNCTION__ );
  431. const SchemaGameCategory_t* pCategory = pCat->m_vecModes[ j ];
  432. if ( !pCategory->PassesRestrictions() )
  433. {
  434. continue;
  435. }
  436. CCasualCategory* pListEntry = NULL;
  437. auto idxCat = m_mapCategoryPanels.Find( pCategory->m_eGameCategory );
  438. // Create the entry if it doesnt exist yet
  439. if ( idxCat == m_mapCategoryPanels.InvalidIndex() )
  440. {
  441. pListEntry = new CCasualCategory( pScrollableList, "MatchmakingCategoryPanel", pCategory->m_eGameCategory, this );
  442. pListEntry->MakeReadyForUse();
  443. pScrollableList->AddPanel( pListEntry, j > 0 ? 5 : 0 );
  444. m_mapCategoryPanels.Insert( pCategory->m_eGameCategory, pListEntry );
  445. }
  446. else
  447. {
  448. pListEntry = (CCasualCategory*)m_mapCategoryPanels[ idxCat ];
  449. }
  450. bool bCatSelected = false;
  451. FOR_EACH_VEC( pCategory->m_vecEnabledMaps, k )
  452. {
  453. bool bMapSelected = GTFGCClientSystem()->IsCasualMapSelected( pCategory->m_vecEnabledMaps[ k ]->m_nDefIndex );
  454. m_bHasAMapSelected |= bMapSelected;
  455. bCatSelected = bCatSelected | bMapSelected;
  456. bGroupSelected = bGroupSelected | bCatSelected;
  457. // Update map check button state
  458. pListEntry->SetCheckButtonState( pCategory->m_vecEnabledMaps[ k ]->m_nDefIndex, bMapSelected, bLeader );
  459. // We're going to use this to setup the tooltip for total selected maps
  460. if ( bMapSelected )
  461. {
  462. vecSelectedMaps.AddToTail( pCategory->m_vecEnabledMaps[ k ] );
  463. }
  464. }
  465. if ( bCatSelected )
  466. {
  467. g_pClientMode->GetViewportAnimationController()->StopAnimationSequence( pListEntry, "CasualCategory_NotSelected" );
  468. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( pListEntry, "CasualCategory_Selected" );
  469. }
  470. else
  471. {
  472. g_pClientMode->GetViewportAnimationController()->StopAnimationSequence( pListEntry, "CasualCategory_Selected" );
  473. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( pListEntry, "CasualCategory_NotSelected" );
  474. }
  475. pListEntry->InvalidateLayout();
  476. // Update the check button within the list entry
  477. CExCheckButton* pCheckButton = pListEntry->FindControl< CExCheckButton >( "CheckButton", true );
  478. if ( pCheckButton )
  479. {
  480. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - if ( pCheckButton )", __FUNCTION__ );
  481. pCheckButton->RemoveActionSignalTarget( this ); // So we dont endlessly loop by checking
  482. pCheckButton->SetCheckButtonCheckable( true ); // So we can potentially check it on the next line
  483. pCheckButton->SetSelected( bCatSelected );
  484. pCheckButton->SetCheckButtonCheckable( bLeader );
  485. pCheckButton->AddActionSignalTarget( this ); // So that we get user check messages
  486. KeyValues* pKVData = new KeyValues( "data" );
  487. pKVData->SetInt( "category_index", pCategory->m_eGameCategory );
  488. pCheckButton->SetData( pKVData );
  489. pCheckButton->SetMouseInputEnabled( bClickable );
  490. }
  491. }
  492. // Update check button state
  493. pTitleLabel->RemoveActionSignalTarget( this );
  494. pTitleLabel->SetCheckButtonCheckable( true );
  495. pTitleLabel->SetSelected( bGroupSelected );
  496. pTitleLabel->SetCheckButtonCheckable( bLeader );
  497. pTitleLabel->AddActionSignalTarget( this );
  498. pGroupPanel->SetMouseInputEnabled( bClickable );
  499. pTitleLabel->SetMouseInputEnabled( bClickable ); // Update clickability
  500. }
  501. EditablePanel* pPlayListPanel = FindControl< EditablePanel >( "PlaylistBGPanel", true );
  502. if ( pPlayListPanel )
  503. {
  504. // Setup the "X maps selected" label
  505. const char* pszToken = vecSelectedMaps.Count() == 1 ? "TF_Casual_SelectedMaps_Singular" : "TF_Casual_SelectedMaps_Plural";
  506. pPlayListPanel->SetDialogVariable( "selected_maps_count", LocalizeNumberWithToken( pszToken, vecSelectedMaps.Count() ) );
  507. }
  508. m_pContainer->SetNextButtonEnabled( m_bHasAMapSelected );
  509. }