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.
467 lines
11 KiB
467 lines
11 KiB
//========= 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 ); |
|
delete messageCharsPanel; |
|
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;
|
|
|