source-engine/game/gamepadui/gamepadui_achievements.cpp
2024-04-13 19:58:55 +03:00

325 lines
12 KiB
C++

#include "gamepadui_button.h"
#include "gamepadui_frame.h"
#include "gamepadui_scroll.h"
#include "gamepadui_interface.h"
#include "gamepadui_image.h"
#include "ienginevgui.h"
#include "vgui/ILocalize.h"
#include "vgui/ISurface.h"
#include "vgui/IVGui.h"
#include "fmtstr.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/ImagePanel.h"
#include "vgui_controls/ScrollBar.h"
#include "KeyValues.h"
#include "filesystem.h"
#include "tier0/memdbgon.h"
class GamepadUIAchievement;
class GamepadUIAchievementsPanel : public GamepadUIFrame
{
DECLARE_CLASS_SIMPLE( GamepadUIAchievementsPanel, GamepadUIFrame );
public:
GamepadUIAchievementsPanel( vgui::Panel *pParent, const char* pPanelName );
void UpdateGradients() OVERRIDE;
void OnThink() OVERRIDE;
void OnCommand( char const* pCommand ) OVERRIDE;
MESSAGE_FUNC_HANDLE( OnGamepadUIButtonNavigatedTo, "OnGamepadUIButtonNavigatedTo", button );
void LayoutAchievementPanels();
void OnMouseWheeled( int nDelta ) OVERRIDE;
private:
CUtlVector< GamepadUIAchievement* > m_pAchievementPanels;
GamepadUIScrollState m_ScrollState;
int m_nTotalAchievements = 0;
int m_nUnlockedAchievements = 0;
GAMEPADUI_PANEL_PROPERTY( float, m_AchievementsFade, "Achievements.Fade", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_AchievementsOffsetX, "Achievements.OffsetX", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_AchievementsOffsetY, "Achievements.OffsetY", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flAchievementsSpacing, "Achievements.Spacing", "0", SchemeValueTypes::ProportionalFloat );
};
class GamepadUIAchievement : public GamepadUIButton
{
public:
DECLARE_CLASS_SIMPLE( GamepadUIAchievement, GamepadUIButton );
GamepadUIAchievement( vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char* pSchemeFile, const char* pCommand, const char* pText, const char* pDescription, const char *pChapterImage )
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
, m_Image( pChapterImage )
{
}
GamepadUIAchievement( vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char* pSchemeFile, const char* pCommand, const wchar* pText, const wchar* pDescription, const char *pChapterImage )
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
, m_Image( pChapterImage )
{
}
void ApplySchemeSettings( vgui::IScheme* pScheme ) OVERRIDE
{
BaseClass::ApplySchemeSettings( pScheme );
m_hProgressFont = pScheme->GetFont( "Button.Progress.Font", true );
}
void Paint() OVERRIDE
{
int x, y, w, t;
GetBounds( x, y, w, t );
PaintButton();
vgui::surface()->DrawSetColor( m_colProgressColor );
vgui::surface()->DrawFilledRect( 0, GetDrawHeight() - m_flProgressHeight, m_flWidth * m_flProgress, GetDrawHeight() );
if ( m_nGoal > 1 && m_flProgress > 0.0f )
{
vgui::surface()->DrawSetColor( m_colUnprogressColor );
vgui::surface()->DrawFilledRect( m_flWidth * m_flProgress, GetDrawHeight() - m_flProgressHeight, m_flWidth, GetDrawHeight() );
}
vgui::surface()->DrawSetColor( Color( 255, 255, 255, 255 ) );
vgui::surface()->DrawSetTexture( m_Image );
int nImageSize = m_flHeight - m_flIconInset * 2;
vgui::surface()->DrawTexturedRect( m_flIconInset, m_flIconInset, m_flIconInset + nImageSize, m_flIconInset + nImageSize );
vgui::surface()->DrawSetTexture( 0 );
PaintText();
if ( m_nGoal > 1 )
{
wchar_t wcsProgress[32];
int nLength = V_swprintf_safe( wcsProgress, L"%d/%d", m_nCount, m_nGoal );
vgui::surface()->DrawSetTextColor( m_colTextColor );
vgui::surface()->DrawSetTextFont( m_hProgressFont );
int32 textSizeX = 0, textSizeY = 0;
vgui::surface()->GetTextSize( m_hProgressFont, wcsProgress, textSizeX, textSizeY );
int textPosX = m_flWidth - textSizeX - m_flProgressOffsetX;
int textPosY = GetDrawHeight() / 2 - textSizeY / 2;
vgui::surface()->DrawSetTextPos( textPosX, textPosY );
vgui::surface()->DrawPrintText( wcsProgress, nLength );
}
}
void SetProgress( bool bAchieved, int nCount, int nGoal )
{
m_nCount = nCount;
m_nGoal = nGoal;
if (bAchieved)
{
m_flProgress = 1.0f;
m_nCount = m_nGoal;
}
else
m_flProgress = min( float( nCount ) / float( nGoal ), 1.0f );
}
private:
GamepadUIImage m_Image;
float m_flProgress = 0.0f;
int m_nCount = 0;
int m_nGoal = 0;
vgui::HFont m_hProgressFont = vgui::INVALID_FONT;
GAMEPADUI_PANEL_PROPERTY( Color, m_colProgressColor, "Button.Background.Progress", "255 0 0 255", SchemeValueTypes::Color );
GAMEPADUI_PANEL_PROPERTY( Color, m_colUnprogressColor, "Button.Background.Unprogress", "255 0 0 255", SchemeValueTypes::Color );
GAMEPADUI_PANEL_PROPERTY( float, m_flProgressHeight, "Button.Progress.Height", "1", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flIconInset, "Button.Icon.Inset", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flProgressOffsetX, "Button.Progress.OffsetX", "0", SchemeValueTypes::ProportionalFloat );
};
GamepadUIAchievementsPanel::GamepadUIAchievementsPanel( vgui::Panel *pParent, const char* pPanelName ) : BaseClass( pParent, pPanelName )
{
vgui::HScheme hScheme = vgui::scheme()->LoadSchemeFromFileEx( GamepadUI::GetInstance().GetSizingVPanel(), GAMEPADUI_DEFAULT_PANEL_SCHEME, "SchemePanel" );
SetScheme( hScheme );
GetFrameTitle() = GamepadUIString( "#GameUI_Achievements_Title" );
SetFooterButtons( FooterButtons::Back );
Activate();
GamepadUI::GetInstance().GetAchievementMgr()->EnsureGlobalStateLoaded();
int nAllAchievements = GamepadUI::GetInstance().GetAchievementMgr()->GetAchievementCount();
for ( int i = 0; i < nAllAchievements; i++ )
{
IAchievement *pCurAchievement = GamepadUI::GetInstance().GetAchievementMgr()->GetAchievementByIndex( i );
if ( !pCurAchievement )
continue;
if ( pCurAchievement->IsAchieved() )
m_nUnlockedAchievements++;
// Don't show hidden achievements if not achieved.
if ( pCurAchievement->ShouldHideUntilAchieved() && !pCurAchievement->IsAchieved() )
continue;
char szIconName[MAX_PATH];
V_sprintf_safe( szIconName, "gamepadui/achievements/%s%s.vmt", pCurAchievement->GetName(), pCurAchievement->IsAchieved() ? "" : "_bw" );
char szMaterialName[MAX_PATH];
V_sprintf_safe( szMaterialName, "materials/%s", szIconName );
if ( !g_pFullFileSystem->FileExists( szMaterialName ) )
V_sprintf_safe( szIconName, "vgui/achievements/%s%s.vmt", pCurAchievement->GetName(), pCurAchievement->IsAchieved() ? "" : "_bw" );
V_sprintf_safe( szMaterialName, "materials/%s", szIconName );
if ( !g_pFullFileSystem->FileExists( szMaterialName ) )
V_strcpy_safe( szIconName, "vgui/hud/icon_locked.vmt" );
auto pAchievementPanel = new GamepadUIAchievement(
this, this,
GAMEPADUI_RESOURCE_FOLDER "schemeachievement.res",
"",
ACHIEVEMENT_LOCALIZED_NAME( pCurAchievement ),
ACHIEVEMENT_LOCALIZED_DESC( pCurAchievement ),
szIconName );
pAchievementPanel->SetProgress( pCurAchievement->IsAchieved(), pCurAchievement->GetCount(), pCurAchievement->GetGoal() );
pAchievementPanel->SetPriority( m_nTotalAchievements );
m_pAchievementPanels.AddToTail( pAchievementPanel );
m_nTotalAchievements++;
}
if ( m_pAchievementPanels.Count() )
m_pAchievementPanels[0]->NavigateTo();
for ( int i = 1; i < m_pAchievementPanels.Count(); i++ )
{
m_pAchievementPanels[i]->SetNavUp( m_pAchievementPanels[i - 1] );
m_pAchievementPanels[i - 1]->SetNavDown( m_pAchievementPanels[i] );
}
UpdateGradients();
}
void GamepadUIAchievementsPanel::UpdateGradients()
{
const float flTime = GamepadUI::GetInstance().GetTime();
GamepadUI::GetInstance().GetGradientHelper()->ResetTargets( flTime );
GamepadUI::GetInstance().GetGradientHelper()->SetTargetGradient( GradientSide::Up, { 1.0f, 1.0f }, flTime );
GamepadUI::GetInstance().GetGradientHelper()->SetTargetGradient( GradientSide::Down, { 1.0f, 0.5f }, flTime );
}
void GamepadUIAchievementsPanel::OnThink()
{
BaseClass::OnThink();
LayoutAchievementPanels();
}
void GamepadUIAchievementsPanel::OnGamepadUIButtonNavigatedTo( vgui::VPANEL button )
{
GamepadUIButton *pButton = dynamic_cast< GamepadUIButton * >( vgui::ipanel()->GetPanel( button, GetModuleName() ) );
if ( pButton )
{
if ( pButton->GetAlpha() != 255 )
{
int nParentW, nParentH;
GetParent()->GetSize( nParentW, nParentH );
int nX, nY;
pButton->GetPos( nX, nY );
int nTargetY = pButton->GetPriority() * (pButton->m_flHeightAnimationValue[ButtonStates::Out] + m_flAchievementsSpacing);
if ( nY < nParentH / 2 )
{
nTargetY += nParentH - m_AchievementsOffsetY;
// Add a bit of spacing to make this more visually appealing :)
nTargetY -= m_flAchievementsSpacing;
}
else
{
nTargetY += pButton->GetMaxHeight();
// Add a bit of spacing to make this more visually appealing :)
nTargetY += (pButton->GetMaxHeight() / 2) + 2 * m_flAchievementsSpacing;
}
m_ScrollState.SetScrollTarget( nTargetY - ( nParentH - m_AchievementsOffsetY ), GamepadUI::GetInstance().GetTime() );
}
}
}
void GamepadUIAchievementsPanel::LayoutAchievementPanels()
{
int nParentW, nParentH;
GetParent()->GetSize( nParentW, nParentH );
float flScrollClamp = 0.0f;
for ( int i = 0; i < m_pAchievementPanels.Count(); i++ )
{
int size = ( m_pAchievementPanels[i]->GetTall() + m_flAchievementsSpacing );
if ( i < m_pAchievementPanels.Count() - 2 )
flScrollClamp += size;
}
m_ScrollState.UpdateScrollBounds( 0.0f, flScrollClamp );
int previousSizes = 0;
for ( int i = 0; i < m_pAchievementPanels.Count(); i++ )
{
int tall = m_pAchievementPanels[i]->GetTall();
int size = ( tall + m_flAchievementsSpacing );
int y = m_AchievementsOffsetY + previousSizes - m_ScrollState.GetScrollProgress();
int fade = 255;
if ( y < m_AchievementsOffsetY )
fade = ( 1.0f - clamp( -( y - m_AchievementsOffsetY ) / m_AchievementsFade, 0.0f, 1.0f ) ) * 255.0f;
if ( y > nParentH - m_AchievementsFade )
fade = ( 1.0f - clamp(( y - ( nParentH - m_AchievementsFade - size ) ) / m_AchievementsFade, 0.0f, 1.0f ) ) * 255.0f;
if ( m_pAchievementPanels[i]->HasFocus() && fade != 0 )
fade = 255;
m_pAchievementPanels[i]->SetAlpha( fade );
m_pAchievementPanels[i]->SetPos( m_AchievementsOffsetX, y );
m_pAchievementPanels[i]->SetVisible( true );
previousSizes += size;
}
m_ScrollState.UpdateScrolling( 2.0f, GamepadUI::GetInstance().GetTime() );
}
void GamepadUIAchievementsPanel::OnCommand( char const* pCommand )
{
if ( !V_strcmp( pCommand, "action_back" ) )
{
Close();
}
else
{
BaseClass::OnCommand( pCommand );
}
}
void GamepadUIAchievementsPanel::OnMouseWheeled( int nDelta )
{
m_ScrollState.OnMouseWheeled( nDelta * 160.0f, GamepadUI::GetInstance().GetTime() );
}
CON_COMMAND( gamepadui_openachievementsdialog, "" )
{
new GamepadUIAchievementsPanel( GamepadUI::GetInstance().GetBasePanel(), "AchievementsPanel" );
}