//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $Workfile: $ // $Date: $ // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "itextmessage.h" #include #include #include #include "VGuiMatSurface/IMatSystemSurface.h" #include #include #include "hud.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" // Simultaneous message limit #define MAX_TEXTMESSAGE_CHARS 2048 //----------------------------------------------------------------------------- // Purpose: For rendering the Titles.txt characters to the screen from the HUD //----------------------------------------------------------------------------- class CTextMessagePanel : public vgui::Panel { typedef vgui::Panel BaseClass; public: enum { TYPE_UNKNOWN = 0, TYPE_POSITION, TYPE_CHARACTER, TYPE_FONT, }; struct message_t { vgui::HFont font; short x, y; wchar_t ch; byte type; byte r, g, b, a; }; CTextMessagePanel( vgui::VPANEL parent ); virtual ~CTextMessagePanel( void ); virtual void SetPosition( int x, int y ); virtual void AddChar( int r, int g, int b, int a, wchar_t ch ); virtual void GetTextExtents( int *wide, int *tall, const char *string ); virtual void SetFont( vgui::HFont hCustomFont ); virtual void SetDefaultFont( void ); virtual void OnTick( void ); virtual void Paint(); virtual bool ShouldDraw( void ); // Get character data for textmessage text virtual int GetFontInfo( FONTABC *pABCs, vgui::HFont hFont ); virtual void ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); SetSize( ScreenWidth(), ScreenHeight() ); SetPos( 0, 0 ); } private: message_t *AllocMessage( void ); void Reset( void ); vgui::HFont m_hFont; vgui::HFont m_hDefaultFont; CUtlVector< message_t > m_Messages; }; //----------------------------------------------------------------------------- // Purpose: Constructor // Input : *parent - //----------------------------------------------------------------------------- CTextMessagePanel::CTextMessagePanel( vgui::VPANEL parent ) : BaseClass( NULL, "CTextMessagePanel" ) { SetParent( parent ); SetSize( ScreenWidth(), ScreenHeight() ); SetPos( 0, 0 ); SetVisible( false ); SetCursor( null ); SetKeyBoardInputEnabled( false ); SetMouseInputEnabled( false ); m_hFont = g_hFontTrebuchet24; m_hDefaultFont = m_hFont; SetFgColor( Color( 0, 0, 0, 255 ) ); SetPaintBackgroundEnabled( false ); // Clear memory out Reset(); vgui::ivgui()->AddTickSignal( GetVPanel(), 100 ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CTextMessagePanel::~CTextMessagePanel( void ) { } //----------------------------------------------------------------------------- // Purpose: Get font sizes // Input : *pWidth - // Output : int //----------------------------------------------------------------------------- int CTextMessagePanel::GetFontInfo( FONTABC *pABCs, vgui::HFont hFont ) { int i; if ( !hFont ) { hFont = m_hFont; } if ( !hFont ) return 0; if ( pABCs ) { for ( i =0; i < 256; i++ ) { int a, b, c; vgui::surface()->GetCharABCwide( hFont, (char)i, a, b, c ); pABCs[i].abcA = a; pABCs[i].abcB = b; pABCs[i].abcC = c; pABCs[i].total = a+b+c; } } return vgui::surface()->GetFontTall( hFont ); } //----------------------------------------------------------------------------- // Purpose: Clear all messages out of active list, etc. //----------------------------------------------------------------------------- void CTextMessagePanel::Reset( void ) { m_Messages.Purge(); SetVisible( false ); } //----------------------------------------------------------------------------- // Purpose: Grab next free message, if any // Output : CTextMessagePanel::message_t //----------------------------------------------------------------------------- CTextMessagePanel::message_t *CTextMessagePanel::AllocMessage( void ) { CTextMessagePanel::message_t *msg; if ( m_Messages.Count() >= MAX_TEXTMESSAGE_CHARS ) return NULL; msg = &m_Messages[ m_Messages.AddToTail() ]; msg->type = TYPE_UNKNOWN; msg->x = 0; msg->y = 0; msg->ch = 0; msg->r = 0; msg->g = 0; msg->b = 0; msg->a = 0; SetVisible( true ); return msg; } //----------------------------------------------------------------------------- // Purpose: // Input : x - // y - //----------------------------------------------------------------------------- void CTextMessagePanel::SetPosition( int x, int y ) { CTextMessagePanel::message_t *msg = AllocMessage(); if ( !msg ) return; msg->type = TYPE_POSITION; // Used fields msg->x = x; msg->y = y; } //----------------------------------------------------------------------------- // Purpose: Adds a character to the active list, if possible // Input : x - // y - // r - // g - // b - // a - // ch - // Output : int //----------------------------------------------------------------------------- void CTextMessagePanel::AddChar( int r, int g, int b, int a, wchar_t ch ) { CTextMessagePanel::message_t *msg = AllocMessage(); if ( !msg ) return; msg->type = TYPE_CHARACTER; // Used fields msg->r = r; msg->g = g; msg->b = b; msg->a = a; msg->ch = ch; } //----------------------------------------------------------------------------- // Purpose: Determine width and height of specified string // Input : *wide - // *tall - // *string - //----------------------------------------------------------------------------- void CTextMessagePanel::GetTextExtents( int *wide, int *tall, const char *string ) { *wide = g_pMatSystemSurface->DrawTextLen( m_hFont, "%s", (char *)string ); *tall = vgui::surface()->GetFontTall( m_hFont ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTextMessagePanel::SetFont( vgui::HFont hCustomFont ) { m_hFont = hCustomFont; CTextMessagePanel::message_t *msg = AllocMessage(); if ( !msg ) return; msg->type = TYPE_FONT; // Used fields msg->font = m_hFont; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTextMessagePanel::SetDefaultFont( void ) { SetFont( m_hDefaultFont ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTextMessagePanel::OnTick( void ) { SetVisible( ShouldDraw() ); } //----------------------------------------------------------------------------- // Purpose: // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CTextMessagePanel::ShouldDraw( void ) { if ( !m_Messages.Count() ) return false; return true; } //----------------------------------------------------------------------------- // Purpose: Draw current text items //----------------------------------------------------------------------------- void CTextMessagePanel::Paint() { CTextMessagePanel::message_t *msg; int xpos = 0, ypos = 0; vgui::surface()->DrawSetTextFont( m_hFont ); int messageCount = m_Messages.Count(); for ( int i = 0 ; i < messageCount; ++i ) { msg = &m_Messages[ i ]; switch ( msg->type ) { default: case TYPE_UNKNOWN: Assert( 0 ); break; case TYPE_POSITION: xpos = msg->x; ypos = msg->y; break; case TYPE_FONT: m_hFont = msg->font; vgui::surface()->DrawSetTextFont( m_hFont ); break; case TYPE_CHARACTER: if ( m_hFont ) { int a, b, c; vgui::surface()->GetCharABCwide( m_hFont, msg->ch, a, b, c ); if ( msg->ch > 32 ) { vgui::surface()->DrawSetTextColor( msg->r, msg->g, msg->b, msg->a ); vgui::surface()->DrawSetTextPos( xpos, ypos ); vgui::surface()->DrawUnicodeChar( msg->ch ); } xpos += a + b + c; } break; } } Reset(); } class CTextMessage : public ITextMessage { private: CTextMessagePanel *textMessagePanel; public: CTextMessage( void ) { textMessagePanel = NULL; } void Create( vgui::VPANEL parent ) { textMessagePanel = new CTextMessagePanel( parent ); } void Destroy( void ) { if ( textMessagePanel ) { textMessagePanel->SetParent( (vgui::Panel *)NULL ); delete textMessagePanel; } } void SetPosition( int x, int y ) { if ( !textMessagePanel ) return; textMessagePanel->SetPosition( x, y ); } void AddChar( int r, int g, int b, int a, wchar_t ch ) { if ( !textMessagePanel ) return; textMessagePanel->AddChar( r, g, b, a, ch ); } void GetLength( int *wide, int *tall, const char *string ) { if ( !textMessagePanel ) { *wide = *tall = 0; return; } textMessagePanel->GetTextExtents( wide, tall, string ); } int GetFontInfo( FONTABC *pABCs, vgui::HFont hFont ) { return textMessagePanel ? textMessagePanel->GetFontInfo( pABCs, hFont ) : 0; } void SetFont( vgui::HFont hCustomFont ) { if ( !textMessagePanel ) return; textMessagePanel->SetFont( hCustomFont ); } void SetDefaultFont( void ) { if ( !textMessagePanel ) return; textMessagePanel->SetDefaultFont(); } }; static CTextMessage g_TextMessage; ITextMessage *textmessage = &g_TextMessage;