aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/hud_hintdisplay.cpp
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/client/hud_hintdisplay.cpp
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/client/hud_hintdisplay.cpp')
-rw-r--r--mp/src/game/client/hud_hintdisplay.cpp790
1 files changed, 790 insertions, 0 deletions
diff --git a/mp/src/game/client/hud_hintdisplay.cpp b/mp/src/game/client/hud_hintdisplay.cpp
new file mode 100644
index 00000000..0bcc6b16
--- /dev/null
+++ b/mp/src/game/client/hud_hintdisplay.cpp
@@ -0,0 +1,790 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "cbase.h"
+#include "hud.h"
+#include "hudelement.h"
+#include "hud_macros.h"
+#include "iclientmode.h"
+#include "vgui_controls/AnimationController.h"
+#include "vgui_controls/Label.h"
+#include "vgui/ILocalize.h"
+#include "vgui/ISurface.h"
+#include "text_message.h"
+#include "c_baseplayer.h"
+#include "IGameUIFuncs.h"
+#include "inputsystem/iinputsystem.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: Displays hints across the center of the screen
+//-----------------------------------------------------------------------------
+class CHudHintDisplay : public vgui::Panel, public CHudElement
+{
+ DECLARE_CLASS_SIMPLE( CHudHintDisplay, vgui::Panel );
+
+public:
+ CHudHintDisplay( const char *pElementName );
+
+ void Init();
+ void Reset();
+ void MsgFunc_HintText( bf_read &msg );
+ void FireGameEvent( IGameEvent * event);
+
+ bool SetHintText( wchar_t *text );
+ void LocalizeAndDisplay( const char *pszHudTxtMsg, const char *szRawString );
+
+ virtual void PerformLayout();
+
+protected:
+ virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
+ virtual void OnThink();
+
+protected:
+ vgui::HFont m_hFont;
+ Color m_bgColor;
+ vgui::Label *m_pLabel;
+ CUtlVector<vgui::Label *> m_Labels;
+ CPanelAnimationVarAliasType( int, m_iTextX, "text_xpos", "8", "proportional_int" );
+ CPanelAnimationVarAliasType( int, m_iTextY, "text_ypos", "8", "proportional_int" );
+ CPanelAnimationVarAliasType( int, m_iCenterX, "center_x", "0", "proportional_int" );
+ CPanelAnimationVarAliasType( int, m_iCenterY, "center_y", "0", "proportional_int" );
+
+ bool m_bLastLabelUpdateHack;
+ CPanelAnimationVar( float, m_flLabelSizePercentage, "HintSize", "0" );
+};
+
+DECLARE_HUDELEMENT( CHudHintDisplay );
+DECLARE_HUD_MESSAGE( CHudHintDisplay, HintText );
+
+#define MAX_HINT_STRINGS 5
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudHintDisplay::CHudHintDisplay( const char *pElementName ) : BaseClass(NULL, "HudHintDisplay"), CHudElement( pElementName )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+ SetVisible( false );
+ m_pLabel = new vgui::Label( this, "HudHintDisplayLabel", "" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHintDisplay::Init()
+{
+ HOOK_HUD_MESSAGE( CHudHintDisplay, HintText );
+
+ // listen for client side events
+ ListenForGameEvent( "player_hintmessage" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHintDisplay::Reset()
+{
+ SetHintText( NULL );
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HintMessageHide" );
+ m_bLastLabelUpdateHack = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHintDisplay::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ SetFgColor( GetSchemeColor("HintMessageFg", pScheme) );
+ m_hFont = pScheme->GetFont( "HudHintText", true );
+ m_pLabel->SetBgColor( GetSchemeColor("HintMessageBg", pScheme) );
+ m_pLabel->SetPaintBackgroundType( 2 );
+ m_pLabel->SetSize( 0, GetTall() ); // Start tiny, it'll grow.
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the hint text, replacing variables as necessary
+//-----------------------------------------------------------------------------
+bool CHudHintDisplay::SetHintText( wchar_t *text )
+{
+ if ( text == NULL || text[0] == L'\0' )
+ {
+ return false;
+ }
+
+ // clear the existing text
+ for (int i = 0; i < m_Labels.Count(); i++)
+ {
+ m_Labels[i]->MarkForDeletion();
+ }
+ m_Labels.RemoveAll();
+
+ wchar_t *p = text;
+
+ while ( p )
+ {
+ wchar_t *line = p;
+ wchar_t *end = wcschr( p, L'\n' );
+ int linelengthbytes = 0;
+ if ( end )
+ {
+ //*end = 0; //eek
+ p = end+1;
+ linelengthbytes = ( end - line ) * 2;
+ }
+ else
+ {
+ p = NULL;
+ }
+
+ // replace any key references with bound keys
+ wchar_t buf[512];
+ UTIL_ReplaceKeyBindings( line, linelengthbytes, buf, sizeof( buf ) );
+
+ // put it in a label
+ vgui::Label *label = vgui::SETUP_PANEL(new vgui::Label(this, NULL, buf));
+ label->SetFont( m_hFont );
+ label->SetPaintBackgroundEnabled( false );
+ label->SetPaintBorderEnabled( false );
+ label->SizeToContents();
+ label->SetContentAlignment( vgui::Label::a_west );
+ label->SetFgColor( GetFgColor() );
+ m_Labels.AddToTail( vgui::SETUP_PANEL(label) );
+ }
+
+ InvalidateLayout( true );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Resizes the label
+//-----------------------------------------------------------------------------
+void CHudHintDisplay::PerformLayout()
+{
+ BaseClass::PerformLayout();
+ int i;
+
+ int wide, tall;
+ GetSize( wide, tall );
+
+ // find the widest line
+ int iDesiredLabelWide = 0;
+ for ( i=0; i < m_Labels.Count(); ++i )
+ {
+ iDesiredLabelWide = MAX( iDesiredLabelWide, m_Labels[i]->GetWide() );
+ }
+
+ // find the total height
+ int fontTall = vgui::surface()->GetFontTall( m_hFont );
+ int labelTall = fontTall * m_Labels.Count();
+
+ iDesiredLabelWide += m_iTextX*2;
+ labelTall += m_iTextY*2;
+
+ // Now clamp it to our animation size
+ iDesiredLabelWide = (iDesiredLabelWide * m_flLabelSizePercentage);
+
+ int x, y;
+ if ( m_iCenterX < 0 )
+ {
+ x = 0;
+ }
+ else if ( m_iCenterX > 0 )
+ {
+ x = wide - iDesiredLabelWide;
+ }
+ else
+ {
+ x = (wide - iDesiredLabelWide) / 2;
+ }
+
+ if ( m_iCenterY > 0 )
+ {
+ y = 0;
+ }
+ else if ( m_iCenterY < 0 )
+ {
+ y = tall - labelTall;
+ }
+ else
+ {
+ y = (tall - labelTall) / 2;
+ }
+
+ x = MAX(x,0);
+ y = MAX(y,0);
+
+ iDesiredLabelWide = MIN(iDesiredLabelWide,wide);
+ m_pLabel->SetBounds( x, y, iDesiredLabelWide, labelTall );
+
+ // now lay out the sub-labels
+ for ( i=0; i<m_Labels.Count(); ++i )
+ {
+ int xOffset = (wide - m_Labels[i]->GetWide()) * 0.5;
+ m_Labels[i]->SetPos( xOffset, y + m_iTextY + i*fontTall );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates the label color each frame
+//-----------------------------------------------------------------------------
+void CHudHintDisplay::OnThink()
+{
+ m_pLabel->SetFgColor(GetFgColor());
+ for (int i = 0; i < m_Labels.Count(); i++)
+ {
+ m_Labels[i]->SetFgColor(GetFgColor());
+ }
+
+ // If our label size isn't at the extreme's, we're sliding open / closed
+ // This is a hack to get around InvalideLayout() not getting called when
+ // m_flLabelSizePercentage is changed via a HudAnimation.
+ if ( ( m_flLabelSizePercentage != 0.0 && m_flLabelSizePercentage != 1.0 ) || m_bLastLabelUpdateHack )
+ {
+ m_bLastLabelUpdateHack = (m_flLabelSizePercentage != 0.0 && m_flLabelSizePercentage != 1.0);
+ InvalidateLayout();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Activates the hint display
+//-----------------------------------------------------------------------------
+void CHudHintDisplay::MsgFunc_HintText( bf_read &msg )
+{
+ // Read the string(s)
+ char szString[255];
+ msg.ReadString( szString, sizeof(szString) );
+
+ char *tmpStr = hudtextmessage->LookupString( szString, NULL );
+ LocalizeAndDisplay( tmpStr, szString );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Activates the hint display upon receiving a hint
+//-----------------------------------------------------------------------------
+void CHudHintDisplay::FireGameEvent( IGameEvent * event)
+{
+ const char *hintmessage = event->GetString( "hintmessage" );
+ char *tmpStr = hudtextmessage->LookupString( hintmessage, NULL );
+ LocalizeAndDisplay( tmpStr, hintmessage );
+}
+
+extern ConVar sv_hudhint_sound;
+ConVar cl_hudhint_sound( "cl_hudhint_sound", "1", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Disable hudhint sounds." );
+
+//-----------------------------------------------------------------------------
+// Purpose: Localize, display, and animate the hud element
+//-----------------------------------------------------------------------------
+void CHudHintDisplay::LocalizeAndDisplay( const char *pszHudTxtMsg, const char *szRawString )
+{
+ static wchar_t szBuf[128];
+ wchar_t *pszBuf;
+
+ // init buffers & pointers
+ szBuf[0] = 0;
+ pszBuf = szBuf;
+
+ // try to localize
+ if ( pszHudTxtMsg )
+ {
+ pszBuf = g_pVGuiLocalize->Find( pszHudTxtMsg );
+ }
+ else
+ {
+ pszBuf = g_pVGuiLocalize->Find( szRawString );
+ }
+
+ if ( !pszBuf )
+ {
+ // use plain ASCII string
+ g_pVGuiLocalize->ConvertANSIToUnicode( szRawString, szBuf, sizeof(szBuf) );
+ pszBuf = szBuf;
+ }
+
+ // make it visible
+ if ( SetHintText( pszBuf ) )
+ {
+ SetVisible( true );
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HintMessageShow" );
+
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+ if ( pLocalPlayer )
+ {
+#ifndef HL2MP
+ if ( sv_hudhint_sound.GetBool() && cl_hudhint_sound.GetBool() )
+ {
+ pLocalPlayer->EmitSound( "Hud.Hint" );
+ }
+#endif // HL2MP
+
+ if ( pLocalPlayer->Hints() )
+ {
+ pLocalPlayer->Hints()->PlayedAHint();
+ }
+ }
+ }
+ else
+ {
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HintMessageHide" );
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Displays small key-centric hints on the right hand side of the screen
+//-----------------------------------------------------------------------------
+class CHudHintKeyDisplay : public vgui::Panel, public CHudElement
+{
+ DECLARE_CLASS_SIMPLE( CHudHintKeyDisplay, vgui::Panel );
+
+public:
+ CHudHintKeyDisplay( const char *pElementName );
+ void Init();
+ void Reset();
+ void MsgFunc_KeyHintText( bf_read &msg );
+ bool ShouldDraw();
+
+ bool SetHintText( const char *text );
+
+protected:
+ virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
+ virtual void OnThink();
+
+private:
+ CUtlVector<vgui::Label *> m_Labels;
+ vgui::HFont m_hSmallFont, m_hLargeFont;
+ int m_iBaseY;
+
+ CPanelAnimationVarAliasType( float, m_iTextX, "text_xpos", "8", "proportional_float" );
+ CPanelAnimationVarAliasType( float, m_iTextY, "text_ypos", "8", "proportional_float" );
+ CPanelAnimationVarAliasType( float, m_iTextGapX, "text_xgap", "8", "proportional_float" );
+ CPanelAnimationVarAliasType( float, m_iTextGapY, "text_ygap", "8", "proportional_float" );
+ CPanelAnimationVarAliasType( float, m_iYOffset, "YOffset", "0", "proportional_float" );
+};
+
+DECLARE_HUDELEMENT( CHudHintKeyDisplay );
+DECLARE_HUD_MESSAGE( CHudHintKeyDisplay, KeyHintText );
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CHudHintKeyDisplay::CHudHintKeyDisplay( const char *pElementName ) : BaseClass(NULL, "HudHintKeyDisplay"), CHudElement( pElementName )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+ SetVisible( false );
+ SetAlpha( 0 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHintKeyDisplay::Init()
+{
+ HOOK_HUD_MESSAGE( CHudHintKeyDisplay, KeyHintText );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHintKeyDisplay::Reset()
+{
+ SetHintText( NULL );
+ SetAlpha( 0 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CHudHintKeyDisplay::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ m_hSmallFont = pScheme->GetFont( "HudHintTextSmall", true );
+ m_hLargeFont = pScheme->GetFont( "HudHintTextLarge", true );
+
+ BaseClass::ApplySchemeSettings( pScheme );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Save CPU cycles by letting the HUD system early cull
+// costly traversal. Called per frame, return true if thinking and
+// painting need to occur.
+//-----------------------------------------------------------------------------
+bool CHudHintKeyDisplay::ShouldDraw( void )
+{
+ return ( ( GetAlpha() > 0 ) && CHudElement::ShouldDraw() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates the label color each frame
+//-----------------------------------------------------------------------------
+void CHudHintKeyDisplay::OnThink()
+{
+ for (int i = 0; i < m_Labels.Count(); i++)
+ {
+ if ( IsX360() && ( i & 1 ) == 0 )
+ {
+ // Don't change the fg color for buttons (even numbered labels)
+ m_Labels[i]->SetAlpha( GetFgColor().a() );
+ }
+ else
+ {
+ m_Labels[i]->SetFgColor(GetFgColor());
+ }
+ }
+
+ int ox, oy;
+ GetPos(ox, oy);
+ SetPos( ox, m_iBaseY + m_iYOffset );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the hint text, replacing variables as necessary
+//-----------------------------------------------------------------------------
+bool CHudHintKeyDisplay::SetHintText( const char *text )
+{
+ if ( text == NULL || text[0] == L'\0' )
+ return false;
+
+ // clear the existing text
+ for (int i = 0; i < m_Labels.Count(); i++)
+ {
+ m_Labels[i]->MarkForDeletion();
+ }
+ m_Labels.RemoveAll();
+
+ // look up the text string
+ wchar_t *ws = g_pVGuiLocalize->Find( text );
+
+ wchar_t wszBuf[256];
+ if ( !ws || wcslen(ws) <= 0)
+ {
+ if (text[0] == '#')
+ {
+ // We don't want to display a localization placeholder, do we?
+ return false;
+ }
+ // use plain ASCII string
+ g_pVGuiLocalize->ConvertANSIToUnicode(text, wszBuf, sizeof(wszBuf));
+ ws = wszBuf;
+ }
+
+ // parse out the text into a label set
+ while ( *ws )
+ {
+ wchar_t token[256];
+ bool isVar = false;
+
+ // check for variables
+ if ( *ws == '%' )
+ {
+ isVar = true;
+ ++ws;
+ }
+
+ // parse out the string
+ wchar_t *end = wcschr( ws, '%' );
+ if ( end )
+ {
+ wcsncpy( token, ws, MIN( end - ws, ARRAYSIZE(token)) );
+ token[end - ws] = L'\0'; // force null termination
+ }
+ else
+ {
+ wcsncpy( token, ws, ARRAYSIZE(token) );
+ token[ ARRAYSIZE(token) - 1 ] = L'\0'; // force null termination
+ }
+
+ ws += wcslen( token );
+ if ( isVar )
+ {
+ // move over the end of the variable
+ ++ws;
+ }
+
+ // put it in a label
+ vgui::Label *label = vgui::SETUP_PANEL(new vgui::Label(this, NULL, token));
+
+ bool bIsBitmap = false;
+
+ // modify the label if necessary
+ if ( isVar )
+ {
+ label->SetFont( m_hLargeFont );
+
+ // lookup key names
+ char binding[64];
+ g_pVGuiLocalize->ConvertUnicodeToANSI( token, binding, sizeof(binding) );
+
+ //!! change some key names into better names
+ char friendlyName[64];
+
+ if ( IsX360() )
+ {
+ int iNumBinds = 0;
+
+ char szBuff[ 512 ];
+ wchar_t szWideBuff[ 64 ];
+
+ for ( int iCode = 0; iCode < BUTTON_CODE_LAST; ++iCode )
+ {
+ ButtonCode_t code = static_cast<ButtonCode_t>( iCode );
+
+ bool bUseThisKey = false;
+
+ // Only check against bind name if we haven't already forced this binding to be used
+ const char *pBinding = gameuifuncs->GetBindingForButtonCode( code );
+
+ if ( !pBinding )
+ continue;
+
+ bUseThisKey = ( Q_stricmp( pBinding, binding ) == 0 );
+
+ if ( !bUseThisKey &&
+ ( Q_stricmp( pBinding, "+duck" ) == 0 || Q_stricmp( pBinding, "toggle_duck" ) == 0 ) &&
+ ( Q_stricmp( binding, "+duck" ) == 0 || Q_stricmp( binding, "toggle_duck" ) == 0 ) )
+ {
+ // +duck and toggle_duck are interchangable
+ bUseThisKey = true;
+ }
+
+ if ( !bUseThisKey &&
+ ( Q_stricmp( pBinding, "+zoom" ) == 0 || Q_stricmp( pBinding, "toggle_zoom" ) == 0 ) &&
+ ( Q_stricmp( binding, "+zoom" ) == 0 || Q_stricmp( binding, "toggle_zoom" ) == 0 ) )
+ {
+ // +zoom and toggle_zoom are interchangable
+ bUseThisKey = true;
+ }
+
+ // Don't use this bind in out list
+ if ( !bUseThisKey )
+ continue;
+
+ // Turn localized string into icon character
+ Q_snprintf( szBuff, sizeof( szBuff ), "#GameUI_Icons_%s", g_pInputSystem->ButtonCodeToString( static_cast<ButtonCode_t>( iCode ) ) );
+ g_pVGuiLocalize->ConstructString( szWideBuff, sizeof( szWideBuff ), g_pVGuiLocalize->Find( szBuff ), 0 );
+ g_pVGuiLocalize->ConvertUnicodeToANSI( szWideBuff, szBuff, sizeof( szBuff ) );
+
+ // Add this icon to our list of keys to display
+ friendlyName[ iNumBinds ] = szBuff[ 0 ];
+ ++iNumBinds;
+ }
+
+ friendlyName[ iNumBinds ] = '\0';
+
+ if ( iNumBinds == 0 )
+ {
+ friendlyName[ 0 ] = '\0';
+ label->SetFont( m_hSmallFont );
+ label->SetText( "#GameUI_Icons_NONE" );
+ }
+ else
+ {
+ // 360 always uses bitmaps
+ bIsBitmap = true;
+ label->SetText( friendlyName );
+ }
+ }
+ else
+ {
+ const char *key = engine->Key_LookupBinding( *binding == '+' ? binding + 1 : binding );
+ if ( !key )
+ {
+ key = "< not bound >";
+ }
+
+ Q_snprintf( friendlyName, sizeof(friendlyName), "#%s", key );
+ Q_strupr( friendlyName );
+
+ // set the variable text - key may need to be localized (button images for example)
+ wchar_t *locName = g_pVGuiLocalize->Find( friendlyName );
+ if ( !locName || wcslen(locName) <= 0)
+ {
+ label->SetText( friendlyName + 1 );
+ }
+ else
+ {
+ // Assuming localized vars must be using a bitmap image. *May* not be the case, but since
+ // keyboard bindings have never been localized in the past, they probably won't in the future either.
+ bIsBitmap = true;
+ label->SetText( locName );
+ }
+ }
+ }
+ else
+ {
+ label->SetFont( m_hSmallFont );
+ }
+
+ label->SetPaintBackgroundEnabled( false );
+ label->SetPaintBorderEnabled( false );
+ label->SizeToContents();
+ label->SetContentAlignment( vgui::Label::a_west );
+ if ( bIsBitmap && isVar )
+ {
+ // Don't change the color of the button art
+ label->SetFgColor( Color(255,255,255,255) );
+ }
+ else
+ {
+ label->SetFgColor( GetFgColor() );
+ }
+ m_Labels.AddToTail( vgui::SETUP_PANEL(label) );
+ }
+
+// Enable this small block of code to test formatting and layout of hint messages
+// with varying numbers of lines
+#define TEST_KEYHINT_DISPLAY 0
+#if TEST_KEYHINT_DISPLAY
+
+ // clear the existing text
+ for (int i = 0; i < m_Labels.Count(); i++)
+ {
+ m_Labels[i]->MarkForDeletion();
+ }
+ m_Labels.RemoveAll();
+
+ const char* sampleText[] =
+ {
+ "This is a test",
+ "of the hint system\nwith a multi-line hint",
+ "that\ngoes\non\nfor",
+ "several",
+ "lines"
+ };
+
+ for ( int i = 0; i < ARRAYSIZE(sampleText); ++i)
+ {
+ // put it in a label
+ vgui::Label *label = vgui::SETUP_PANEL(new vgui::Label(this, NULL, sampleText[i]));
+
+ label->SetFont( m_hSmallFont );
+ label->SetPaintBackgroundEnabled( false );
+ label->SetPaintBorderEnabled( false );
+ label->SizeToContents();
+ label->SetContentAlignment( vgui::Label::a_west );
+ label->SetFgColor( GetFgColor() );
+ m_Labels.AddToTail( vgui::SETUP_PANEL(label) );
+ }
+#endif
+
+ // find the bounds we need to show
+ int widest1 = 0, widest2 = 0;
+ for (int i = 0; i < m_Labels.Count(); i++)
+ {
+ vgui::Label *label = m_Labels[i];
+
+ if (i & 1)
+ {
+ // help text
+ if (label->GetWide() > widest2)
+ {
+ widest2 = label->GetWide();
+ }
+ }
+ else
+ {
+ // variable
+ if (label->GetWide() > widest1)
+ {
+ widest1 = label->GetWide();
+ }
+ }
+ }
+
+ // position the labels
+ int col1_x = m_iTextX;
+ int col2_x = m_iTextX + widest1 + m_iTextGapX;
+ int col_y = m_iTextY;
+
+ for (int i = 0; i < m_Labels.Count(); i += 2)
+ {
+ int rowHeight = 0;
+ vgui::Label *label0 = m_Labels[i];
+ int tall0 = label0->GetTall();
+ rowHeight = tall0;
+
+ if (i + 1 < m_Labels.Count())
+ {
+ vgui::Label *label1 = m_Labels[i + 1];
+ int tall1 = label1->GetTall();
+ rowHeight = MAX(tall0, tall1);
+ label1->SetPos( col2_x, col_y + (rowHeight - tall1) / 2 );
+ }
+
+ label0->SetPos( col1_x, col_y + (rowHeight - tall0) / 2 );
+
+ col_y += rowHeight + m_iTextGapY;
+ }
+
+ // move ourselves relative to our start position
+ int newWide = m_iTextX + col2_x + widest2;
+ int newTall = col_y;
+ int ox, oy;
+ GetPos(ox, oy);
+
+ if (IsRightAligned())
+ {
+ int oldWide = GetWide();
+ int diff = newWide - oldWide;
+ ox -= diff;
+ }
+
+ if (IsBottomAligned())
+ {
+ int oldTall = GetTall();
+ int diff = newTall - oldTall;
+ oy -= diff;
+ }
+
+ // set the size of the hint panel to fit
+ SetPos( ox, oy );
+ SetSize( newWide, newTall );
+
+ m_iBaseY = oy;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Activates the hint display
+//-----------------------------------------------------------------------------
+void CHudHintKeyDisplay::MsgFunc_KeyHintText( bf_read &msg )
+{
+ // how many strings do we receive ?
+ int count = msg.ReadByte();
+
+ // here we expect only one string
+ if ( count != 1 )
+ {
+ DevMsg("CHudHintKeyDisplay::MsgFunc_KeyHintText: string count != 1.\n");
+ return;
+ }
+
+ // read the string
+ char szString[2048];
+ msg.ReadString( szString, sizeof(szString) );
+
+ // make it visible
+ if ( SetHintText( szString ) )
+ {
+ SetVisible( true );
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "KeyHintMessageShow" );
+ }
+ else
+ {
+ // it's being cleared, hide the panel
+ g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "KeyHintMessageHide" );
+ }
+}