diff options
Diffstat (limited to 'game/client/vgui_messagechars.cpp')
| -rw-r--r-- | game/client/vgui_messagechars.cpp | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/game/client/vgui_messagechars.cpp b/game/client/vgui_messagechars.cpp new file mode 100644 index 0000000..153e082 --- /dev/null +++ b/game/client/vgui_messagechars.cpp @@ -0,0 +1,467 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include <stdarg.h> +#include "imessagechars.h" +#include <vgui/IVGui.h> +#include "VGuiMatSurface/IMatSystemSurface.h" +#include <vgui_controls/Panel.h> +#include <vgui_controls/Controls.h> +#include <vgui/IScheme.h> +#include <vgui/ISurface.h> + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// Simultaneous message limit +#define MAX_MESSAGECHARS_MESSAGES 1024 +#define MAX_MESSAGECHARSPANEL_LEN 1024 + +//----------------------------------------------------------------------------- +// Purpose: Panel for displaying console characters at specified locations +//----------------------------------------------------------------------------- +class CMessageCharsPanel : public vgui::Panel +{ + typedef vgui::Panel BaseClass; +public: + // Internal pool of such messages + typedef struct message_s + { + struct message_s *next; + int x, y; + byte r, g, b, a; + char *text; + vgui::HFont hCustomFont; + float fTTL; + int messageID; + } message_t; + + // Construct/destruct + CMessageCharsPanel( vgui::VPANEL parent ); + virtual ~CMessageCharsPanel( void ); + + // Add block of text to list + virtual int AddText( + float flTime, + vgui::HFont hCustomFont, + int x, + int y, + int r, + int g, + int b, + int a, + char *fmt, + int messageID, + ... ); + + // Determine text side and height + virtual void GetTextExtents( vgui::HFont hCustomFont, int *wide, int *tall, const char *string ); + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void Paint(); + virtual void OnTick( void ); + + virtual bool ShouldDraw( void ); + + void RemoveStringsByID( int messageID ); + + void Clear( void ); + +private: + // Allocate a new message + message_t *AllocMessage( void ); + // Clear out all messages + void Reset( void ); + + vgui::HFont m_hFont; + + // Pool of messages + message_t m_Messages[ MAX_MESSAGECHARS_MESSAGES ]; + message_t *m_pActive; + message_t *m_pFree; +}; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +// Output : +//----------------------------------------------------------------------------- +CMessageCharsPanel::CMessageCharsPanel( vgui::VPANEL parent ) : + BaseClass( NULL, "CMessageCharsPanel" ) +{ + SetParent( parent ); + SetSize( ScreenWidth(), ScreenHeight() ); + SetPos( 0, 0 ); + SetVisible( true ); + SetCursor( null ); + SetKeyBoardInputEnabled( false ); + SetMouseInputEnabled( false ); + + m_hFont = vgui::INVALID_FONT; + + SetFgColor( Color( 0, 0, 0, 255 ) ); + SetPaintBackgroundEnabled( false ); + + Q_memset( m_Messages, 0, sizeof( m_Messages ) ); + + Reset(); + + vgui::ivgui()->AddTickSignal( GetVPanel(), 100 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : +//----------------------------------------------------------------------------- +CMessageCharsPanel::~CMessageCharsPanel( void ) +{ +} + +void CMessageCharsPanel::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + m_hFont = pScheme->GetFont( "Default" ); + Assert( m_hFont != vgui::INVALID_FONT ); + + SetSize( ScreenWidth(), ScreenHeight() ); + SetPos( 0, 0 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMessageCharsPanel::Clear( void ) +{ + Reset(); +} + +//----------------------------------------------------------------------------- +// Purpose: Reset all messages +//----------------------------------------------------------------------------- +void CMessageCharsPanel::Reset( void ) +{ + m_pActive = NULL; + int i; + for( i = 0; i < MAX_MESSAGECHARS_MESSAGES-1; i++ ) + { + if ( m_Messages[ i ].text ) + { + delete[] m_Messages[ i ].text; + m_Messages[ i ].text = NULL; + } + m_Messages[ i ].next = &m_Messages[ i + 1 ]; + } + m_Messages[ i ].next = NULL; + m_pFree = &m_Messages[ 0 ]; + SetVisible( false ); +} + +//----------------------------------------------------------------------------- +// Purpose: Allocate a message if possible +// Output : CMessageCharsPanel::message_t +//----------------------------------------------------------------------------- +CMessageCharsPanel::message_t *CMessageCharsPanel::AllocMessage( void ) +{ + CMessageCharsPanel::message_t *msg; + + if ( !m_pFree ) + return NULL; + + msg = m_pFree; + m_pFree = m_pFree->next; + + msg->next = m_pActive; + m_pActive = msg; + + msg->x = 0; + msg->y = 0; + msg->text = NULL; + + msg->hCustomFont = NULL; + + return msg; +} + +//----------------------------------------------------------------------------- +// Purpose: Allocate message and fill in data +// Input : x - +// y - +// *fmt - +// ... - +// Output : int +//----------------------------------------------------------------------------- +int CMessageCharsPanel::AddText( + float flTime, + vgui::HFont hCustomFont, + int x, + int y, + int r, + int g, + int b, + int a, + char *fmt, + int messageID, + ... ) +{ + va_list argptr; + char data[ MAX_MESSAGECHARSPANEL_LEN ]; + int len; + + va_start(argptr, messageID); + len = Q_vsnprintf(data, sizeof( data ), fmt, argptr); + va_end(argptr); + + data[ MAX_MESSAGECHARSPANEL_LEN - 1 ] = 0; + + CMessageCharsPanel::message_t *msg = AllocMessage(); + if ( !msg ) + return x; + + msg->x = x; + msg->y = y; + msg->r = r; + msg->g = g; + msg->b = b; + msg->a = a; + msg->messageID = messageID; + + Assert( !msg->text ); + + int textLength = Q_strlen( data ) + 1; + msg->text = new char[ textLength ]; + Assert( msg->text ); + Q_strncpy( msg->text, data, textLength ); + + if ( flTime ) + msg->fTTL = gpGlobals->curtime + flTime; + else + msg->fTTL = 0; + SetVisible( true ); + + if ( hCustomFont ) + msg->hCustomFont = hCustomFont; + else + msg->hCustomFont = m_hFont; + + // Return new cursor position + return x + g_pMatSystemSurface->DrawTextLen( msg->hCustomFont, "%s", data ); +} + +//----------------------------------------------------------------------------- +// Purpose: Determine text size ahead of time +// Input : *wide - +// *tall - +// *string - +//----------------------------------------------------------------------------- +void CMessageCharsPanel::GetTextExtents( vgui::HFont hCustomFont, int *wide, int *tall, const char *string ) +{ + if ( !hCustomFont ) + { + // Make sure we actually have the font... + vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); + hCustomFont = pScheme->GetFont( "Default" ); + } + + Assert( hCustomFont ); + + *wide = g_pMatSystemSurface->DrawTextLen( hCustomFont, "%s", (char *)string ); + *tall = vgui::surface()->GetFontTall( hCustomFont ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMessageCharsPanel::OnTick( void ) +{ + bool bVisible = ShouldDraw(); + if ( IsVisible() != bVisible ) + { + SetVisible( bVisible ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CMessageCharsPanel::ShouldDraw( void ) +{ + if ( !m_pActive ) + return false; + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +//----------------------------------------------------------------------------- +void CMessageCharsPanel::Paint() +{ + CMessageCharsPanel::message_t *msg = m_pActive; + while ( msg ) + { + g_pMatSystemSurface->DrawColoredText( msg->hCustomFont, msg->x, msg->y, msg->r, msg->g, msg->b, msg->a, "%s", msg->text ); + msg = msg->next; + } + + // Clear our dead messages + message_t *pPrev = NULL; + message_t *pCurrent = m_pActive; + while ( pCurrent ) + { + if ( pCurrent->fTTL <= gpGlobals->curtime ) + { + // Move it to the free list + if ( !pPrev ) + { + m_pActive = pCurrent->next; + } + else + { + pPrev->next = pCurrent->next; + } + + // Store off next one, because we're about to move the current + message_t *pNext = pCurrent->next; + delete[] pCurrent->text; + pCurrent->text = NULL; + pCurrent->next = m_pFree; + m_pFree = pCurrent; + + // Don't advance pPrev + pCurrent = pNext; + continue; + } + + pPrev = pCurrent; + pCurrent = pCurrent->next; + } +} + + +void CMessageCharsPanel::RemoveStringsByID( int messageID ) +{ + for ( message_t *pCurrent = m_pActive; pCurrent; pCurrent = pCurrent->next ) + { + if ( pCurrent->messageID == messageID ) + pCurrent->fTTL = gpGlobals->curtime - 1000; + } +} + +class CMessageChars : public IMessageChars +{ +private: + CMessageCharsPanel *messageCharsPanel; +public: + CMessageChars( void ) + { + messageCharsPanel = NULL; + } + + void Create( vgui::VPANEL parent ) + { + messageCharsPanel = new CMessageCharsPanel( parent ); + } + + void Destroy( void ) + { + if ( messageCharsPanel ) + { + messageCharsPanel->SetParent( (vgui::Panel *)NULL ); + messageCharsPanel->MarkForDeletion(); + messageCharsPanel = NULL; + } + } + + int DrawStringForTime( float flTime, vgui::HFont hCustomFont, int x, int y, int r, int g, int b, int a, const char *fmt, int messageID, ... ) + { + va_list argptr; + char data[ MAX_MESSAGECHARSPANEL_LEN ]; + int len; + + va_start(argptr, messageID); + len = Q_vsnprintf(data, sizeof( data ), fmt, argptr); + va_end(argptr); + + data[ MAX_MESSAGECHARSPANEL_LEN - 1 ] = 0; + + if ( !messageCharsPanel ) + return x; + + return messageCharsPanel->AddText( flTime, hCustomFont, x, y, r, g, b, a, data, messageID ); + } + + int DrawStringForTime( float flTime, vgui::HFont hCustomFont, int x, int y, const char *fmt, int messageID, ... ) + { + int r = 192, g = 192, b = 192; + + va_list argptr; + va_start(argptr, messageID); + int result = DrawString( hCustomFont, x, y, r, g, b, 255, fmt, messageID, argptr ); + va_end( argptr ); + return result; + } + + virtual void RemoveStringsByID( int messageID ) + { + messageCharsPanel->RemoveStringsByID( messageID ); + } + + int DrawString( vgui::HFont hCustomFont, int x, int y, int r, int g, int b, int a, const char *fmt, int messageID, ... ) + { + va_list argptr; + va_start(argptr, messageID); + int result = DrawStringForTime( 0, hCustomFont, x, y, r, g, b, a, fmt, messageID, argptr ); + va_end( argptr ); + return result; + } + + int DrawString( vgui::HFont hCustomFont, int x, int y, const char *fmt, int messageID, ... ) + { + va_list argptr; + va_start(argptr, messageID); + int result = DrawStringForTime( 0, hCustomFont, x, y, fmt, messageID, argptr ); + va_end( argptr ); + return result; + } + + void GetStringLength( vgui::HFont hCustomFont, int *width, int *height, const char *fmt, ... ) + { + if ( !messageCharsPanel ) + { + return; + } + + va_list argptr; + char data[ MAX_MESSAGECHARSPANEL_LEN ]; + int len; + + va_start(argptr, fmt); + len = Q_vsnprintf(data, sizeof( data ), fmt, argptr); + va_end(argptr); + + data[ MAX_MESSAGECHARSPANEL_LEN - 1 ] = 0; + + messageCharsPanel->GetTextExtents( hCustomFont, width, height, data ); + } + + void Clear( void ) + { + if ( !messageCharsPanel ) + return; + messageCharsPanel->Clear(); + } +}; + +static CMessageChars g_MessageChars; +IMessageChars *messagechars = ( IMessageChars * )&g_MessageChars; |