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.
282 lines
9.9 KiB
282 lines
9.9 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//============================================================================= |
|
|
|
#include "cbase.h" |
|
#include "hud.h" |
|
#include "hud_macros.h" |
|
#include "hudelement.h" |
|
#include "iclientmode.h" |
|
#include "ienginevgui.h" |
|
#include <vgui/ILocalize.h> |
|
#include <vgui/ISurface.h> |
|
#include <vgui/IVGui.h> |
|
#include <vgui_controls/EditablePanel.h> |
|
#include <vgui_controls/Label.h> |
|
#include <vgui_controls/ImagePanel.h> |
|
#include "achievement_notification_panel.h" |
|
#include "steam/steam_api.h" |
|
#include "iachievementmgr.h" |
|
#include "fmtstr.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
using namespace vgui; |
|
|
|
#define ACHIEVEMENT_NOTIFICATION_DURATION 10.0f |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
|
|
DECLARE_HUDELEMENT_DEPTH( CAchievementNotificationPanel, 100 ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CAchievementNotificationPanel::CAchievementNotificationPanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "AchievementNotificationPanel" ) |
|
{ |
|
Panel *pParent = g_pClientMode->GetViewport(); |
|
SetParent( pParent ); |
|
|
|
m_flHideTime = 0; |
|
m_pPanelBackground = new EditablePanel( this, "Notification_Background" ); |
|
m_pIcon = new ImagePanel( this, "Notification_Icon" ); |
|
m_pLabelHeading = new Label( this, "HeadingLabel", "" ); |
|
m_pLabelTitle = new Label( this, "TitleLabel", "" ); |
|
|
|
m_pIcon->SetShouldScaleImage( true ); |
|
|
|
vgui::ivgui()->AddTickSignal( GetVPanel() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CAchievementNotificationPanel::Init() |
|
{ |
|
ListenForGameEvent( "achievement_event" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CAchievementNotificationPanel::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
// load control settings... |
|
LoadControlSettings( "resource/UI/AchievementNotification.res" ); |
|
|
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CAchievementNotificationPanel::PerformLayout( void ) |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
// Set background color of various elements. Need to do this in code, if we do it in res file it gets slammed by the |
|
// scheme. (Incl. label background: some products don't have label background colors set in their scheme and helpfully slam it to white.) |
|
SetBgColor( Color( 0, 0, 0, 0 ) ); |
|
m_pLabelHeading->SetBgColor( Color( 0, 0, 0, 0 ) ); |
|
m_pLabelTitle->SetBgColor( Color( 0, 0, 0, 0 ) ); |
|
m_pPanelBackground->SetBgColor( Color( 128, 128, 128, 128 ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CAchievementNotificationPanel::FireGameEvent( IGameEvent * event ) |
|
{ |
|
const char *name = event->GetName(); |
|
if ( Q_strcmp( name, "achievement_event" ) == 0 ) |
|
{ |
|
const char *pchName = event->GetString( "achievement_name" ); |
|
int iCur = event->GetInt( "cur_val" ); |
|
int iMax = event->GetInt( "max_val" ); |
|
wchar_t szLocalizedName[256]=L""; |
|
|
|
#ifndef DISABLE_STEAM |
|
if ( IsPC() ) |
|
{ |
|
// shouldn't ever get achievement progress if steam not running and user logged in, but check just in case |
|
if ( !steamapicontext->SteamUserStats() ) |
|
{ |
|
Msg( "Steam not running, achievement progress notification not displayed\n" ); |
|
} |
|
else |
|
{ |
|
// use Steam to show achievement progress UI |
|
steamapicontext->SteamUserStats()->IndicateAchievementProgress( pchName, iCur, iMax ); |
|
} |
|
} |
|
else |
|
#endif |
|
{ |
|
// on X360 we need to show our own achievement progress UI |
|
|
|
const wchar_t *pchLocalizedName = ACHIEVEMENT_LOCALIZED_NAME_FROM_STR( pchName ); |
|
Assert( pchLocalizedName ); |
|
if ( !pchLocalizedName || !pchLocalizedName[0] ) |
|
return; |
|
Q_wcsncpy( szLocalizedName, pchLocalizedName, sizeof( szLocalizedName ) ); |
|
|
|
// this is achievement progress, compose the message of form: "<name> (<#>/<max>)" |
|
wchar_t szText[512]=L""; |
|
wchar_t szFmt[128]=L""; |
|
wchar_t szNumFound[16]=L""; |
|
wchar_t szNumTotal[16]=L""; |
|
|
|
if( iCur >= iMax ) |
|
{ |
|
AddNotification( pchName, g_pVGuiLocalize->Find( "#GameUI_Achievement_Awarded" ), szLocalizedName ); |
|
return; |
|
} |
|
|
|
_snwprintf( szNumFound, ARRAYSIZE( szNumFound ), L"%i", iCur ); |
|
_snwprintf( szNumTotal, ARRAYSIZE( szNumTotal ), L"%i", iMax ); |
|
|
|
const wchar_t *pchFmt = g_pVGuiLocalize->Find( "#GameUI_Achievement_Progress_Fmt" ); |
|
if ( !pchFmt || !pchFmt[0] ) |
|
return; |
|
Q_wcsncpy( szFmt, pchFmt, sizeof( szFmt ) ); |
|
|
|
g_pVGuiLocalize->ConstructString( szText, sizeof( szText ), szFmt, 3, szLocalizedName, szNumFound, szNumTotal ); |
|
|
|
AddNotification( pchName, g_pVGuiLocalize->Find( "#GameUI_Achievement_Progress" ), szText ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Called on each tick |
|
//----------------------------------------------------------------------------- |
|
void CAchievementNotificationPanel::OnTick( void ) |
|
{ |
|
if ( ( m_flHideTime > 0 ) && ( m_flHideTime < gpGlobals->curtime ) ) |
|
{ |
|
m_flHideTime = 0; |
|
ShowNextNotification(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CAchievementNotificationPanel::ShouldDraw( void ) |
|
{ |
|
return ( ( m_flHideTime > 0 ) && ( m_flHideTime > gpGlobals->curtime ) && CHudElement::ShouldDraw() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CAchievementNotificationPanel::AddNotification( const char *szIconBaseName, const wchar_t *pHeading, const wchar_t *pTitle ) |
|
{ |
|
// put this notification in our queue |
|
int iQueueItem = m_queueNotification.AddToTail(); |
|
Notification_t ¬ification = m_queueNotification[iQueueItem]; |
|
Q_strncpy( notification.szIconBaseName, szIconBaseName, ARRAYSIZE( notification.szIconBaseName ) ); |
|
Q_wcsncpy( notification.szHeading, pHeading, sizeof( notification.szHeading ) ); |
|
Q_wcsncpy( notification.szTitle, pTitle, sizeof( notification.szTitle ) ); |
|
|
|
// if we are not currently displaying a notification, go ahead and show this one |
|
if ( 0 == m_flHideTime ) |
|
{ |
|
ShowNextNotification(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Shows next notification in queue if there is one |
|
//----------------------------------------------------------------------------- |
|
void CAchievementNotificationPanel::ShowNextNotification() |
|
{ |
|
// see if we have anything to do |
|
if ( 0 == m_queueNotification.Count() ) |
|
{ |
|
m_flHideTime = 0; |
|
return; |
|
} |
|
|
|
Notification_t ¬ification = m_queueNotification[ m_queueNotification.Head() ]; |
|
|
|
m_flHideTime = gpGlobals->curtime + ACHIEVEMENT_NOTIFICATION_DURATION; |
|
|
|
// set the text and icon in the dialog |
|
SetDialogVariable( "heading", notification.szHeading ); |
|
SetDialogVariable( "title", notification.szTitle ); |
|
const char *pchIconBaseName = notification.szIconBaseName; |
|
if ( pchIconBaseName && pchIconBaseName[0] ) |
|
{ |
|
m_pIcon->SetImage( CFmtStr( "achievements/%s.vmt", pchIconBaseName ) ); |
|
} |
|
|
|
// resize the panel so it always looks good |
|
|
|
// get fonts |
|
HFont hFontHeading = m_pLabelHeading->GetFont(); |
|
HFont hFontTitle = m_pLabelTitle->GetFont(); |
|
// determine how wide the text strings are |
|
int iHeadingWidth = UTIL_ComputeStringWidth( hFontHeading, notification.szHeading ); |
|
int iTitleWidth = UTIL_ComputeStringWidth( hFontTitle, notification.szTitle ); |
|
// use the widest string |
|
int iTextWidth = MAX( iHeadingWidth, iTitleWidth ); |
|
// don't let it be insanely wide |
|
iTextWidth = MIN( iTextWidth, XRES( 300 ) ); |
|
int iIconWidth = m_pIcon->GetWide(); |
|
int iSpacing = XRES( 10 ); |
|
int iPanelWidth = iSpacing + iIconWidth + iSpacing + iTextWidth + iSpacing; |
|
int iPanelX = GetWide() - iPanelWidth; |
|
int iIconX = iPanelX + iSpacing; |
|
int iTextX = iIconX + iIconWidth + iSpacing; |
|
// resize all the elements |
|
SetXAndWide( m_pPanelBackground, iPanelX, iPanelWidth ); |
|
SetXAndWide( m_pIcon, iIconX, iIconWidth ); |
|
SetXAndWide( m_pLabelHeading, iTextX, iTextWidth ); |
|
SetXAndWide( m_pLabelTitle, iTextX, iTextWidth ); |
|
|
|
m_queueNotification.Remove( m_queueNotification.Head() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CAchievementNotificationPanel::SetXAndWide( Panel *pPanel, int x, int wide ) |
|
{ |
|
int xCur, yCur; |
|
pPanel->GetPos( xCur, yCur ); |
|
pPanel->SetPos( x, yCur ); |
|
pPanel->SetWide( wide ); |
|
} |
|
|
|
CON_COMMAND( achievement_notification_test, "Test the hud notification UI" ) |
|
{ |
|
static int iCount=0; |
|
|
|
CAchievementNotificationPanel *pPanel = GET_HUDELEMENT( CAchievementNotificationPanel ); |
|
if ( pPanel ) |
|
{ |
|
pPanel->AddNotification( "HL2_KILL_ODESSAGUNSHIP", L"Achievement Progress", ( 0 == ( iCount % 2 ) ? L"Test Notification Message A (1/10)" : |
|
L"Test Message B" ) ); |
|
} |
|
|
|
#if 0 |
|
IGameEvent *event = gameeventmanager->CreateEvent( "achievement_event" ); |
|
if ( event ) |
|
{ |
|
const char *szTestStr[] = { "TF_GET_HEADSHOTS", "TF_PLAY_GAME_EVERYMAP", "TF_PLAY_GAME_EVERYCLASS", "TF_GET_HEALPOINTS" }; |
|
event->SetString( "achievement_name", szTestStr[iCount%ARRAYSIZE(szTestStr)] ); |
|
event->SetInt( "cur_val", ( iCount%9 ) + 1 ); |
|
event->SetInt( "max_val", 10 ); |
|
gameeventmanager->FireEvent( event ); |
|
} |
|
#endif |
|
|
|
iCount++; |
|
}
|
|
|