Counter Strike : Global Offensive Source Code
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.

791 lines
21 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "hud.h"
  8. #include "hudelement.h"
  9. #include "hud_macros.h"
  10. #include "iclientmode.h"
  11. #include "vgui_controls/AnimationController.h"
  12. #include "vgui_controls/Label.h"
  13. #include "vgui/ILocalize.h"
  14. #include "vgui/ISurface.h"
  15. #include "text_message.h"
  16. #include "c_baseplayer.h"
  17. #include "IGameUIFuncs.h"
  18. #include "inputsystem/iinputsystem.h"
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. //-----------------------------------------------------------------------------
  22. // Purpose: Displays hints across the center of the screen
  23. //-----------------------------------------------------------------------------
  24. class CHudHintDisplay : public vgui::Panel, public CHudElement
  25. {
  26. DECLARE_CLASS_SIMPLE( CHudHintDisplay, vgui::Panel );
  27. public:
  28. explicit CHudHintDisplay( const char *pElementName );
  29. void Init();
  30. void Reset();
  31. bool MsgFunc_HintText( const CCSUsrMsg_HintText &msg );
  32. void FireGameEvent( IGameEvent * event);
  33. bool SetHintText( wchar_t *text );
  34. void LocalizeAndDisplay( const char *pszHudTxtMsg, const char *szRawString );
  35. virtual void PerformLayout();
  36. virtual bool ShouldDraw()
  37. {
  38. // [jason] Moving into Scaleform: sfhudinfopanel
  39. #if defined( CSTRIKE15 )
  40. return false;
  41. #else
  42. return Super::ShouldDraw();
  43. #endif
  44. }
  45. CUserMessageBinder m_UMCMsgHintText;
  46. protected:
  47. virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
  48. virtual void OnThink();
  49. protected:
  50. vgui::HFont m_hFont;
  51. Color m_bgColor;
  52. vgui::Label *m_pLabel;
  53. CUtlVector<vgui::Label *> m_Labels;
  54. CPanelAnimationVarAliasType( int, m_iTextX, "text_xpos", "8", "proportional_int" );
  55. CPanelAnimationVarAliasType( int, m_iTextY, "text_ypos", "8", "proportional_int" );
  56. CPanelAnimationVarAliasType( int, m_iCenterX, "center_x", "0", "proportional_int" );
  57. CPanelAnimationVarAliasType( int, m_iCenterY, "center_y", "0", "proportional_int" );
  58. bool m_bLastLabelUpdateHack;
  59. CPanelAnimationVar( float, m_flLabelSizePercentage, "HintSize", "0" );
  60. };
  61. DECLARE_HUDELEMENT( CHudHintDisplay );
  62. DECLARE_HUD_MESSAGE( CHudHintDisplay, HintText );
  63. #define MAX_HINT_STRINGS 5
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Constructor
  66. //-----------------------------------------------------------------------------
  67. CHudHintDisplay::CHudHintDisplay( const char *pElementName ) : BaseClass(NULL, "HudHintDisplay"), CHudElement( pElementName )
  68. {
  69. vgui::Panel *pParent = GetClientMode()->GetViewport();
  70. SetParent( pParent );
  71. SetVisible( false );
  72. m_pLabel = new vgui::Label( this, "HudHintDisplayLabel", "" );
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Purpose:
  76. //-----------------------------------------------------------------------------
  77. void CHudHintDisplay::Init()
  78. {
  79. HOOK_HUD_MESSAGE( CHudHintDisplay, HintText );
  80. // listen for client side events
  81. ListenForGameEvent( "player_hintmessage" );
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose:
  85. //-----------------------------------------------------------------------------
  86. void CHudHintDisplay::Reset()
  87. {
  88. SetHintText( NULL );
  89. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence( "HintMessageHide" );
  90. m_bLastLabelUpdateHack = true;
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Purpose:
  94. //-----------------------------------------------------------------------------
  95. void CHudHintDisplay::ApplySchemeSettings( vgui::IScheme *pScheme )
  96. {
  97. BaseClass::ApplySchemeSettings( pScheme );
  98. SetFgColor( GetSchemeColor("HintMessageFg", pScheme) );
  99. m_hFont = pScheme->GetFont( "HudHintText", true );
  100. m_pLabel->SetBgColor( GetSchemeColor("HintMessageBg", pScheme) );
  101. m_pLabel->SetPaintBackgroundType( 2 );
  102. m_pLabel->SetSize( 0, GetTall() ); // Start tiny, it'll grow.
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Purpose: Sets the hint text, replacing variables as necessary
  106. //-----------------------------------------------------------------------------
  107. bool CHudHintDisplay::SetHintText( wchar_t *text )
  108. {
  109. // clear the existing text
  110. for (int i = 0; i < m_Labels.Count(); i++)
  111. {
  112. m_Labels[i]->MarkForDeletion();
  113. }
  114. m_Labels.RemoveAll();
  115. wchar_t *p = text;
  116. while ( p )
  117. {
  118. wchar_t *line = p;
  119. wchar_t *end = wcschr( p, L'\n' );
  120. int linelengthbytes = 0;
  121. if ( end )
  122. {
  123. //*end = 0; //eek
  124. p = end+1;
  125. linelengthbytes = ( end - line ) * 2;
  126. }
  127. else
  128. {
  129. p = NULL;
  130. }
  131. // replace any key references with bound keys
  132. wchar_t buf[512];
  133. UTIL_ReplaceKeyBindings( line, linelengthbytes, buf, sizeof( buf ) );
  134. // put it in a label
  135. vgui::Label *label = vgui::SETUP_PANEL(new vgui::Label(this, NULL, buf));
  136. label->SetFont( m_hFont );
  137. label->SetPaintBackgroundEnabled( false );
  138. label->SetPaintBorderEnabled( false );
  139. label->SizeToContents();
  140. label->SetContentAlignment( vgui::Label::a_west );
  141. label->SetFgColor( GetFgColor() );
  142. m_Labels.AddToTail( vgui::SETUP_PANEL(label) );
  143. }
  144. InvalidateLayout( true );
  145. return true;
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Purpose: Resizes the label
  149. //-----------------------------------------------------------------------------
  150. void CHudHintDisplay::PerformLayout()
  151. {
  152. BaseClass::PerformLayout();
  153. int i;
  154. int wide, tall;
  155. GetSize( wide, tall );
  156. // find the widest line
  157. int iDesiredLabelWide = 0;
  158. for ( i=0; i < m_Labels.Count(); ++i )
  159. {
  160. iDesiredLabelWide = MAX( iDesiredLabelWide, m_Labels[i]->GetWide() );
  161. }
  162. // find the total height
  163. int fontTall = vgui::surface()->GetFontTall( m_hFont );
  164. int labelTall = fontTall * m_Labels.Count();
  165. iDesiredLabelWide += m_iTextX*2;
  166. labelTall += m_iTextY*2;
  167. // Now clamp it to our animation size
  168. iDesiredLabelWide = (iDesiredLabelWide * m_flLabelSizePercentage);
  169. int x, y;
  170. if ( m_iCenterX < 0 )
  171. {
  172. x = 0;
  173. }
  174. else if ( m_iCenterX > 0 )
  175. {
  176. x = wide - iDesiredLabelWide;
  177. }
  178. else
  179. {
  180. x = (wide - iDesiredLabelWide) / 2;
  181. }
  182. if ( m_iCenterY > 0 )
  183. {
  184. y = 0;
  185. }
  186. else if ( m_iCenterY < 0 )
  187. {
  188. y = tall - labelTall;
  189. }
  190. else
  191. {
  192. y = (tall - labelTall) / 2;
  193. }
  194. x = MAX(x,0);
  195. y = MAX(y,0);
  196. iDesiredLabelWide = MIN(iDesiredLabelWide,wide);
  197. m_pLabel->SetBounds( x, y, iDesiredLabelWide, labelTall );
  198. // now lay out the sub-labels
  199. for ( i=0; i<m_Labels.Count(); ++i )
  200. {
  201. int xOffset = (wide - m_Labels[i]->GetWide()) * 0.5;
  202. m_Labels[i]->SetPos( xOffset, y + m_iTextY + i*fontTall );
  203. }
  204. }
  205. //-----------------------------------------------------------------------------
  206. // Purpose: Updates the label color each frame
  207. //-----------------------------------------------------------------------------
  208. void CHudHintDisplay::OnThink()
  209. {
  210. m_pLabel->SetFgColor(GetFgColor());
  211. for (int i = 0; i < m_Labels.Count(); i++)
  212. {
  213. m_Labels[i]->SetFgColor(GetFgColor());
  214. }
  215. // If our label size isn't at the extreme's, we're sliding open / closed
  216. // This is a hack to get around InvalideLayout() not getting called when
  217. // m_flLabelSizePercentage is changed via a HudAnimation.
  218. if ( m_flLabelSizePercentage != 0.0 && m_flLabelSizePercentage != 1.0 || m_bLastLabelUpdateHack )
  219. {
  220. m_bLastLabelUpdateHack = (m_flLabelSizePercentage != 0.0 && m_flLabelSizePercentage != 1.0);
  221. InvalidateLayout();
  222. }
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Purpose: Activates the hint display
  226. //-----------------------------------------------------------------------------
  227. bool CHudHintDisplay::MsgFunc_HintText( const CCSUsrMsg_HintText &msg )
  228. {
  229. #if defined( CSTRIKE15 )
  230. // csgo handles their hint text in sfhudinfopanel
  231. return true;
  232. #endif
  233. char *tmpStr = hudtextmessage->LookupString( msg.text().c_str(), NULL );
  234. LocalizeAndDisplay( tmpStr, msg.text().c_str() );
  235. return true;
  236. }
  237. //-----------------------------------------------------------------------------
  238. // Purpose: Activates the hint display upon recieving a hint
  239. //-----------------------------------------------------------------------------
  240. void CHudHintDisplay::FireGameEvent( IGameEvent * event)
  241. {
  242. const char *hintmessage = event->GetString( "hintmessage" );
  243. char *tmpStr = hudtextmessage->LookupString( hintmessage, NULL );
  244. LocalizeAndDisplay( tmpStr, hintmessage );
  245. }
  246. ConVar sv_hudhint_sound( "sv_hudhint_sound", "1", FCVAR_REPLICATED );
  247. //-----------------------------------------------------------------------------
  248. // Purpose: Localize, display, and animate the hud element
  249. //-----------------------------------------------------------------------------
  250. void CHudHintDisplay::LocalizeAndDisplay( const char *pszHudTxtMsg, const char *szRawString )
  251. {
  252. static wchar_t szBuf[128];
  253. static wchar_t *pszBuf;
  254. // init buffers & pointers
  255. szBuf[0] = 0;
  256. pszBuf = szBuf;
  257. // try to localize
  258. if ( pszHudTxtMsg )
  259. {
  260. pszBuf = g_pVGuiLocalize->Find( pszHudTxtMsg );
  261. }
  262. else
  263. {
  264. pszBuf = g_pVGuiLocalize->Find( szRawString );
  265. }
  266. if ( !pszBuf )
  267. {
  268. // use plain ASCII string
  269. g_pVGuiLocalize->ConvertANSIToUnicode( szRawString, szBuf, sizeof(szBuf) );
  270. pszBuf = szBuf;
  271. }
  272. // make it visible
  273. if ( SetHintText( pszBuf ) )
  274. {
  275. SetVisible( true );
  276. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence( "HintMessageShow" );
  277. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  278. if ( pLocalPlayer )
  279. {
  280. #ifndef HL2MP
  281. if ( sv_hudhint_sound.GetBool() )
  282. {
  283. pLocalPlayer->EmitSound( "Hud.Hint" );
  284. }
  285. #endif // HL2MP
  286. if ( pLocalPlayer->Hints() )
  287. {
  288. pLocalPlayer->Hints()->PlayedAHint();
  289. }
  290. }
  291. }
  292. else
  293. {
  294. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence( "HintMessageHide" );
  295. }
  296. }
  297. //-----------------------------------------------------------------------------
  298. // Purpose: Displays small key-centric hints on the right hand side of the screen
  299. //-----------------------------------------------------------------------------
  300. class CHudHintKeyDisplay : public vgui::Panel, public CHudElement
  301. {
  302. DECLARE_CLASS_SIMPLE( CHudHintKeyDisplay, vgui::Panel );
  303. public:
  304. explicit CHudHintKeyDisplay( const char *pElementName );
  305. void Init();
  306. void Reset();
  307. bool MsgFunc_KeyHintText( const CCSUsrMsg_KeyHintText &msg );
  308. bool ShouldDraw();
  309. bool SetHintText( const char *text );
  310. CUserMessageBinder m_UMCMsgKeyHintText;
  311. protected:
  312. virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
  313. virtual void OnThink();
  314. private:
  315. CUtlVector<vgui::Label *> m_Labels;
  316. vgui::HFont m_hSmallFont, m_hLargeFont;
  317. int m_iBaseY;
  318. CPanelAnimationVarAliasType( float, m_iTextX, "text_xpos", "8", "proportional_float" );
  319. CPanelAnimationVarAliasType( float, m_iTextY, "text_ypos", "8", "proportional_float" );
  320. CPanelAnimationVarAliasType( float, m_iTextGapX, "text_xgap", "8", "proportional_float" );
  321. CPanelAnimationVarAliasType( float, m_iTextGapY, "text_ygap", "8", "proportional_float" );
  322. CPanelAnimationVarAliasType( float, m_iYOffset, "YOffset", "0", "proportional_float" );
  323. };
  324. DECLARE_HUDELEMENT( CHudHintKeyDisplay );
  325. DECLARE_HUD_MESSAGE( CHudHintKeyDisplay, KeyHintText );
  326. //-----------------------------------------------------------------------------
  327. // Purpose: Constructor
  328. //-----------------------------------------------------------------------------
  329. CHudHintKeyDisplay::CHudHintKeyDisplay( const char *pElementName ) : BaseClass(NULL, "HudHintKeyDisplay"), CHudElement( pElementName )
  330. {
  331. vgui::Panel *pParent = GetClientMode()->GetViewport();
  332. SetParent( pParent );
  333. SetVisible( false );
  334. SetAlpha( 0 );
  335. }
  336. //-----------------------------------------------------------------------------
  337. // Purpose:
  338. //-----------------------------------------------------------------------------
  339. void CHudHintKeyDisplay::Init()
  340. {
  341. HOOK_HUD_MESSAGE( CHudHintKeyDisplay, KeyHintText );
  342. }
  343. //-----------------------------------------------------------------------------
  344. // Purpose:
  345. //-----------------------------------------------------------------------------
  346. void CHudHintKeyDisplay::Reset()
  347. {
  348. SetHintText( NULL );
  349. SetAlpha( 0 );
  350. }
  351. //-----------------------------------------------------------------------------
  352. // Purpose:
  353. //-----------------------------------------------------------------------------
  354. void CHudHintKeyDisplay::ApplySchemeSettings( vgui::IScheme *pScheme )
  355. {
  356. m_hSmallFont = pScheme->GetFont( "HudHintTextSmall", true );
  357. m_hLargeFont = pScheme->GetFont( "HudHintTextLarge", true );
  358. BaseClass::ApplySchemeSettings( pScheme );
  359. }
  360. //-----------------------------------------------------------------------------
  361. // Purpose: Save CPU cycles by letting the HUD system early cull
  362. // costly traversal. Called per frame, return true if thinking and
  363. // painting need to occur.
  364. //-----------------------------------------------------------------------------
  365. bool CHudHintKeyDisplay::ShouldDraw( void )
  366. {
  367. // [jason] Moving into Scaleform: sfhudinfopanel
  368. #if defined( CSTRIKE15 )
  369. return false;
  370. #endif
  371. return ( ( GetAlpha() > 0 ) && CHudElement::ShouldDraw() );
  372. }
  373. //-----------------------------------------------------------------------------
  374. // Purpose: Updates the label color each frame
  375. //-----------------------------------------------------------------------------
  376. void CHudHintKeyDisplay::OnThink()
  377. {
  378. for (int i = 0; i < m_Labels.Count(); i++)
  379. {
  380. if ( IsGameConsole() && ( i & 1 ) == 0 )
  381. {
  382. // Don't change the fg color for buttons (even numbered labels)
  383. m_Labels[i]->SetAlpha( GetFgColor().a() );
  384. }
  385. else
  386. {
  387. m_Labels[i]->SetFgColor(GetFgColor());
  388. }
  389. }
  390. int ox, oy;
  391. GetPos(ox, oy);
  392. SetPos( ox, m_iBaseY + m_iYOffset );
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Purpose: Sets the hint text, replacing variables as necessary
  396. //-----------------------------------------------------------------------------
  397. bool CHudHintKeyDisplay::SetHintText( const char *text )
  398. {
  399. if ( text == NULL || text[0] == L'\0' )
  400. return false;
  401. // clear the existing text
  402. for (int i = 0; i < m_Labels.Count(); i++)
  403. {
  404. m_Labels[i]->MarkForDeletion();
  405. }
  406. m_Labels.RemoveAll();
  407. // look up the text string
  408. wchar_t *ws = g_pVGuiLocalize->Find( text );
  409. wchar_t wszBuf[256];
  410. if ( !ws || wcslen(ws) <= 0)
  411. {
  412. g_pVGuiLocalize->ConvertANSIToUnicode(text, wszBuf, sizeof(wszBuf));
  413. ws = wszBuf;
  414. }
  415. // parse out the text into a label set
  416. while ( *ws )
  417. {
  418. wchar_t token[256];
  419. bool isVar = false;
  420. // check for variables
  421. if ( *ws == '%' )
  422. {
  423. isVar = true;
  424. ++ws;
  425. }
  426. // parse out the string
  427. wchar_t *end = wcschr( ws, '%' );
  428. if ( end )
  429. {
  430. wcsncpy( token, ws, MIN( end - ws, ARRAYSIZE(token)) );
  431. token[end - ws] = L'\0'; // force null termination
  432. }
  433. else
  434. {
  435. wcsncpy( token, ws, ARRAYSIZE(token) );
  436. token[ ARRAYSIZE(token) - 1 ] = L'\0'; // force null termination
  437. }
  438. ws += wcslen( token );
  439. if ( isVar )
  440. {
  441. // move over the end of the variable
  442. ++ws;
  443. }
  444. // put it in a label
  445. vgui::Label *label = vgui::SETUP_PANEL(new vgui::Label(this, NULL, token));
  446. bool bIsBitmap = false;
  447. // modify the label if necessary
  448. if ( isVar )
  449. {
  450. label->SetFont( m_hLargeFont );
  451. // lookup key names
  452. char binding[64];
  453. g_pVGuiLocalize->ConvertUnicodeToANSI( token, binding, sizeof(binding) );
  454. //!! change some key names into better names
  455. char friendlyName[64];
  456. if ( IsGameConsole() )
  457. {
  458. int iNumBinds = 0;
  459. char szBuff[ 512 ];
  460. wchar_t szWideBuff[ 64 ];
  461. for ( int iCode = 0; iCode < BUTTON_CODE_LAST; ++iCode )
  462. {
  463. ButtonCode_t code = static_cast<ButtonCode_t>( iCode );
  464. bool bUseThisKey = false;
  465. // Only check against bind name if we haven't already forced this binding to be used
  466. const char *pBinding = gameuifuncs->GetBindingForButtonCode( code );
  467. if ( !pBinding )
  468. continue;
  469. bUseThisKey = ( Q_stricmp( pBinding, binding ) == 0 );
  470. if ( !bUseThisKey &&
  471. ( Q_stricmp( pBinding, "+duck" ) == 0 || Q_stricmp( pBinding, "toggle_duck" ) == 0 ) &&
  472. ( Q_stricmp( binding, "+duck" ) == 0 || Q_stricmp( binding, "toggle_duck" ) == 0 ) )
  473. {
  474. // +duck and toggle_duck are interchangable
  475. bUseThisKey = true;
  476. }
  477. if ( !bUseThisKey &&
  478. ( Q_stricmp( pBinding, "+zoom" ) == 0 || Q_stricmp( pBinding, "toggle_zoom" ) == 0 ) &&
  479. ( Q_stricmp( binding, "+zoom" ) == 0 || Q_stricmp( binding, "toggle_zoom" ) == 0 ) )
  480. {
  481. // +zoom and toggle_zoom are interchangable
  482. bUseThisKey = true;
  483. }
  484. // Don't use this bind in out list
  485. if ( !bUseThisKey )
  486. continue;
  487. // Turn localized string into icon character
  488. Q_snprintf( szBuff, sizeof( szBuff ), "#GameUI_Icons_%s", g_pInputSystem->ButtonCodeToString( static_cast<ButtonCode_t>( iCode ) ) );
  489. g_pVGuiLocalize->ConstructString( szWideBuff, sizeof( szWideBuff ), g_pVGuiLocalize->Find( szBuff ), 0 );
  490. g_pVGuiLocalize->ConvertUnicodeToANSI( szWideBuff, szBuff, sizeof( szBuff ) );
  491. // Add this icon to our list of keys to display
  492. friendlyName[ iNumBinds ] = szBuff[ 0 ];
  493. ++iNumBinds;
  494. }
  495. friendlyName[ iNumBinds ] = '\0';
  496. if ( iNumBinds == 0 )
  497. {
  498. friendlyName[ 0 ] = '\0';
  499. label->SetFont( m_hSmallFont );
  500. label->SetText( "#GameUI_Icons_NONE" );
  501. }
  502. else
  503. {
  504. // 360 always uses bitmaps
  505. bIsBitmap = true;
  506. label->SetText( friendlyName );
  507. }
  508. }
  509. else
  510. {
  511. const char *key = engine->Key_LookupBinding( *binding == '+' ? binding + 1 : binding );
  512. if ( !key )
  513. {
  514. key = "< not bound >";
  515. }
  516. Q_snprintf( friendlyName, sizeof(friendlyName), "#%s", key );
  517. Q_strupr( friendlyName );
  518. // set the variable text - key may need to be localized (button images for example)
  519. wchar_t *locName = g_pVGuiLocalize->Find( friendlyName );
  520. if ( !locName || wcslen(locName) <= 0)
  521. {
  522. label->SetText( friendlyName + 1 );
  523. }
  524. else
  525. {
  526. // Assuming localized vars must be using a bitmap image. *May* not be the case, but since
  527. // keyboard bindings have never been locaized in the past, they probably won't in the future either.
  528. bIsBitmap = true;
  529. label->SetText( locName );
  530. }
  531. }
  532. }
  533. else
  534. {
  535. label->SetFont( m_hSmallFont );
  536. }
  537. label->SetPaintBackgroundEnabled( false );
  538. label->SetPaintBorderEnabled( false );
  539. label->SizeToContents();
  540. label->SetContentAlignment( vgui::Label::a_west );
  541. if ( bIsBitmap && isVar )
  542. {
  543. // Don't change the color of the button art
  544. label->SetFgColor( Color(255,255,255,255) );
  545. }
  546. else
  547. {
  548. label->SetFgColor( GetFgColor() );
  549. }
  550. m_Labels.AddToTail( vgui::SETUP_PANEL(label) );
  551. }
  552. // find the bounds we need to show
  553. int widest1 = 0, widest2 = 0;
  554. for (int i = 0; i < m_Labels.Count(); i++)
  555. {
  556. vgui::Label *label = m_Labels[i];
  557. if (i & 1)
  558. {
  559. // help text
  560. if (label->GetWide() > widest2)
  561. {
  562. widest2 = label->GetWide();
  563. }
  564. }
  565. else
  566. {
  567. // variable
  568. if (label->GetWide() > widest1)
  569. {
  570. widest1 = label->GetWide();
  571. }
  572. }
  573. }
  574. int tallest1 = 0, tallest2 = 0;
  575. for (int i = 0; i < m_Labels.Count(); i++)
  576. {
  577. vgui::Label *label = m_Labels[i];
  578. if (i & 1)
  579. {
  580. // help text
  581. if (label->GetTall() > tallest2)
  582. {
  583. tallest2 = label->GetTall();
  584. }
  585. }
  586. else
  587. {
  588. // variable
  589. if (label->GetTall() > tallest1)
  590. {
  591. tallest1 = label->GetTall();
  592. }
  593. }
  594. }
  595. int tallest = MAX( tallest1, tallest2 );
  596. // position the labels
  597. int col1_x = m_iTextX;
  598. int col2_x = m_iTextX + widest1 + m_iTextGapX;
  599. int col_y = m_iTextY;
  600. // Difference between the variable and the help text
  601. int col_y_extra = ( (tallest1 - tallest2) / 2 );
  602. if ( col_y_extra < 0 )
  603. {
  604. // text is taller than the variable (multi-line text).
  605. // Push the variable's y down by subtracting the negative value.
  606. col_y -= col_y_extra;
  607. }
  608. for (int i = 0; i < m_Labels.Count(); i++)
  609. {
  610. vgui::Label *label = m_Labels[i];
  611. if (i & 1)
  612. {
  613. label->SetPos( col2_x, col_y + col_y_extra );
  614. col_y += tallest;
  615. col_y += m_iTextGapY;
  616. }
  617. else
  618. {
  619. // variable
  620. label->SetPos( col1_x, col_y );
  621. }
  622. }
  623. // move ourselves relative to our start position
  624. int newWide = col2_x + widest2 + m_iTextX;
  625. int newTall = col_y;
  626. int ox, oy;
  627. GetPos(ox, oy);
  628. if (IsRightAligned())
  629. {
  630. int oldWide = GetWide();
  631. int diff = newWide - oldWide;
  632. ox -= diff;
  633. }
  634. if (IsBottomAligned())
  635. {
  636. int oldTall = GetTall();
  637. int diff = newTall - oldTall;
  638. oy -= diff;
  639. }
  640. // set the size of the hint panel to fit
  641. SetPos( ox, oy );
  642. SetSize( newWide, newTall );
  643. m_iBaseY = oy;
  644. return true;
  645. }
  646. //-----------------------------------------------------------------------------
  647. // Purpose: Activates the hint display
  648. //-----------------------------------------------------------------------------
  649. bool CHudHintKeyDisplay::MsgFunc_KeyHintText( const CCSUsrMsg_KeyHintText &msg )
  650. {
  651. // how many strings do we receive ?
  652. int count = msg.hints_size();
  653. // here we expect only one string
  654. if ( count != 1 )
  655. {
  656. DevMsg("CHudHintKeyDisplay::MsgFunc_KeyHintText: string count != 1.\n");
  657. return true;
  658. }
  659. // make it visible
  660. if ( SetHintText( msg.hints(0).c_str() ) )
  661. {
  662. SetVisible( true );
  663. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence( "KeyHintMessageShow" );
  664. }
  665. else
  666. {
  667. // it's being cleared, hide the panel
  668. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence( "KeyHintMessageHide" );
  669. }
  670. return true;
  671. }