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.
790 lines
21 KiB
790 lines
21 KiB
//========= 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_safe( 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" ); |
|
} |
|
}
|
|
|