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.

465 lines
11 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. #include "cbase.h"
  10. #include <stdarg.h>
  11. #include "imessagechars.h"
  12. #include <vgui/IVGui.h>
  13. #include "VGuiMatSurface/IMatSystemSurface.h"
  14. #include <vgui_controls/Panel.h>
  15. #include <vgui_controls/Controls.h>
  16. #include <vgui/IScheme.h>
  17. #include <vgui/ISurface.h>
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. // Simultaneous message limit
  21. #define MAX_MESSAGECHARS_MESSAGES 1024
  22. #define MAX_MESSAGECHARSPANEL_LEN 1024
  23. //-----------------------------------------------------------------------------
  24. // Purpose: Panel for displaying console characters at specified locations
  25. //-----------------------------------------------------------------------------
  26. class CMessageCharsPanel : public vgui::Panel
  27. {
  28. typedef vgui::Panel BaseClass;
  29. public:
  30. // Internal pool of such messages
  31. typedef struct message_s
  32. {
  33. struct message_s *next;
  34. int x, y;
  35. byte r, g, b, a;
  36. char *text;
  37. vgui::HFont hCustomFont;
  38. float fTTL;
  39. int messageID;
  40. } message_t;
  41. // Construct/destruct
  42. explicit CMessageCharsPanel( vgui::VPANEL parent );
  43. virtual ~CMessageCharsPanel( void );
  44. // Add block of text to list
  45. virtual int AddText(
  46. float flTime,
  47. vgui::HFont hCustomFont,
  48. int x,
  49. int y,
  50. int r,
  51. int g,
  52. int b,
  53. int a,
  54. char *fmt,
  55. int messageID,
  56. ... );
  57. // Determine text side and height
  58. virtual void GetTextExtents( vgui::HFont hCustomFont, int *wide, int *tall, const char *string );
  59. virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
  60. virtual void Paint();
  61. virtual void OnTick( void );
  62. virtual bool ShouldDraw( void );
  63. void RemoveStringsByID( int messageID );
  64. void Clear( void );
  65. private:
  66. // Allocate a new message
  67. message_t *AllocMessage( void );
  68. // Clear out all messages
  69. void Reset( void );
  70. vgui::HFont m_hFont;
  71. // Pool of messages
  72. message_t m_Messages[ MAX_MESSAGECHARS_MESSAGES ];
  73. message_t *m_pActive;
  74. message_t *m_pFree;
  75. };
  76. //-----------------------------------------------------------------------------
  77. // Purpose:
  78. // Input : *parent -
  79. // Output :
  80. //-----------------------------------------------------------------------------
  81. CMessageCharsPanel::CMessageCharsPanel( vgui::VPANEL parent ) :
  82. BaseClass( NULL, "CMessageCharsPanel" )
  83. {
  84. SetParent( parent );
  85. SetSize( ScreenWidth(), ScreenHeight() );
  86. SetPos( 0, 0 );
  87. SetVisible( true );
  88. SetCursor( 0 );
  89. SetKeyBoardInputEnabled( false );
  90. SetMouseInputEnabled( false );
  91. m_hFont = vgui::INVALID_FONT;
  92. SetFgColor( Color( 0, 0, 0, 255 ) );
  93. SetPaintBackgroundEnabled( false );
  94. Q_memset( m_Messages, 0, sizeof( m_Messages ) );
  95. Reset();
  96. vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Purpose:
  100. // Output :
  101. //-----------------------------------------------------------------------------
  102. CMessageCharsPanel::~CMessageCharsPanel( void )
  103. {
  104. }
  105. void CMessageCharsPanel::ApplySchemeSettings(vgui::IScheme *pScheme)
  106. {
  107. BaseClass::ApplySchemeSettings(pScheme);
  108. m_hFont = pScheme->GetFont( "Default" );
  109. Assert( m_hFont != vgui::INVALID_FONT );
  110. SetSize( ScreenWidth(), ScreenHeight() );
  111. SetPos( 0, 0 );
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Purpose:
  115. //-----------------------------------------------------------------------------
  116. void CMessageCharsPanel::Clear( void )
  117. {
  118. Reset();
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose: Reset all messages
  122. //-----------------------------------------------------------------------------
  123. void CMessageCharsPanel::Reset( void )
  124. {
  125. m_pActive = NULL;
  126. int i;
  127. for( i = 0; i < MAX_MESSAGECHARS_MESSAGES-1; i++ )
  128. {
  129. if ( m_Messages[ i ].text )
  130. {
  131. delete[] m_Messages[ i ].text;
  132. m_Messages[ i ].text = NULL;
  133. }
  134. m_Messages[ i ].next = &m_Messages[ i + 1 ];
  135. }
  136. m_Messages[ i ].next = NULL;
  137. m_pFree = &m_Messages[ 0 ];
  138. SetVisible( false );
  139. }
  140. //-----------------------------------------------------------------------------
  141. // Purpose: Allocate a message if possible
  142. // Output : CMessageCharsPanel::message_t
  143. //-----------------------------------------------------------------------------
  144. CMessageCharsPanel::message_t *CMessageCharsPanel::AllocMessage( void )
  145. {
  146. CMessageCharsPanel::message_t *msg;
  147. if ( !m_pFree )
  148. return NULL;
  149. msg = m_pFree;
  150. m_pFree = m_pFree->next;
  151. msg->next = m_pActive;
  152. m_pActive = msg;
  153. msg->x = 0;
  154. msg->y = 0;
  155. msg->text = NULL;
  156. msg->hCustomFont = NULL;
  157. return msg;
  158. }
  159. //-----------------------------------------------------------------------------
  160. // Purpose: Allocate message and fill in data
  161. // Input : x -
  162. // y -
  163. // *fmt -
  164. // ... -
  165. // Output : int
  166. //-----------------------------------------------------------------------------
  167. int CMessageCharsPanel::AddText(
  168. float flTime,
  169. vgui::HFont hCustomFont,
  170. int x,
  171. int y,
  172. int r,
  173. int g,
  174. int b,
  175. int a,
  176. char *fmt,
  177. int messageID,
  178. ... )
  179. {
  180. va_list argptr;
  181. char data[ MAX_MESSAGECHARSPANEL_LEN ];
  182. int len;
  183. va_start(argptr, messageID);
  184. len = Q_vsnprintf(data, sizeof( data ), fmt, argptr);
  185. va_end(argptr);
  186. data[ MAX_MESSAGECHARSPANEL_LEN - 1 ] = 0;
  187. CMessageCharsPanel::message_t *msg = AllocMessage();
  188. if ( !msg )
  189. return x;
  190. msg->x = x;
  191. msg->y = y;
  192. msg->r = r;
  193. msg->g = g;
  194. msg->b = b;
  195. msg->a = a;
  196. msg->messageID = messageID;
  197. Assert( !msg->text );
  198. msg->text = new char[ Q_strlen( data ) + 1 ];
  199. Assert( msg->text );
  200. Q_strncpy( msg->text, data, sizeof( msg->text ) );
  201. if ( flTime )
  202. msg->fTTL = gpGlobals->curtime + flTime;
  203. else
  204. msg->fTTL = 0;
  205. SetVisible( true );
  206. if ( hCustomFont )
  207. msg->hCustomFont = hCustomFont;
  208. else
  209. msg->hCustomFont = m_hFont;
  210. // Return new cursor position
  211. return x + g_pMatSystemSurface->DrawTextLen( msg->hCustomFont, "%s", data );
  212. }
  213. //-----------------------------------------------------------------------------
  214. // Purpose: Determine text size ahead of time
  215. // Input : *wide -
  216. // *tall -
  217. // *string -
  218. //-----------------------------------------------------------------------------
  219. void CMessageCharsPanel::GetTextExtents( vgui::HFont hCustomFont, int *wide, int *tall, const char *string )
  220. {
  221. if ( !hCustomFont )
  222. {
  223. // Make sure we actually have the font...
  224. vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
  225. hCustomFont = pScheme->GetFont( "Default" );
  226. }
  227. Assert( hCustomFont );
  228. *wide = g_pMatSystemSurface->DrawTextLen( hCustomFont, "%s", (char *)string );
  229. *tall = vgui::surface()->GetFontTall( hCustomFont );
  230. }
  231. //-----------------------------------------------------------------------------
  232. // Purpose:
  233. //-----------------------------------------------------------------------------
  234. void CMessageCharsPanel::OnTick( void )
  235. {
  236. bool bVisible = ShouldDraw();
  237. if ( IsVisible() != bVisible )
  238. {
  239. SetVisible( bVisible );
  240. }
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Purpose:
  244. // Output : Returns true on success, false on failure.
  245. //-----------------------------------------------------------------------------
  246. bool CMessageCharsPanel::ShouldDraw( void )
  247. {
  248. if ( !m_pActive )
  249. return false;
  250. return true;
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Purpose:
  254. // Input :
  255. //-----------------------------------------------------------------------------
  256. void CMessageCharsPanel::Paint()
  257. {
  258. CMessageCharsPanel::message_t *msg = m_pActive;
  259. while ( msg )
  260. {
  261. g_pMatSystemSurface->DrawColoredText( msg->hCustomFont, msg->x, msg->y, msg->r, msg->g, msg->b, msg->a, "%s", msg->text );
  262. msg = msg->next;
  263. }
  264. // Clear our dead messages
  265. message_t *pPrev = NULL;
  266. message_t *pCurrent = m_pActive;
  267. while ( pCurrent )
  268. {
  269. if ( pCurrent->fTTL <= gpGlobals->curtime )
  270. {
  271. // Move it to the free list
  272. if ( !pPrev )
  273. {
  274. m_pActive = pCurrent->next;
  275. }
  276. else
  277. {
  278. pPrev->next = pCurrent->next;
  279. }
  280. // Store off next one, because we're about to move the current
  281. message_t *pNext = pCurrent->next;
  282. delete[] pCurrent->text;
  283. pCurrent->text = NULL;
  284. pCurrent->next = m_pFree;
  285. m_pFree = pCurrent;
  286. // Don't advance pPrev
  287. pCurrent = pNext;
  288. continue;
  289. }
  290. pPrev = pCurrent;
  291. pCurrent = pCurrent->next;
  292. }
  293. }
  294. void CMessageCharsPanel::RemoveStringsByID( int messageID )
  295. {
  296. for ( message_t *pCurrent = m_pActive; pCurrent; pCurrent = pCurrent->next )
  297. {
  298. if ( pCurrent->messageID == messageID )
  299. pCurrent->fTTL = gpGlobals->curtime - 1000;
  300. }
  301. }
  302. class CMessageChars : public IMessageChars
  303. {
  304. private:
  305. CMessageCharsPanel *messageCharsPanel;
  306. public:
  307. CMessageChars( void )
  308. {
  309. messageCharsPanel = NULL;
  310. }
  311. void Create( vgui::VPANEL parent )
  312. {
  313. messageCharsPanel = new CMessageCharsPanel( parent );
  314. }
  315. void Destroy( void )
  316. {
  317. if ( messageCharsPanel )
  318. {
  319. messageCharsPanel->SetParent( (vgui::Panel *)NULL );
  320. delete messageCharsPanel;
  321. }
  322. }
  323. int DrawStringForTime( float flTime, vgui::HFont hCustomFont, int x, int y, int r, int g, int b, int a, const char *fmt, int messageID, ... )
  324. {
  325. va_list argptr;
  326. char data[ MAX_MESSAGECHARSPANEL_LEN ];
  327. int len;
  328. va_start(argptr, messageID);
  329. len = Q_vsnprintf(data, sizeof( data ), fmt, argptr);
  330. va_end(argptr);
  331. data[ MAX_MESSAGECHARSPANEL_LEN - 1 ] = 0;
  332. if ( !messageCharsPanel )
  333. return x;
  334. return messageCharsPanel->AddText( flTime, hCustomFont, x, y, r, g, b, a, data, messageID );
  335. }
  336. int DrawStringForTime( float flTime, vgui::HFont hCustomFont, int x, int y, const char *fmt, int messageID, ... )
  337. {
  338. int r = 192, g = 192, b = 192;
  339. va_list argptr;
  340. va_start( argptr, messageID );
  341. int result = DrawString( hCustomFont, x, y, r, g, b, 255, fmt, messageID, argptr );
  342. va_end( argptr );
  343. return result;
  344. }
  345. virtual void RemoveStringsByID( int messageID )
  346. {
  347. messageCharsPanel->RemoveStringsByID( messageID );
  348. }
  349. int DrawString( vgui::HFont hCustomFont, int x, int y, int r, int g, int b, int a, const char *fmt, int messageID, ... )
  350. {
  351. va_list argptr;
  352. va_start( argptr, messageID );
  353. int result = DrawStringForTime( 0, hCustomFont, x, y, r, g, b, a, fmt, messageID, argptr );
  354. va_end( argptr );
  355. return result;
  356. }
  357. int DrawString( vgui::HFont hCustomFont, int x, int y, const char *fmt, int messageID, ... )
  358. {
  359. va_list argptr;
  360. va_start( argptr, messageID );
  361. int result = DrawStringForTime( 0, hCustomFont, x, y, fmt, messageID, argptr );
  362. va_end( argptr );
  363. return result;
  364. }
  365. void GetStringLength( vgui::HFont hCustomFont, int *width, int *height, const char *fmt, ... )
  366. {
  367. if ( !messageCharsPanel )
  368. {
  369. return;
  370. }
  371. va_list argptr;
  372. char data[ MAX_MESSAGECHARSPANEL_LEN ];
  373. int len;
  374. va_start(argptr, fmt);
  375. len = Q_vsnprintf(data, sizeof( data ), fmt, argptr);
  376. va_end(argptr);
  377. data[ MAX_MESSAGECHARSPANEL_LEN - 1 ] = 0;
  378. messageCharsPanel->GetTextExtents( hCustomFont, width, height, data );
  379. }
  380. void Clear( void )
  381. {
  382. if ( !messageCharsPanel )
  383. return;
  384. messageCharsPanel->Clear();
  385. }
  386. };
  387. static CMessageChars g_MessageChars;
  388. IMessageChars *messagechars = ( IMessageChars * )&g_MessageChars;