summaryrefslogtreecommitdiff
path: root/game/client/cstrike/VGUI/achievements_page.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/cstrike/VGUI/achievements_page.cpp')
-rw-r--r--game/client/cstrike/VGUI/achievements_page.cpp1061
1 files changed, 1061 insertions, 0 deletions
diff --git a/game/client/cstrike/VGUI/achievements_page.cpp b/game/client/cstrike/VGUI/achievements_page.cpp
new file mode 100644
index 0000000..bc6036e
--- /dev/null
+++ b/game/client/cstrike/VGUI/achievements_page.cpp
@@ -0,0 +1,1061 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Display a list of achievements for the current game
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "achievements_page.h"
+#include "vgui_controls/Button.h"
+#include "vgui/ILocalize.h"
+#include "ixboxsystem.h"
+#include "iachievementmgr.h"
+#include "filesystem.h"
+#include "vgui_controls/ImagePanel.h"
+#include "vgui_controls/ComboBox.h"
+#include "vgui_controls/CheckButton.h"
+#include "fmtstr.h"
+#include "c_cs_playerresource.h"
+#include "stat_card.h"
+#include <vgui/IInput.h>
+
+#include "../../../public/steam/steam_api.h"
+#include "achievementmgr.h"
+#include "../../../../public/vgui/IScheme.h"
+#include "../vgui_controls/ScrollBar.h"
+#include "achievements_cs.h"
+
+extern CAchievementMgr g_AchievementMgrCS;
+
+using namespace vgui;
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+KeyValues *g_pPreloadedCSAchievementPageItemLayout = NULL;
+KeyValues *g_pPreloadedCSAchievementPageGroupLayout = NULL;
+
+// Shared helper functions so xbox and pc can share as much code as possible while coming from different bases.
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the parameter pIconPanel to display the specified achievement's icon file.
+//-----------------------------------------------------------------------------
+bool CSLoadAchievementIconForPage( vgui::ImagePanel* pIconPanel, CCSBaseAchievement* pAchievement, const char *pszExt /*= NULL*/ )
+{
+ char imagePath[_MAX_PATH];
+ Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) );
+ Q_strncat( imagePath, pAchievement->GetName(), sizeof(imagePath), COPY_ALL_CHARACTERS );
+ if ( pszExt )
+ {
+ Q_strncat( imagePath, pszExt, sizeof(imagePath), COPY_ALL_CHARACTERS );
+ }
+ Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS );
+
+ char checkFile[_MAX_PATH];
+ Q_snprintf( checkFile, sizeof(checkFile), "materials\\vgui\\%s", imagePath );
+ if ( !g_pFullFileSystem->FileExists( checkFile ) )
+ {
+ Q_snprintf( imagePath, sizeof(imagePath), "hud\\icon_locked.vtf" );
+ }
+
+ pIconPanel->SetShouldScaleImage( true );
+ pIconPanel->SetImage( imagePath );
+ pIconPanel->SetVisible( true );
+
+ return pIconPanel->IsVisible();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the parameter pIconPanel to display the specified achievement's icon file.
+//-----------------------------------------------------------------------------
+bool CSLoadIconForPage( vgui::ImagePanel* pIconPanel, const char* pFilename, const char *pszExt /*= NULL*/ )
+{
+ char imagePath[_MAX_PATH];
+ Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) );
+ Q_strncat( imagePath, pFilename, sizeof(imagePath), COPY_ALL_CHARACTERS );
+ if ( pszExt )
+ {
+ Q_strncat( imagePath, pszExt, sizeof(imagePath), COPY_ALL_CHARACTERS );
+ }
+ Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS );
+
+ char checkFile[_MAX_PATH];
+ Q_snprintf( checkFile, sizeof(checkFile), "materials\\vgui\\%s", imagePath );
+ if ( !g_pFullFileSystem->FileExists( checkFile ) )
+ {
+ Q_snprintf( imagePath, sizeof(imagePath), "hud\\icon_locked.vtf" );
+ }
+
+ pIconPanel->SetShouldScaleImage( true );
+ pIconPanel->SetImage( imagePath );
+ pIconPanel->SetVisible( true );
+
+ return pIconPanel->IsVisible();
+}
+
+//-----------------------------------------------------------------------------
+// The bias is to ensure the percentage bar gets plenty orange before it reaches the text,
+// as the white-on-grey is hard to read.
+//-----------------------------------------------------------------------------
+Color CSLerpColorsForPage ( Color cStart, Color cEnd, float flPercent )
+{
+ float r = (float)((float)(cStart.r()) + (float)(cEnd.r() - cStart.r()) * Bias( flPercent, 0.75 ) );
+ float g = (float)((float)(cStart.g()) + (float)(cEnd.g() - cStart.g()) * Bias( flPercent, 0.75 ) );
+ float b = (float)((float)(cStart.b()) + (float)(cEnd.b() - cStart.b()) * Bias( flPercent, 0.75 ) );
+ float a = (float)((float)(cStart.a()) + (float)(cEnd.a() - cStart.a()) * Bias( flPercent, 0.75 ) );
+ return Color( r, g, b, a );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Shares common percentage bar calculations/color settings between xbox and pc.
+// Not really intended for robustness or reuse across many panels.
+// Input : pFrame - assumed to have certain child panels (see below)
+// *pAchievement - source achievement to poll for progress. Non progress achievements will not show a percentage bar.
+//-----------------------------------------------------------------------------
+void CSUpdateProgressBarForPage( vgui::EditablePanel* pPanel, CCSBaseAchievement* pAchievement, Color clrProgressBar )
+{
+ ///*
+ if ( pAchievement->GetGoal() > 1 )
+ {
+ bool bShowProgress = true;
+
+ // if this achievement gets saved with game and we're not in a level and have not achieved it, then we do not have any state
+ // for this achievement, don't show progress
+ if ( ( pAchievement->GetFlags() & ACH_SAVE_WITH_GAME ) && /*!GameUI().IsInLevel() &&*/ !pAchievement->IsAchieved() )
+ {
+ bShowProgress = false;
+ }
+
+ float flCompletion = 0.0f;
+
+ // Once achieved, we can't rely on count. If they've completed the achievement just set to 100%.
+ int iCount = pAchievement->GetCount();
+ if ( pAchievement->IsAchieved() )
+ {
+ flCompletion = 1.0f;
+ iCount = pAchievement->GetGoal();
+ }
+ else if ( bShowProgress )
+ {
+ flCompletion = ( ((float)pAchievement->GetCount()) / ((float)pAchievement->GetGoal()) );
+ // In rare cases count can exceed goal and not be achieved (switch local storage on X360, take saved game from different user on PC).
+ // These will self-correct with continued play, but if we're in that state don't show more than 100% achieved.
+ flCompletion = MIN( flCompletion, 1.0 );
+ }
+
+ char szPercentageText[ 256 ] = "";
+ if ( bShowProgress )
+ {
+ Q_snprintf( szPercentageText, 256, "%d/%d", iCount, pAchievement->GetGoal() );
+ }
+
+ pPanel->SetControlString( "PercentageText", szPercentageText );
+ pPanel->SetControlVisible( "PercentageText", true );
+ pPanel->SetControlVisible( "CompletionText", true );
+
+ vgui::ImagePanel *pPercentageBar = (vgui::ImagePanel*)pPanel->FindChildByName( "PercentageBar" );
+ vgui::ImagePanel *pPercentageBarBkg = (vgui::ImagePanel*)pPanel->FindChildByName( "PercentageBarBackground" );
+
+ if ( pPercentageBar && pPercentageBarBkg )
+ {
+ pPercentageBar->SetFillColor( clrProgressBar );
+ pPercentageBar->SetWide( pPercentageBarBkg->GetWide() * flCompletion );
+
+ pPanel->SetControlVisible( "PercentageBarBackground", IsX360() ? bShowProgress : true );
+ pPanel->SetControlVisible( "PercentageBar", true );
+ }
+ }
+ //*/
+}
+
+// TODO: revisit this once other games are rebuilt using the updated IAchievement interface
+bool CSGameSupportsAchievementTrackerForPage()
+{
+ const char *pGame = Q_UnqualifiedFileName( engine->GetGameDirectory() );
+ return ( !Q_stricmp( pGame, "cstrike" ) );
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PC Implementation
+//////////////////////////////////////////////////////////////////////////
+
+
+
+int AchivementSortPredicate( CCSBaseAchievement* const* pLeft, CCSBaseAchievement* const* pRight )
+{
+ if ( (*pLeft)->IsAchieved() && !(*pRight)->IsAchieved() )
+ return -1;
+
+ if ( !(*pLeft)->IsAchieved() && (*pRight)->IsAchieved() )
+ return 1;
+
+ if ( (*pLeft)->GetAchievementID() < (*pRight)->GetAchievementID() )
+ return -1;
+
+ if ( (*pLeft)->GetAchievementID() > (*pRight)->GetAchievementID() )
+ return 1;
+
+ return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: creates child panels, passes down name to pick up any settings from res files.
+//-----------------------------------------------------------------------------
+CAchievementsPage::CAchievementsPage(vgui::Panel *parent, const char *name) : BaseClass(parent, "CSAchievementsDialog")
+{
+ m_iFixedWidth = 900; // Give this an initial value in order to set a proper size
+ SetBounds(0, 0, 900, 780);
+ SetMinimumSize( 256, 780 );
+
+ m_pStatCard = new StatCard(this, "ignored");
+
+ m_pAchievementsList = new vgui::PanelListPanel( this, "listpanel_achievements" );
+ m_pAchievementsList->SetFirstColumnWidth( 0 );
+
+ m_pGroupsList = new vgui::PanelListPanel( this, "listpanel_groups" );
+ m_pGroupsList->SetFirstColumnWidth( 0 );
+
+ m_pListBG = new vgui::ImagePanel( this, "listpanel_background" );
+
+ m_pPercentageBarBackground = SETUP_PANEL( new ImagePanel( this, "PercentageBarBackground" ) );
+ m_pPercentageBar = SETUP_PANEL( new ImagePanel( this, "PercentageBar" ) );
+
+ ListenForGameEvent( "player_stats_updated" );
+ ListenForGameEvent( "achievement_earned_local" );
+
+ // int that holds the highest number achievement id we've found
+ int iHighestAchievementIDSeen = -1;
+ int iNextGroupBoundary = 1000;
+
+ Q_memset( m_AchievementGroups, 0, sizeof(m_AchievementGroups) );
+ m_iNumAchievementGroups = 0;
+
+ // Base groups
+ int iCount = g_AchievementMgrCS.GetAchievementCount();
+ for ( int i = 0; i < iCount; ++i )
+ {
+ CCSBaseAchievement* pAchievement = dynamic_cast<CCSBaseAchievement*>(g_AchievementMgrCS.GetAchievementByIndex( i ));
+
+ if ( !pAchievement )
+ continue;
+
+ int iAchievementID = pAchievement->GetAchievementID();
+
+ if ( iAchievementID > iHighestAchievementIDSeen )
+ {
+ // if it's crossed the next group boundary, create a new group
+ if ( iAchievementID >= iNextGroupBoundary )
+ {
+ int iNewGroupBoundary = iAchievementID;
+ CreateNewAchievementGroup( iNewGroupBoundary, iNewGroupBoundary+99 );
+
+ iNextGroupBoundary = iNewGroupBoundary + 100;
+ }
+
+ iHighestAchievementIDSeen = iAchievementID;
+ }
+ }
+
+ LoadControlSettings("resource/ui/CSAchievementsDialog.res");
+ UpdateTotalProgressDisplay();
+ CreateOrUpdateComboItems( true );
+
+ // Default display shows the first achievement group
+ UpdateAchievementList(1001, 1100);
+
+ m_bStatsDirty = true;
+ m_bAchievementsDirty = true;
+}
+
+CAchievementsPage::~CAchievementsPage()
+{
+ g_AchievementMgrCS.SaveGlobalStateIfDirty( false ); // check for saving here to store achievements we want pinned to HUD
+
+ m_pAchievementsList->DeleteAllItems();
+ delete m_pAchievementsList;
+ delete m_pPercentageBarBackground;
+ delete m_pPercentageBar;
+}
+
+void CAchievementsPage::CreateNewAchievementGroup( int iMinRange, int iMaxRange )
+{
+ m_AchievementGroups[m_iNumAchievementGroups].m_iMinRange = iMinRange;
+ m_AchievementGroups[m_iNumAchievementGroups].m_iMaxRange = iMaxRange;
+ m_iNumAchievementGroups++;
+}
+
+//----------------------------------------------------------
+// Get the width we're going to lock at
+//----------------------------------------------------------
+void CAchievementsPage::ApplySettings( KeyValues *pResourceData )
+{
+ m_iFixedWidth = pResourceData->GetInt( "wide", 512 );
+
+ BaseClass::ApplySettings( pResourceData );
+}
+
+//----------------------------------------------------------
+// Preserve our width to the one in the .res file
+//----------------------------------------------------------
+void CAchievementsPage::OnSizeChanged(int newWide, int newTall)
+{
+ // Lock the width, but allow height scaling
+ if ( newWide != m_iFixedWidth )
+ {
+ SetSize( m_iFixedWidth, newTall );
+ return;
+ }
+
+ BaseClass::OnSizeChanged(newWide, newTall);
+}
+
+//----------------------------------------------------------
+// Re-populate the achievement list with the selected group
+//----------------------------------------------------------
+void CAchievementsPage::UpdateAchievementList(CAchievementsPageGroupPanel* groupPanel)
+{
+ if (!groupPanel)
+ return;
+
+ UpdateAchievementList( groupPanel->GetFirstAchievementID(), groupPanel->GetLastAchievementID() );
+
+ vgui::IScheme *pGroupScheme = scheme()->GetIScheme( GetScheme() );
+
+ // Update active status for button display
+ for (int i = 0; i < m_pGroupsList->GetItemCount(); i++)
+ {
+ CAchievementsPageGroupPanel *pPanel = (CAchievementsPageGroupPanel*)m_pGroupsList->GetItemPanel(i);
+ if ( pPanel )
+ {
+ if ( pPanel != groupPanel )
+ {
+ pPanel->SetGroupActive( false );
+ }
+ else
+ {
+ pPanel->SetGroupActive( true );
+ }
+
+ pPanel->UpdateAchievementInfo( pGroupScheme );
+ }
+ }
+}
+
+void CAchievementsPage::UpdateTotalProgressDisplay()
+{
+ // Set up total completion percentage bar
+ float flCompletion = 0.0f;
+
+ int iCount = g_AchievementMgrCS.GetAchievementCount();
+ int nUnlocked = 0;
+
+ if ( iCount > 0 )
+ {
+ for ( int i = 0; i < iCount; ++i )
+ {
+ CCSBaseAchievement* pAchievement = dynamic_cast<CCSBaseAchievement*>(g_AchievementMgrCS.GetAchievementByIndex( i ));
+
+ if ( pAchievement && pAchievement->IsAchieved() )
+ ++nUnlocked;
+ }
+
+ flCompletion = (((float)nUnlocked) / ((float)g_AchievementMgrCS.GetAchievementCount()));
+ }
+
+ char szPercentageText[64];
+ V_sprintf_safe( szPercentageText, "%d / %d",
+ nUnlocked, g_AchievementMgrCS.GetAchievementCount() );
+
+ SetControlString( "PercentageText", szPercentageText );
+ SetControlVisible( "PercentageText", true );
+ SetControlVisible( "CompletionText", true );
+
+ vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
+
+ Color clrHighlight = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) );
+ Color clrWhite(255, 255, 255, 255);
+
+ Color cProgressBar = Color( static_cast<float>( clrHighlight.r() ) * ( 1.0f - flCompletion ) + static_cast<float>( clrWhite.r() ) * flCompletion,
+ static_cast<float>( clrHighlight.g() ) * ( 1.0f - flCompletion ) + static_cast<float>( clrWhite.g() ) * flCompletion,
+ static_cast<float>( clrHighlight.b() ) * ( 1.0f - flCompletion ) + static_cast<float>( clrWhite.b() ) * flCompletion,
+ static_cast<float>( clrHighlight.a() ) * ( 1.0f - flCompletion ) + static_cast<float>( clrWhite.a() ) * flCompletion );
+
+ m_pPercentageBar->SetFgColor( cProgressBar );
+ m_pPercentageBar->SetWide( m_pPercentageBarBackground->GetWide() * flCompletion );
+
+ SetControlVisible( "PercentageBarBackground", true );
+ SetControlVisible( "PercentageBar", true );
+}
+
+//----------------------------------------------------------
+// Re-populate the achievement list with the selected group
+//----------------------------------------------------------
+void CAchievementsPage::UpdateAchievementList(int minID, int maxID)
+{
+ int iMinRange = minID;
+ int iMaxRange = maxID;
+
+ int iCount = g_AchievementMgrCS.GetAchievementCount();
+
+ CUtlVector<CCSBaseAchievement*> sortedAchivementList;
+ sortedAchivementList.EnsureCapacity(iCount);
+
+ for ( int i = 0; i < iCount; ++i )
+ {
+ CCSBaseAchievement* pAchievement = dynamic_cast<CCSBaseAchievement*>(g_AchievementMgrCS.GetAchievementByIndex(i));
+
+ if ( !pAchievement )
+ continue;
+
+ int iAchievementID = pAchievement->GetAchievementID();
+
+ if ( iAchievementID < iMinRange || iAchievementID > iMaxRange )
+ continue;
+
+ // don't show hidden achievements if not achieved
+ if ( pAchievement->ShouldHideUntilAchieved() && !pAchievement->IsAchieved() )
+ continue;
+
+ sortedAchivementList.AddToTail(pAchievement);
+ }
+
+ sortedAchivementList.Sort(AchivementSortPredicate);
+
+ m_pAchievementsList->DeleteAllItems();
+
+ FOR_EACH_VEC(sortedAchivementList, i)
+ {
+ CCSBaseAchievement* pAchievement = sortedAchivementList[i];
+
+ CAchievementsPageItemPanel *pAchievementItemPanel = new CAchievementsPageItemPanel( m_pAchievementsList, "AchievementDialogItemPanel");
+ pAchievementItemPanel->SetAchievementInfo(pAchievement);
+
+ // force all our new panel to have the correct internal layout and size so that our parent container can layout properly
+ pAchievementItemPanel->InvalidateLayout(true, true);
+
+ m_pAchievementsList->AddItem( NULL, pAchievementItemPanel );
+ }
+
+ m_pAchievementsList->MoveScrollBarToTop();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Loads settings from achievementsdialog.res in hl2/resource/ui/
+// Sets up progress bar displaying total achievement unlocking progress by the user.
+//-----------------------------------------------------------------------------
+void CAchievementsPage::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ m_pGroupsList->SetBgColor(Color(86,86,86,255));
+
+ SetBgColor(Color(86,86,86,255));
+
+ // Set text color for percentage
+ Panel *pPanel;
+ pPanel = FindChildByName("PercentageText");
+ if (pPanel)
+ {
+ pPanel->SetFgColor(Color(157, 194, 80, 255));
+ }
+
+ // Set text color for achievement earned label
+ pPanel = FindChildByName("AchievementsEarnedLabel");
+ if (pPanel)
+ {
+ pPanel->SetFgColor(Color(157, 194, 80, 255));
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Each sub-panel gets its data updated
+//-----------------------------------------------------------------------------
+void CAchievementsPage::UpdateAchievementDialogInfo( void )
+{
+ // Hide the group list scrollbar
+ if (m_pGroupsList->GetScrollbar())
+ {
+ m_pGroupsList->GetScrollbar()->SetWide(0);
+ }
+
+ int iCount = m_pAchievementsList->GetItemCount();
+ vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
+
+ int i;
+ for ( i = 0; i < iCount; i++ )
+ {
+ CAchievementsPageItemPanel *pPanel = (CAchievementsPageItemPanel*)m_pAchievementsList->GetItemPanel(i);
+ if ( pPanel )
+ {
+ pPanel->UpdateAchievementInfo( pScheme );
+ }
+ }
+
+ // Update all group panels
+ int iGroupCount = m_pGroupsList->GetItemCount();
+ for ( i = 0; i < iGroupCount; i++ )
+ {
+ CAchievementsPageGroupPanel *pPanel = (CAchievementsPageGroupPanel*)m_pGroupsList->GetItemPanel(i);
+ if ( pPanel )
+ {
+ pPanel->UpdateAchievementInfo( pScheme );
+
+ if ( pPanel->IsGroupActive() )
+ {
+ UpdateAchievementList( pPanel );
+ }
+ }
+ }
+
+ // update the groups and overall progress bar
+ CreateOrUpdateComboItems( false ); // update them with new achieved counts
+
+ UpdateTotalProgressDisplay();
+
+ m_pStatCard->UpdateInfo();
+
+ m_bAchievementsDirty = false;
+ m_bStatsDirty = false;
+}
+
+void CAchievementsPage::CreateOrUpdateComboItems( bool bCreate )
+{
+ // Build up achievement group names
+ for ( int i=0;i<m_iNumAchievementGroups;i++ )
+ {
+ char buf[128];
+
+ int achievementRangeStart = (m_AchievementGroups[i].m_iMinRange / 1000) * 1000;
+ Q_snprintf( buf, sizeof(buf), "#Achievement_Group_%d", achievementRangeStart );
+
+ wchar_t *wzGroupName = g_pVGuiLocalize->Find( buf );
+
+ if ( !wzGroupName )
+ {
+ wzGroupName = L"Need Title ( %s1 of %s2 )";
+ }
+
+ wchar_t wzGroupTitle[128];
+
+ if ( wzGroupName )
+ {
+ // Determine number of achievements in the group which have been awarded
+ int numAwarded = 0;
+ int numTested = 0;
+ for (int j = m_AchievementGroups[i].m_iMinRange; j < m_AchievementGroups[i].m_iMaxRange; j++)
+ {
+ IAchievement* pCur = g_AchievementMgrCS.GetAchievementByID( j );
+
+ if ( !pCur )
+ continue;
+
+ numTested++;
+
+ if ( pCur->IsAchieved() )
+ {
+ numAwarded++;
+ }
+ }
+
+ wchar_t wzNumUnlocked[8];
+ V_snwprintf( wzNumUnlocked, ARRAYSIZE( wzNumUnlocked ), L"%d", numAwarded );
+
+ wchar_t wzNumAchievements[8];
+ V_snwprintf( wzNumAchievements, ARRAYSIZE( wzNumAchievements ), L"%d", numTested );
+
+ g_pVGuiLocalize->ConstructString( wzGroupTitle, sizeof( wzGroupTitle ), wzGroupName, 0 );
+ }
+
+ KeyValues *pKV = new KeyValues( "grp" );
+ pKV->SetInt( "minrange", m_AchievementGroups[i].m_iMinRange );
+ pKV->SetInt( "maxrange", m_AchievementGroups[i].m_iMaxRange );
+
+ if ( bCreate )
+ {
+ // Create an achievement group instance
+ CAchievementsPageGroupPanel *achievementGroupPanel = new CAchievementsPageGroupPanel( m_pGroupsList, this, "AchievementDialogGroupPanel", i );
+ achievementGroupPanel->SetGroupInfo( wzGroupTitle, m_AchievementGroups[i].m_iMinRange, m_AchievementGroups[i].m_iMaxRange );
+
+ if (i == 0)
+ {
+ achievementGroupPanel->SetGroupActive(true);
+ }
+ else
+ {
+ achievementGroupPanel->SetGroupActive(false);
+ }
+
+ m_pGroupsList->AddItem( NULL, achievementGroupPanel );
+ }
+ }
+
+ m_pStatCard->UpdateInfo();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: creates child panels, passes down name to pick up any settings from res files.
+//-----------------------------------------------------------------------------
+CAchievementsPageItemPanel::CAchievementsPageItemPanel( vgui::PanelListPanel *parent, const char* name) : BaseClass( parent, name )
+{
+ m_pParent = parent;
+ m_pSchemeSettings = NULL;
+
+ m_pAchievementIcon = SETUP_PANEL(new vgui::ImagePanel( this, "AchievementIcon" ));
+ m_pAchievementNameLabel = new vgui::Label( this, "AchievementName", "name" );
+ m_pAchievementDescLabel = new vgui::Label( this, "AchievementDesc", "desc" );
+ m_pPercentageBar = SETUP_PANEL( new ImagePanel( this, "PercentageBar" ) );
+ m_pPercentageText = new vgui::Label( this, "PercentageText", "" );
+ m_pAwardDate = new vgui::Label( this, "AwardDate", "date" );
+ m_pShowOnHUDButton = new vgui::CheckButton( this, "ShowOnHudToggle", "" );
+ m_pShowOnHUDButton->SetMouseInputEnabled( true );
+ m_pShowOnHUDButton->SetEnabled( true );
+ m_pShowOnHUDButton->SetCheckButtonCheckable( true );
+ m_pShowOnHUDButton->AddActionSignalTarget( this );
+
+ m_pHiddenHUDToggleButton = new CHiddenHUDToggleButton( this, "HiddenHUDToggle", "" );
+ m_pHiddenHUDToggleButton->SetPaintBorderEnabled( false );
+
+
+ SetMouseInputEnabled( true );
+ parent->SetMouseInputEnabled( true );
+}
+
+CAchievementsPageItemPanel::~CAchievementsPageItemPanel()
+{
+ delete m_pAchievementIcon;
+ delete m_pAchievementNameLabel;
+ delete m_pAchievementDescLabel;
+ delete m_pPercentageBar;
+ delete m_pPercentageText;
+ delete m_pAwardDate;
+ delete m_pShowOnHUDButton;
+ delete m_pHiddenHUDToggleButton;
+}
+
+void CAchievementsPageItemPanel::ToggleShowOnHUDButton()
+{
+ if (m_pShowOnHUDButton)
+ {
+ m_pShowOnHUDButton->SetSelected( !m_pShowOnHUDButton->IsSelected() );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates displayed achievement data. In applyschemesettings, and when gameui activates.
+//-----------------------------------------------------------------------------
+void CAchievementsPageItemPanel::UpdateAchievementInfo( vgui::IScheme* pScheme )
+{
+ if ( m_pSourceAchievement && m_pSchemeSettings )
+ {
+ //=============================================================================
+ // HPE_BEGIN:
+ // [dwenger] Get achievement name and description text from the localized file
+ //=============================================================================
+
+ // Set name, description and unlocked state text
+ m_pAchievementNameLabel->SetText( ACHIEVEMENT_LOCALIZED_NAME( m_pSourceAchievement ) );
+ m_pAchievementDescLabel->SetText( ACHIEVEMENT_LOCALIZED_DESC( m_pSourceAchievement ) );
+
+ //=============================================================================
+ // HPE_END
+ //=============================================================================
+
+ // Setup icon
+ // get the vtfFilename from the path.
+
+ // Display percentage completion for progressive achievements
+ // Set up total completion percentage bar. Goal > 1 means its a progress achievement.
+ CSUpdateProgressBarForPage( this, m_pSourceAchievement, m_clrProgressBar );
+
+ if ( m_pSourceAchievement->IsAchieved() )
+ {
+ CSLoadAchievementIconForPage( m_pAchievementIcon, m_pSourceAchievement );
+
+ SetBgColor( pScheme->GetColor( "AchievementsLightGrey", Color(255, 0, 0, 255) ) );
+
+ m_pAchievementNameLabel->SetFgColor( pScheme->GetColor( "SteamLightGreen", Color(255, 255, 255, 255) ) );
+
+ Color fgColor = pScheme->GetColor( "Label.TextBrightColor", Color(255, 255, 255, 255) );
+ m_pAchievementDescLabel->SetFgColor( fgColor );
+ m_pPercentageText->SetFgColor( fgColor );
+ m_pShowOnHUDButton->SetVisible( false );
+ m_pShowOnHUDButton->SetSelected( false );
+ m_pHiddenHUDToggleButton->SetVisible( false );
+ m_pAwardDate->SetVisible( true );
+ m_pAwardDate->SetFgColor( pScheme->GetColor( "SteamLightGreen", Color(255, 255, 255, 255) ) );
+
+ // Assign the award date text
+ int year, month, day, hour, minute, second;
+ if ( m_pSourceAchievement->GetAwardTime(year, month, day, hour, minute, second) )
+ {
+ char dateBuffer[32] = "";
+ Q_snprintf( dateBuffer, 32, "%4d-%02d-%02d", year, month, day );
+ m_pAwardDate->SetText( dateBuffer );
+ }
+ else
+ m_pAwardDate->SetText( "" );
+ }
+ else
+ {
+ CSLoadAchievementIconForPage( m_pAchievementIcon, m_pSourceAchievement, "_bw" );
+
+ SetBgColor( pScheme->GetColor( "AchievementsDarkGrey", Color(255, 0, 0, 255) ) );
+
+ Color fgColor = pScheme->GetColor( "AchievementsInactiveFG", Color(255, 255, 255, 255) );
+ m_pAchievementNameLabel->SetFgColor( fgColor );
+ m_pAchievementDescLabel->SetFgColor( fgColor );
+ m_pPercentageText->SetFgColor( fgColor );
+
+ if ( CSGameSupportsAchievementTrackerForPage() )
+ {
+ m_pShowOnHUDButton->SetVisible( !m_pSourceAchievement->ShouldHideUntilAchieved() );
+ m_pShowOnHUDButton->SetSelected( m_pSourceAchievement->ShouldShowOnHUD() );
+
+ m_pHiddenHUDToggleButton->SetVisible( !m_pSourceAchievement->ShouldHideUntilAchieved() );
+ }
+ else
+ {
+ m_pShowOnHUDButton->SetVisible( false );
+ m_pHiddenHUDToggleButton->SetVisible( false );
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Makes a local copy of a pointer to the achievement entity stored on the client.
+//-----------------------------------------------------------------------------
+void CAchievementsPageItemPanel::SetAchievementInfo( CCSBaseAchievement* pAchievement )
+{
+ if ( !pAchievement )
+ {
+ Assert( 0 );
+ return;
+ }
+
+ m_pSourceAchievement = pAchievement;
+ m_iSourceAchievementIndex = pAchievement->GetAchievementID();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CAchievementsPageItemPanel::PreloadResourceFile( void )
+{
+ const char *controlResourceName = "resource/ui/AchievementItem.res";
+
+ g_pPreloadedCSAchievementPageItemLayout = new KeyValues(controlResourceName);
+ g_pPreloadedCSAchievementPageItemLayout->LoadFromFile(g_pFullFileSystem, controlResourceName);
+
+/*
+ // precache all achievement icons
+ int iCount = g_AchievementMgrCS.GetAchievementCount();
+ for ( int i = 0; i < iCount; ++i )
+ {
+ CCSBaseAchievement* pAchievement = dynamic_cast<CCSBaseAchievement*>(g_AchievementMgrCS.GetAchievementByIndex( i ));
+ char imagePath[_MAX_PATH];
+
+ Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) );
+ Q_strncat( imagePath, pAchievement->GetName(), sizeof(imagePath), COPY_ALL_CHARACTERS );
+ Q_strncat( imagePath, "_bw", sizeof(imagePath), COPY_ALL_CHARACTERS );
+ Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS );
+
+ scheme()->GetImage(imagePath, true);
+
+ Q_strncpy( imagePath, "achievements\\", sizeof(imagePath) );
+ Q_strncat( imagePath, pAchievement->GetName(), sizeof(imagePath), COPY_ALL_CHARACTERS );
+ Q_strncat( imagePath, ".vtf", sizeof(imagePath), COPY_ALL_CHARACTERS );
+
+ scheme()->GetImage(imagePath, true);
+ }
+*/
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Loads settings from hl2/resource/ui/achievementitem.res
+// Sets display info for this achievement item.
+//-----------------------------------------------------------------------------
+void CAchievementsPageItemPanel::ApplySchemeSettings( vgui::IScheme* pScheme )
+{
+ if ( !g_pPreloadedCSAchievementPageItemLayout )
+ {
+ PreloadResourceFile();
+ }
+
+ LoadControlSettings( "", NULL, g_pPreloadedCSAchievementPageItemLayout );
+
+ m_pSchemeSettings = pScheme;
+
+ if ( !m_pSourceAchievement )
+ {
+ return;
+ }
+
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ // m_pSchemeSettings must be set for this.
+ UpdateAchievementInfo( pScheme );
+}
+
+void CAchievementsPageItemPanel::OnCheckButtonChecked(Panel *panel)
+{
+ if ( CSGameSupportsAchievementTrackerForPage() && panel == m_pShowOnHUDButton && m_pSourceAchievement )
+ {
+ m_pSourceAchievement->SetShowOnHUD( m_pShowOnHUDButton->IsSelected() );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: creates child panels, passes down name to pick up any settings from res files.
+//-----------------------------------------------------------------------------
+CAchievementsPageGroupPanel::CAchievementsPageGroupPanel( vgui::PanelListPanel *parent, CAchievementsPage *owner, const char* name, int iListItemID ) : BaseClass( parent, name )
+{
+ m_pParent = parent;
+ m_pOwner = owner;
+ m_pSchemeSettings = NULL;
+
+ m_pGroupIcon = SETUP_PANEL(new vgui::ImagePanel( this, "GroupIcon" ));
+ m_pAchievementGroupLabel = new vgui::Label( this, "GroupName", "name" );
+ m_pPercentageText = new vgui::Label( this, "GroupPercentageText", "1/1" );
+ m_pPercentageBar = SETUP_PANEL( new ImagePanel( this, "GroupPercentageBar" ) );
+ m_pGroupButton = new CGroupButton( this, "GroupButton", "" );
+ m_pGroupButton->SetPos( 0, 0 );
+ m_pGroupButton->SetZPos( 20 );
+ m_pGroupButton->SetWide( 256 );
+ m_pGroupButton->SetTall( 64 );
+ SetMouseInputEnabled( true );
+ parent->SetMouseInputEnabled( true );
+
+ m_bActiveButton = false;
+}
+
+CAchievementsPageGroupPanel::~CAchievementsPageGroupPanel()
+{
+ delete m_pAchievementGroupLabel;
+ delete m_pPercentageBar;
+ delete m_pPercentageText;
+ delete m_pGroupIcon;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Loads settings from hl2/resource/ui/achievementitem.res
+// Sets display info for this achievement item.
+//-----------------------------------------------------------------------------
+void CAchievementsPageGroupPanel::ApplySchemeSettings( vgui::IScheme* pScheme )
+{
+ if ( !g_pPreloadedCSAchievementPageGroupLayout )
+ {
+ PreloadResourceFile();
+ }
+
+ LoadControlSettings( "", NULL, g_pPreloadedCSAchievementPageGroupLayout );
+
+ m_pSchemeSettings = pScheme;
+
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ // m_pSchemeSettings must be set for this.
+ UpdateAchievementInfo( pScheme );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates displayed achievement data. In ApplySchemeSettings(), and
+// when gameui activates.
+//-----------------------------------------------------------------------------
+void CAchievementsPageGroupPanel::UpdateAchievementInfo( vgui::IScheme* pScheme )
+{
+ if ( m_pSchemeSettings )
+ {
+ int numAwarded = 0;
+ int numTested = 0;
+
+ char buf[128];
+ int achievementRangeStart = (m_iFirstAchievementID / 1000) * 1000;
+ Q_snprintf( buf, sizeof(buf), "#Achievement_Group_%d", achievementRangeStart );
+
+ wchar_t *wzGroupName = g_pVGuiLocalize->Find( buf );
+
+ if ( !wzGroupName )
+ {
+ wzGroupName = L"Need Title ( %s1 of %s2 )";
+ }
+
+ wchar_t wzGroupTitle[128];
+
+ if ( wzGroupName )
+ {
+ // Determine number of achievements in the group which have been awarded
+ for (int i = m_iFirstAchievementID; i < m_iLastAchievementID; i++)
+ {
+ IAchievement* pCur = g_AchievementMgrCS.GetAchievementByID( i );
+
+ if ( !pCur )
+ continue;
+
+ numTested++;
+
+ if ( pCur->IsAchieved() )
+ {
+ numAwarded++;
+ }
+ }
+
+ wchar_t wzNumUnlocked[8];
+ V_snwprintf( wzNumUnlocked, ARRAYSIZE( wzNumUnlocked ), L"%d", numAwarded );
+
+ wchar_t wzNumAchievements[8];
+ V_snwprintf( wzNumAchievements,ARRAYSIZE( wzNumAchievements ), L"%d", numTested );
+
+ g_pVGuiLocalize->ConstructString( wzGroupTitle, sizeof( wzGroupTitle ), wzGroupName, 2, wzNumUnlocked, wzNumAchievements );
+ }
+
+ // Set group name text
+ m_pAchievementGroupLabel->SetText( wzGroupTitle );//m_pGroupName );
+ m_pAchievementGroupLabel->SetFgColor(Color(157, 194, 80, 255));
+
+ char* buff[32];
+ Q_snprintf( (char*)buff, 32, "%d / %d", numAwarded, numTested );
+ m_pPercentageText->SetText( (const char*)buff );
+ m_pPercentageText->SetFgColor(Color(157, 194, 80, 255));
+
+ if ( !m_bActiveButton )
+ {
+ CSLoadIconForPage( m_pGroupIcon, "achievement-btn-up" );
+ }
+ else
+ {
+ CSLoadIconForPage( m_pGroupIcon, "achievement-btn-select" );
+ }
+
+ // Update the percentage complete bar
+ vgui::ImagePanel *pPercentageBar = (vgui::ImagePanel*)FindChildByName( "GroupPercentageBar" );
+ vgui::ImagePanel *pPercentageBarBkg = (vgui::ImagePanel*)FindChildByName( "GroupPercentageBarBackground" );
+
+ if ( pPercentageBar && pPercentageBarBkg )
+ {
+ float flCompletion = (float)numAwarded / (float)numTested;
+ pPercentageBar->SetFillColor( Color(157, 194, 80, 255) );
+ pPercentageBar->SetWide( pPercentageBarBkg->GetWide() * flCompletion );
+
+ SetControlVisible( "GroupPercentageBarBackground", true );
+ SetControlVisible( "GroupPercentageBar", true );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CAchievementsPageGroupPanel::PreloadResourceFile( void )
+{
+ const char *controlResourceName = "resource/ui/AchievementGroup.res";
+
+ g_pPreloadedCSAchievementPageGroupLayout = new KeyValues(controlResourceName);
+ g_pPreloadedCSAchievementPageGroupLayout->LoadFromFile(g_pFullFileSystem, controlResourceName);
+
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Assigns a name and achievement id bounds for an achievement group.
+//-----------------------------------------------------------------------------
+void CAchievementsPageGroupPanel::SetGroupInfo( const wchar_t* name, int firstAchievementID, int lastAchievementID )
+{
+ // Store away the group name
+ short _textLen = (short)wcslen(name) + 1;
+ m_pGroupName = new wchar_t[_textLen];
+ Q_memcpy( m_pGroupName, name, _textLen * sizeof(wchar_t) );
+
+ // Store off the start & end achievement IDs
+ m_iFirstAchievementID = firstAchievementID;
+ m_iLastAchievementID = lastAchievementID;
+}
+
+CGroupButton::CGroupButton( vgui::Panel *pParent, const char *pName, const char *pText ) :
+BaseClass( pParent, pName, pText )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Handle the case where the user presses an achievement group button.
+//-----------------------------------------------------------------------------
+void CGroupButton::DoClick( void )
+{
+ // Process when a group button is hit
+ CAchievementsPageGroupPanel* pParent = static_cast<CAchievementsPageGroupPanel*>(GetParent());
+
+ if (pParent)
+ {
+ CAchievementsPage* pAchievementsPage = static_cast<CAchievementsPage*>(pParent->GetOwner());
+
+ if (pAchievementsPage)
+ {
+ // Update the list of group achievements
+ pAchievementsPage->UpdateAchievementList( pParent );
+ }
+ }
+}
+
+void CAchievementsPage::OnPageShow()
+{
+ m_pGroupsList->GetScrollbar()->SetWide(0);
+}
+
+void CAchievementsPage::FireGameEvent( IGameEvent *event )
+{
+ const char *type = event->GetName();
+
+ if ( 0 == Q_strcmp( type, "achievement_earned_local" ) )
+ m_bAchievementsDirty = true;
+
+ if ( 0 == Q_strcmp( type, "player_stats_updated" ) )
+ m_bStatsDirty = true;
+}
+
+void CAchievementsPage::OnThink()
+{
+ vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
+
+ if ( m_bAchievementsDirty )
+ {
+ UpdateAchievementDialogInfo();
+ }
+ else if ( m_bStatsDirty )
+ {
+ // Update progress for currently displayed achievements
+ int itemId = m_pAchievementsList->FirstItem();
+
+ while (itemId != m_pAchievementsList->InvalidItemID() )
+ {
+ CAchievementsPageItemPanel *pAchievementItem = dynamic_cast<CAchievementsPageItemPanel*>(m_pAchievementsList->GetItemPanel(itemId));
+ pAchievementItem->UpdateAchievementInfo(pScheme);
+
+ itemId = m_pAchievementsList->NextItem(itemId);
+ }
+ m_bStatsDirty = false;
+ }
+}
+
+CHiddenHUDToggleButton::CHiddenHUDToggleButton( vgui::Panel *pParent, const char *pName, const char *pText ) :
+BaseClass( pParent, pName, pText )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Handle the case where the user shift-clicks on an un-awarded achievement.
+//-----------------------------------------------------------------------------
+void CHiddenHUDToggleButton::DoClick( void )
+{
+ if ( input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT) )
+ {
+ // Process when a group button is hit
+ CAchievementsPageItemPanel* pParent = static_cast<CAchievementsPageItemPanel*>(GetParent());
+
+ if (pParent)
+ {
+ pParent->ToggleShowOnHUDButton();
+ }
+ }
+}