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.

1008 lines
24 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. //
  9. // Message.cpp
  10. //
  11. // implementation of CHudMessage class
  12. //
  13. #include "cbase.h"
  14. #include "message.h"
  15. #include "client_textmessage.h"
  16. #include "hud_macros.h"
  17. #include "iclientmode.h"
  18. #include "vgui_controls/Controls.h"
  19. #include "vgui/ILocalize.h"
  20. #include "vgui/IScheme.h"
  21. #include "vgui/ISurface.h"
  22. #include "VGuiMatSurface/IMatSystemSurface.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. #include <ctype.h>
  26. #define NETWORK_MESSAGE1 "__NETMESSAGE__1"
  27. #define NETWORK_MESSAGE2 "__NETMESSAGE__2"
  28. #define NETWORK_MESSAGE3 "__NETMESSAGE__3"
  29. #define NETWORK_MESSAGE4 "__NETMESSAGE__4"
  30. #define NETWORK_MESSAGE5 "__NETMESSAGE__5"
  31. #define NETWORK_MESSAGE6 "__NETMESSAGE__6"
  32. #define MAX_NETMESSAGE 6
  33. // Simultaneous message limit
  34. #define MAX_TEXTMESSAGE_CHARS 2048
  35. static const char *s_NetworkMessageNames[MAX_NETMESSAGE] = { NETWORK_MESSAGE1, NETWORK_MESSAGE2, NETWORK_MESSAGE3, NETWORK_MESSAGE4, NETWORK_MESSAGE5, NETWORK_MESSAGE6 };
  36. //-----------------------------------------------------------------------------
  37. // Purpose:
  38. //-----------------------------------------------------------------------------
  39. void DispatchHudText( const char *pszText )
  40. {
  41. if ( pszText == NULL )
  42. {
  43. (GET_HUDELEMENT( CHudMessage ))->Reset();
  44. }
  45. else
  46. {
  47. (GET_HUDELEMENT( CHudMessage ))->MessageAdd( pszText );
  48. }
  49. }
  50. //
  51. //-----------------------------------------------------
  52. //
  53. DECLARE_HUDELEMENT( CHudMessage );
  54. DECLARE_HUD_MESSAGE( CHudMessage, HudText );
  55. DECLARE_HUD_MESSAGE( CHudMessage, GameTitle );
  56. DECLARE_HUD_MESSAGE( CHudMessage, HudMsg );
  57. ITextMessage *textmessage = NULL;
  58. //-----------------------------------------------------------------------------
  59. // Purpose:
  60. //-----------------------------------------------------------------------------
  61. CHudMessage::CHudMessage( const char *pElementName ) :
  62. CHudElement( pElementName ), BaseClass( NULL, "HudMessage" )
  63. {
  64. vgui::Panel *pParent = GetClientMode()->GetViewport();
  65. SetParent( pParent );
  66. if( textmessage == NULL ) //HACKHACK: Fixes center print text in when MAX_SPLITSCREEN_PLAYERS is greater than 1
  67. {
  68. textmessage = this;
  69. }
  70. m_hFont = g_hFontTrebuchet24;
  71. m_hDefaultFont = m_hFont;
  72. // Clear memory out
  73. ResetCharacters();
  74. }
  75. CHudMessage::~CHudMessage()
  76. {
  77. textmessage = NULL;
  78. }
  79. void CHudMessage::ApplySchemeSettings( IScheme *scheme )
  80. {
  81. BaseClass::ApplySchemeSettings( scheme );
  82. SetPaintBackgroundEnabled( false );
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Purpose:
  86. //-----------------------------------------------------------------------------
  87. void CHudMessage::Init(void)
  88. {
  89. HOOK_HUD_MESSAGE( CHudMessage, HudText );
  90. HOOK_HUD_MESSAGE( CHudMessage, GameTitle );
  91. HOOK_HUD_MESSAGE( CHudMessage, HudMsg );
  92. Reset();
  93. };
  94. //-----------------------------------------------------------------------------
  95. // Purpose:
  96. //-----------------------------------------------------------------------------
  97. void CHudMessage::VidInit( void )
  98. {
  99. m_iconTitleHalf = HudIcons().GetIcon( "title_half" );
  100. m_iconTitleLife = HudIcons().GetIcon( "title_life" );
  101. };
  102. //-----------------------------------------------------------------------------
  103. // Purpose:
  104. //-----------------------------------------------------------------------------
  105. void CHudMessage::Reset( void )
  106. {
  107. memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages );
  108. memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages );
  109. m_gameTitleTime = 0;
  110. m_pGameTitle = NULL;
  111. m_bHaveMessage = false;
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Purpose:
  115. //-----------------------------------------------------------------------------
  116. float CHudMessage::FadeBlend( float fadein, float fadeout, float hold, float localTime )
  117. {
  118. float fadeTime = fadein + hold;
  119. float fadeBlend;
  120. if ( localTime < 0 )
  121. return 0;
  122. if ( localTime < fadein )
  123. {
  124. fadeBlend = 1 - ((fadein - localTime) / fadein);
  125. }
  126. else if ( localTime > fadeTime )
  127. {
  128. if ( fadeout > 0 )
  129. fadeBlend = 1 - ((localTime - fadeTime) / fadeout);
  130. else
  131. fadeBlend = 0;
  132. }
  133. else
  134. fadeBlend = 1;
  135. return fadeBlend;
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Purpose:
  139. //-----------------------------------------------------------------------------
  140. int CHudMessage::XPosition( float x, int width, int totalWidth )
  141. {
  142. int xPos;
  143. if ( x == -1 )
  144. {
  145. xPos = (ScreenWidth() - width) / 2;
  146. }
  147. else
  148. {
  149. if ( x < 0 )
  150. xPos = (1.0 + x) * ScreenWidth() - totalWidth; // Align to right
  151. else
  152. xPos = x * ScreenWidth();
  153. }
  154. if ( xPos + width > ScreenWidth() )
  155. xPos = ScreenWidth() - width;
  156. else if ( xPos < 0 )
  157. xPos = 0;
  158. return xPos;
  159. }
  160. //-----------------------------------------------------------------------------
  161. // Purpose:
  162. //-----------------------------------------------------------------------------
  163. int CHudMessage::YPosition( float y, int height )
  164. {
  165. int yPos;
  166. if ( y == -1 ) // Centered?
  167. yPos = (ScreenHeight() - height) * 0.5;
  168. else
  169. {
  170. // Alight bottom?
  171. if ( y < 0 )
  172. yPos = (1.0 + y) * ScreenHeight() - height; // Alight bottom
  173. else // align top
  174. yPos = y * ScreenHeight();
  175. }
  176. if ( yPos + height > ScreenHeight() )
  177. yPos = ScreenHeight() - height;
  178. else if ( yPos < 0 )
  179. yPos = 0;
  180. return yPos;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Purpose:
  184. //-----------------------------------------------------------------------------
  185. void CHudMessage::MessageScanNextChar( void )
  186. {
  187. int srcRed, srcGreen, srcBlue, destRed, destGreen, destBlue;
  188. int blend;
  189. srcRed = m_parms.pMessage->r1;
  190. srcGreen = m_parms.pMessage->g1;
  191. srcBlue = m_parms.pMessage->b1;
  192. blend = 0; // Pure source
  193. destRed = destGreen = destBlue = 0;
  194. switch( m_parms.pMessage->effect )
  195. {
  196. // Fade-in / Fade-out
  197. case 0:
  198. case 1:
  199. destRed = destGreen = destBlue = 0;
  200. blend = m_parms.fadeBlend;
  201. break;
  202. case 2:
  203. m_parms.charTime += m_parms.pMessage->fadein;
  204. if ( m_parms.charTime > m_parms.time )
  205. {
  206. srcRed = srcGreen = srcBlue = 0;
  207. blend = 0; // pure source
  208. }
  209. else
  210. {
  211. float deltaTime = m_parms.time - m_parms.charTime;
  212. destRed = destGreen = destBlue = 0;
  213. if ( m_parms.time > m_parms.fadeTime )
  214. {
  215. blend = m_parms.fadeBlend;
  216. }
  217. else if ( deltaTime > m_parms.pMessage->fxtime )
  218. blend = 0; // pure dest
  219. else
  220. {
  221. destRed = m_parms.pMessage->r2;
  222. destGreen = m_parms.pMessage->g2;
  223. destBlue = m_parms.pMessage->b2;
  224. blend = 255 - (deltaTime * (1.0/m_parms.pMessage->fxtime) * 255.0 + 0.5);
  225. }
  226. }
  227. break;
  228. }
  229. if ( blend > 255 )
  230. blend = 255;
  231. else if ( blend < 0 )
  232. blend = 0;
  233. m_parms.r = ((srcRed * (255-blend)) + (destRed * blend)) >> 8;
  234. m_parms.g = ((srcGreen * (255-blend)) + (destGreen * blend)) >> 8;
  235. m_parms.b = ((srcBlue * (255-blend)) + (destBlue * blend)) >> 8;
  236. #if 0
  237. if ( m_parms.pMessage->effect == 1 && m_parms.charTime != 0 )
  238. {
  239. textmessage->AddChar( m_parms.pMessage->r2, m_parms.pMessage->g2, m_parms.pMessage->b2, 255, m_parms.text );
  240. }
  241. #endif
  242. }
  243. void CHudMessage::SetFont( HScheme scheme, const char *pFontName )
  244. {
  245. vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( scheme );
  246. if ( pScheme )
  247. {
  248. bool bProportional = false;
  249. #ifdef PORTAL2
  250. bProportional = true;
  251. #endif
  252. vgui::HFont font = pScheme->GetFont( pFontName, bProportional );
  253. textmessage->SetFont( font );
  254. m_parms.font = font;
  255. }
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Purpose:
  259. //-----------------------------------------------------------------------------
  260. void CHudMessage::MessageScanStart( void )
  261. {
  262. switch( m_parms.pMessage->effect )
  263. {
  264. // Fade-in / out with flicker
  265. case 1:
  266. case 0:
  267. m_parms.fadeTime = m_parms.pMessage->fadein + m_parms.pMessage->holdtime;
  268. if ( m_parms.time < m_parms.pMessage->fadein )
  269. {
  270. m_parms.fadeBlend = ((m_parms.pMessage->fadein - m_parms.time) * (1.0/m_parms.pMessage->fadein) * 255);
  271. }
  272. else if ( m_parms.time > m_parms.fadeTime )
  273. {
  274. if ( m_parms.pMessage->fadeout > 0 )
  275. m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255);
  276. else
  277. m_parms.fadeBlend = 255; // Pure dest (off)
  278. }
  279. else
  280. m_parms.fadeBlend = 0; // Pure source (on)
  281. m_parms.charTime = 0;
  282. if ( m_parms.pMessage->effect == 1 && (rand()%100) < 10 )
  283. m_parms.charTime = 1;
  284. break;
  285. case 2:
  286. m_parms.fadeTime = (m_parms.pMessage->fadein * m_parms.length) + m_parms.pMessage->holdtime;
  287. if ( m_parms.time > m_parms.fadeTime && m_parms.pMessage->fadeout > 0 )
  288. m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255);
  289. else
  290. m_parms.fadeBlend = 0;
  291. break;
  292. }
  293. m_parms.font = g_hFontTrebuchet24;
  294. if ( m_parms.vguiFontName != NULL &&
  295. m_parms.vguiFontName[ 0 ] )
  296. {
  297. #ifdef PORTAL2
  298. SetFont( vgui::scheme()->GetScheme( "basemodui_scheme" ), m_parms.vguiFontName );
  299. #else
  300. SetFont( vgui::scheme()->GetDefaultScheme(), m_parms.vguiFontName );
  301. #endif
  302. }
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Purpose:
  306. //-----------------------------------------------------------------------------
  307. void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time )
  308. {
  309. int i, j, length, width;
  310. const wchar_t *pText;
  311. wchar_t textBuf[ 1024 ];
  312. {
  313. // look up in localization table
  314. // strip off any trailing newlines
  315. int len = Q_strlen( pMessage->pMessage );
  316. int tempLen = len + 2;
  317. char *localString = (char *)stackalloc( tempLen );
  318. Q_strncpy( localString, pMessage->pMessage, tempLen );
  319. if (len > 0 && V_iscntrl(localString[len - 1]))
  320. {
  321. localString[len - 1] = 0;
  322. }
  323. pText = g_pVGuiLocalize->Find( localString );
  324. if ( !pText )
  325. {
  326. g_pVGuiLocalize->ConvertANSIToUnicode( pMessage->pMessage, textBuf, sizeof( textBuf ) );
  327. pText = textBuf;
  328. }
  329. }
  330. const wchar_t *pPerm = pText;
  331. // Count lines
  332. m_parms.lines = 1;
  333. m_parms.time = time;
  334. m_parms.pMessage = pMessage;
  335. length = 0;
  336. width = 0;
  337. m_parms.totalWidth = 0;
  338. m_parms.vguiFontName = pMessage->pVGuiSchemeFontName;
  339. if ( m_parms.font == 0 )
  340. {
  341. if ( m_parms.vguiFontName != NULL &&
  342. m_parms.vguiFontName[ 0 ] )
  343. {
  344. #ifdef PORTAL2
  345. SetFont( vgui::scheme()->GetScheme( "basemodui_scheme" ), m_parms.vguiFontName );
  346. #else
  347. SetFont( vgui::scheme()->GetDefaultScheme(), m_parms.vguiFontName );
  348. #endif
  349. }
  350. else
  351. {
  352. m_parms.font = g_hFontTrebuchet24;
  353. }
  354. }
  355. while ( *pText )
  356. {
  357. if ( *pText == '\n' )
  358. {
  359. m_parms.lines++;
  360. if ( width > m_parms.totalWidth )
  361. m_parms.totalWidth = width;
  362. width = 0;
  363. }
  364. else
  365. {
  366. width += vgui::surface()->GetCharacterWidth( m_parms.font, *pText );
  367. }
  368. pText++;
  369. length++;
  370. }
  371. if ( width > m_parms.totalWidth )
  372. m_parms.totalWidth = width;
  373. m_parms.length = length;
  374. int fontHeight = vgui::surface()->GetFontTall( m_parms.font );
  375. m_parms.totalHeight = ( m_parms.lines * fontHeight );
  376. m_parms.y = YPosition( pMessage->y, m_parms.totalHeight );
  377. pText = pPerm;
  378. m_parms.charTime = 0;
  379. float flBoxPixels = 0.0f;
  380. MessageScanStart();
  381. if ( pMessage->bRoundedRectBackdropBox )
  382. {
  383. // 2.0f since we have extra space at both the top and bottom
  384. flBoxPixels = pMessage->flBoxSize * fontHeight;
  385. // Draw the box
  386. int boxx = XPosition( pMessage->x, m_parms.totalWidth, m_parms.totalWidth );
  387. int boxy = YPosition( pMessage->y, m_parms.totalHeight );
  388. boxx -= flBoxPixels;
  389. boxy -= flBoxPixels * 0.5f;
  390. float flAlphaScale = clamp( ( 255.0f - (float)m_parms.fadeBlend ) / 255.0f, 0.0f, 1.0f );
  391. Color boxColor(
  392. pMessage->boxcolor[ 0 ],
  393. pMessage->boxcolor[ 1 ],
  394. pMessage->boxcolor[ 2 ],
  395. pMessage->boxcolor[ 3 ] * flAlphaScale );
  396. DrawBox( boxx, boxy, m_parms.totalWidth + 2.0f * flBoxPixels, m_parms.totalHeight + 2.0f * flBoxPixels * 0.5f, boxColor, 1.0f );
  397. }
  398. wchar_t line[ 512 ];
  399. for ( i = 0; i < m_parms.lines; i++ )
  400. {
  401. m_parms.lineLength = 0;
  402. m_parms.width = 0;
  403. while ( *pText && *pText != '\n' )
  404. {
  405. wchar_t c = *pText;
  406. line[m_parms.lineLength] = c;
  407. m_parms.width += vgui::surface()->GetCharacterWidth( m_parms.font, c);
  408. m_parms.lineLength++;
  409. if ( m_parms.lineLength > (ARRAYSIZE(line)-1) )
  410. {
  411. m_parms.lineLength = ARRAYSIZE(line)-1;
  412. }
  413. pText++;
  414. }
  415. pText++; // Skip LF
  416. line[m_parms.lineLength] = 0;
  417. m_parms.x = XPosition( pMessage->x, m_parms.width, m_parms.totalWidth );
  418. textmessage->SetPosition( m_parms.x, m_parms.y );
  419. if (m_parms.fadeBlend > 255)
  420. m_parms.fadeBlend = 255;
  421. for ( j = 0; j < m_parms.lineLength; j++ )
  422. {
  423. m_parms.text = line[j];
  424. MessageScanNextChar();
  425. textmessage->AddChar( m_parms.r, m_parms.g, m_parms.b, 255 - m_parms.fadeBlend, m_parms.text );
  426. }
  427. m_parms.y += vgui::surface()->GetFontTall( m_parms.font );
  428. }
  429. // Restore default font
  430. textmessage->SetDefaultFont();
  431. }
  432. //-----------------------------------------------------------------------------
  433. // Purpose:
  434. //-----------------------------------------------------------------------------
  435. bool CHudMessage::ShouldDraw( void )
  436. {
  437. return ( CHudElement::ShouldDraw() &&
  438. ( m_bHaveMessage || m_Messages.Count() ) );
  439. }
  440. //-----------------------------------------------------------------------------
  441. // Purpose:
  442. //-----------------------------------------------------------------------------
  443. void CHudMessage::Paint()
  444. {
  445. int i, drawn;
  446. client_textmessage_t *pMessage;
  447. float endTime;
  448. drawn = 0;
  449. if ( m_gameTitleTime > 0 )
  450. {
  451. float localTime = gpGlobals->curtime - m_gameTitleTime;
  452. float brightness;
  453. // Maybe timer isn't set yet
  454. if ( m_gameTitleTime > gpGlobals->curtime )
  455. {
  456. m_gameTitleTime = gpGlobals->curtime;
  457. }
  458. if ( localTime > (m_pGameTitle->fadein + m_pGameTitle->holdtime + m_pGameTitle->fadeout) )
  459. {
  460. m_gameTitleTime = 0;
  461. }
  462. else
  463. {
  464. brightness = FadeBlend( m_pGameTitle->fadein, m_pGameTitle->fadeout, m_pGameTitle->holdtime, localTime );
  465. int halfWidth = m_iconTitleHalf->Width();
  466. int fullWidth = halfWidth + m_iconTitleLife->Width();
  467. int fullHeight = m_iconTitleHalf->Height();
  468. int x = XPosition( m_pGameTitle->x, fullWidth, fullWidth );
  469. int y = YPosition( m_pGameTitle->y, fullHeight );
  470. m_iconTitleHalf->DrawSelf( x, y, Color( m_pGameTitle->r1, m_pGameTitle->g1, m_pGameTitle->b1, brightness * 255 ) );
  471. m_iconTitleLife->DrawSelf( x + halfWidth, y, Color( m_pGameTitle->r1, m_pGameTitle->g1, m_pGameTitle->b1, brightness * 255 ) );
  472. drawn = 1;
  473. }
  474. }
  475. // Fixup level transitions
  476. for ( i = 0; i < maxHUDMessages; i++ )
  477. {
  478. // Assume m_parms.time contains last time
  479. if ( m_pMessages[i] )
  480. {
  481. pMessage = m_pMessages[i];
  482. if ( m_startTime[i] > gpGlobals->curtime )
  483. m_startTime[i] = gpGlobals->curtime + m_parms.time - m_startTime[i] + 0.2; // Server takes 0.2 seconds to spawn, adjust for this
  484. }
  485. }
  486. for ( i = 0; i < maxHUDMessages; i++ )
  487. {
  488. if ( m_pMessages[i] )
  489. {
  490. pMessage = m_pMessages[i];
  491. // This is when the message is over
  492. switch( pMessage->effect )
  493. {
  494. case 0:
  495. case 1:
  496. endTime = m_startTime[i] + pMessage->fadein + pMessage->fadeout + pMessage->holdtime;
  497. break;
  498. // Fade in is per character in scanning messages
  499. case 2:
  500. endTime = m_startTime[i] + (pMessage->fadein * strlen( pMessage->pMessage )) + pMessage->fadeout + pMessage->holdtime;
  501. break;
  502. default:
  503. endTime = 0;
  504. break;
  505. }
  506. if ( gpGlobals->curtime <= endTime )
  507. {
  508. float messageTime = gpGlobals->curtime - m_startTime[i];
  509. // Draw the message
  510. // effect 0 is fade in/fade out
  511. // effect 1 is flickery credits
  512. // effect 2 is write out (training room)
  513. MessageDrawScan( pMessage, messageTime );
  514. drawn++;
  515. }
  516. else
  517. {
  518. // The message is over
  519. m_pMessages[i] = NULL;
  520. }
  521. }
  522. }
  523. // Remember the time -- to fix up level transitions
  524. m_parms.time = gpGlobals->curtime;
  525. // Did we draw any messages?
  526. if ( !drawn )
  527. {
  528. m_bHaveMessage = false;
  529. }
  530. PaintCharacters();
  531. }
  532. //-----------------------------------------------------------------------------
  533. // Purpose:
  534. //-----------------------------------------------------------------------------
  535. void CHudMessage::MessageAdd( const char *pName )
  536. {
  537. int i;
  538. float time = gpGlobals->curtime;
  539. client_textmessage_t *pMessage = NULL;
  540. if ( pName[0] == '#' )
  541. {
  542. pMessage = TextMessageGet( pName+1 );
  543. }
  544. else
  545. {
  546. pMessage = TextMessageGet( pName );
  547. }
  548. if ( !pMessage )
  549. return;
  550. if ( pMessage->pClearMessage )
  551. {
  552. for ( i = 0; i < maxHUDMessages; i++ )
  553. {
  554. if ( m_pMessages[ i ] && !Q_stricmp( m_pMessages[ i ]->pName, pMessage->pClearMessage ) )
  555. {
  556. m_startTime[ i ] = 0.0f;
  557. m_pMessages[ i ] = NULL;
  558. break;
  559. }
  560. }
  561. }
  562. for ( i = 0; i < maxHUDMessages; i++ )
  563. {
  564. if ( !m_pMessages[i] )
  565. {
  566. m_pMessages[i] = pMessage;
  567. m_startTime[i] = time;
  568. break;
  569. }
  570. }
  571. // Remember the time -- to fix up level transitions
  572. m_parms.time = time;
  573. m_bHaveMessage = true;
  574. // Force this now so that SCR_UpdateScreen will paint the panel immediately!!!
  575. SetVisible( true );
  576. }
  577. //-----------------------------------------------------------------------------
  578. // Purpose:
  579. //-----------------------------------------------------------------------------
  580. bool CHudMessage::MsgFunc_HudText(const CCSUsrMsg_HudText &msg)
  581. {
  582. MessageAdd( msg.text().c_str() );
  583. return true;
  584. }
  585. #include "ivieweffects.h"
  586. #include "shake.h"
  587. //-----------------------------------------------------------------------------
  588. // Purpose:
  589. //-----------------------------------------------------------------------------
  590. bool CHudMessage::MsgFunc_GameTitle(const CCSUsrMsg_GameTitle &msg)
  591. {
  592. m_pGameTitle = TextMessageGet( "GAMETITLE" );
  593. if ( m_pGameTitle != NULL )
  594. {
  595. m_gameTitleTime = gpGlobals->curtime;
  596. m_bHaveMessage = true;
  597. }
  598. // if ( READ_BYTE() )
  599. {
  600. ScreenFade_t sf;
  601. memset( &sf, 0, sizeof( sf ) );
  602. sf.a = 255;
  603. sf.r = 0;
  604. sf.g = 0;
  605. sf.b = 0;
  606. sf.duration = (float)(1<<SCREENFADE_FRACBITS) * 5.0f;
  607. sf.holdTime = (float)(1<<SCREENFADE_FRACBITS) * 1.0f;
  608. sf.fadeFlags = FFADE_IN | FFADE_PURGE;
  609. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  610. {
  611. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  612. GetViewEffects()->Fade( sf );
  613. }
  614. Msg( "%i gametitle fade\n", gpGlobals->framecount );
  615. }
  616. return true;
  617. }
  618. bool CHudMessage::MsgFunc_HudMsg(const CCSUsrMsg_HudMsg &msg)
  619. {
  620. // Position command $position x y
  621. // x & y are from 0 to 1 to be screen resolution independent
  622. // -1 means center in each dimension
  623. // Effect command $effect <effect number>
  624. // effect 0 is fade in/fade out
  625. // effect 1 is flickery credits
  626. // effect 2 is write out (training room)
  627. // Text color r g b command $color
  628. // Text color r g b command $color2
  629. // fadein time fadeout time / hold time
  630. // $fadein (message fade in time - per character in effect 2)
  631. // $fadeout (message fade out time)
  632. // $holdtime (stay on the screen for this long)
  633. int channel = msg.channel() % MAX_NETMESSAGE; // Pick the buffer
  634. client_textmessage_t *pNetMessage = TextMessageGet( s_NetworkMessageNames[ channel ] );
  635. if ( !pNetMessage || !pNetMessage->pMessage )
  636. return true;
  637. pNetMessage->x = msg.pos().x();
  638. pNetMessage->y = msg.pos().y();
  639. pNetMessage->r1 = msg.clr1().r();
  640. pNetMessage->g1 = msg.clr1().g();
  641. pNetMessage->b1 = msg.clr1().b();
  642. pNetMessage->a1 = msg.clr1().a();
  643. pNetMessage->r2 = msg.clr2().r();
  644. pNetMessage->g2 = msg.clr2().g();
  645. pNetMessage->b2 = msg.clr2().b();
  646. pNetMessage->a2 = msg.clr2().a();
  647. pNetMessage->effect = msg.effect();
  648. pNetMessage->fadein = msg.fade_in_time();
  649. pNetMessage->fadeout = msg.fade_out_time();
  650. pNetMessage->holdtime = msg.hold_time();
  651. pNetMessage->fxtime = msg.fx_time();
  652. #ifdef PORTAL2
  653. // hack to make the chapter title channel define the font size in Portal 2
  654. if ( channel == 2 || channel == 3 )
  655. {
  656. const char *pFontName;
  657. if ( channel == 2 )
  658. pFontName = "InGameChapterTitle";
  659. else
  660. pFontName = "InGameChapterSubtitle";
  661. pNetMessage->pVGuiSchemeFontName = pFontName;
  662. }
  663. #endif
  664. pNetMessage->pName = s_NetworkMessageNames[ channel ];
  665. // see tmessage.cpp why 512
  666. Q_strncpy( (char*)pNetMessage->pMessage, msg.text().c_str(), 512 );
  667. MessageAdd( pNetMessage->pName );
  668. return true;
  669. }
  670. //-----------------------------------------------------------------------------
  671. // Purpose: Get font sizes
  672. // Input : *pWidth -
  673. // Output : int
  674. //-----------------------------------------------------------------------------
  675. int CHudMessage::GetFontInfo( FONTABC *pABCs, vgui::HFont hFont )
  676. {
  677. int i;
  678. if ( !hFont )
  679. {
  680. hFont = m_hFont;
  681. }
  682. if ( !hFont )
  683. return 0;
  684. if ( pABCs )
  685. {
  686. for ( i =0; i < 256; i++ )
  687. {
  688. int a, b, c;
  689. vgui::surface()->GetCharABCwide( hFont, (char)i, a, b, c );
  690. pABCs[i].abcA = a;
  691. pABCs[i].abcB = b;
  692. pABCs[i].abcC = c;
  693. pABCs[i].total = a+b+c;
  694. }
  695. }
  696. return vgui::surface()->GetFontTall( hFont );
  697. }
  698. //-----------------------------------------------------------------------------
  699. // Purpose: Clear all messages out of active list, etc.
  700. //-----------------------------------------------------------------------------
  701. void CHudMessage::ResetCharacters( void )
  702. {
  703. m_Messages.Purge();
  704. }
  705. //-----------------------------------------------------------------------------
  706. // Purpose: Grab next free message, if any
  707. // Output : CTextMessagePanel::message_t
  708. //-----------------------------------------------------------------------------
  709. CHudMessage::message_t *CHudMessage::AllocMessage( void )
  710. {
  711. message_t *msg;
  712. if ( m_Messages.Count() >= MAX_TEXTMESSAGE_CHARS )
  713. return NULL;
  714. msg = &m_Messages[ m_Messages.AddToTail() ];
  715. msg->type = TYPE_UNKNOWN;
  716. msg->x = 0;
  717. msg->y = 0;
  718. msg->ch = 0;
  719. msg->r = 0;
  720. msg->g = 0;
  721. msg->b = 0;
  722. msg->a = 0;
  723. msg->font = 0;
  724. SetVisible( true );
  725. return msg;
  726. }
  727. //-----------------------------------------------------------------------------
  728. // Purpose:
  729. // Input : x -
  730. // y -
  731. //-----------------------------------------------------------------------------
  732. void CHudMessage::SetPosition( int x, int y )
  733. {
  734. message_t *msg = AllocMessage();
  735. if ( !msg )
  736. return;
  737. msg->type = TYPE_POSITION;
  738. // Used fields
  739. msg->x = x;
  740. msg->y = y;
  741. }
  742. //-----------------------------------------------------------------------------
  743. // Purpose: Adds a character to the active list, if possible
  744. // Input : x -
  745. // y -
  746. // r -
  747. // g -
  748. // b -
  749. // a -
  750. // ch -
  751. // Output : int
  752. //-----------------------------------------------------------------------------
  753. void CHudMessage::AddChar( int r, int g, int b, int a, wchar_t ch )
  754. {
  755. message_t *msg = AllocMessage();
  756. if ( !msg )
  757. return;
  758. msg->type = TYPE_CHARACTER;
  759. // Used fields
  760. msg->r = r;
  761. msg->g = g;
  762. msg->b = b;
  763. msg->a = a;
  764. msg->ch = ch;
  765. }
  766. //-----------------------------------------------------------------------------
  767. // Purpose: Determine width and height of specified string
  768. // Input : *wide -
  769. // *tall -
  770. // *string -
  771. //-----------------------------------------------------------------------------
  772. void CHudMessage::GetTextExtents( int *wide, int *tall, const char *string )
  773. {
  774. *wide = g_pMatSystemSurface->DrawTextLen( m_hFont, "%s", (char *)string );
  775. *tall = vgui::surface()->GetFontTall( m_hFont );
  776. }
  777. //-----------------------------------------------------------------------------
  778. // Purpose:
  779. //-----------------------------------------------------------------------------
  780. void CHudMessage::SetFont( vgui::HFont hCustomFont )
  781. {
  782. m_hFont = hCustomFont;
  783. message_t *msg = AllocMessage();
  784. if ( !msg )
  785. return;
  786. msg->type = TYPE_FONT;
  787. // Used fields
  788. msg->font = m_hFont;
  789. }
  790. //-----------------------------------------------------------------------------
  791. // Purpose:
  792. //-----------------------------------------------------------------------------
  793. void CHudMessage::SetDefaultFont( void )
  794. {
  795. SetFont( m_hDefaultFont );
  796. }
  797. //-----------------------------------------------------------------------------
  798. // Purpose: Draw current text items
  799. //-----------------------------------------------------------------------------
  800. void CHudMessage::PaintCharacters()
  801. {
  802. int xpos = 0, ypos = 0;
  803. vgui::surface()->DrawSetTextFont( m_hFont );
  804. int messageCount = m_Messages.Count();
  805. for ( int i = 0 ; i < messageCount; ++i )
  806. {
  807. message_t *msg = &m_Messages[ i ];
  808. switch ( msg->type )
  809. {
  810. default:
  811. case TYPE_UNKNOWN:
  812. Assert( 0 );
  813. break;
  814. case TYPE_POSITION:
  815. xpos = msg->x;
  816. ypos = msg->y;
  817. break;
  818. case TYPE_FONT:
  819. m_hFont = msg->font;
  820. vgui::surface()->DrawSetTextFont( m_hFont );
  821. break;
  822. case TYPE_CHARACTER:
  823. if ( m_hFont )
  824. {
  825. int a, b, c;
  826. vgui::surface()->GetCharABCwide( m_hFont, msg->ch, a, b, c );
  827. if ( msg->ch > 32 )
  828. {
  829. vgui::surface()->DrawSetTextColor( msg->r, msg->g, msg->b, msg->a );
  830. vgui::surface()->DrawSetTextPos( xpos, ypos );
  831. vgui::surface()->DrawUnicodeChar( msg->ch );
  832. }
  833. xpos += a + b + c;
  834. }
  835. break;
  836. }
  837. }
  838. ResetCharacters();
  839. }
  840. void CHudMessage::GetLength( int *wide, int *tall, const char *string )
  841. {
  842. GetTextExtents( wide, tall, string );
  843. }