|
|
//========= Copyright � 1996-2002, Valve LLC, 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"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
#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 = GetClientMode()->GetViewport(); SetParent( pParent );
SetScheme( "basemodui_scheme" );
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( 62,70,55, 200 ) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::FireGameEvent( IGameEvent * event ) { const char *name = event->GetName(); if ( 0 == Q_strcmp( name, "achievement_event" ) ) { 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 NO_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 szFmt[128]=L""; wchar_t szText[512]=L""; wchar_t szNumFound[16]=L""; wchar_t szNumTotal[16]=L""; Q_snwprintf( szNumFound, ARRAYSIZE( szNumFound ), L"%i", iCur ); Q_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->FindSafe( "#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_F( achievement_notification_test, "Test the hud notification UI", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY ) { 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++; }
|