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.
335 lines
8.9 KiB
335 lines
8.9 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "drawing_panel.h" |
|
#include "softline.h" |
|
#include <vgui/IScheme.h> |
|
#include <vgui/IVGui.h> |
|
#include "voice_status.h" |
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
extern ConVar cl_mute_all_comms; |
|
|
|
Color g_DrawPanel_TeamColors[TF_TEAM_COUNT] = |
|
{ |
|
COLOR_TF_SPECTATOR, // unassigned |
|
COLOR_TF_SPECTATOR, // spectator |
|
COLOR_TF_RED, // red |
|
COLOR_TF_BLUE, // blue |
|
}; |
|
|
|
DECLARE_BUILD_FACTORY( CDrawingPanel ); |
|
|
|
CDrawingPanel::CDrawingPanel( Panel *parent, const char*name ) : Panel( parent, name ) |
|
{ |
|
m_bDrawingLines = false; |
|
m_fLastMapLine = 0; |
|
m_iMouseX = 0; |
|
m_iMouseY = 0; |
|
m_iPanelType = DRAWING_PANEL_TYPE_NONE; |
|
m_bTeamColors = false; |
|
|
|
m_nWhiteTexture = vgui::surface()->CreateNewTextureID(); |
|
vgui::surface()->DrawSetTextureFile( m_nWhiteTexture, "vgui/white", true, false ); |
|
|
|
ListenForGameEvent( "cl_drawline" ); |
|
} |
|
|
|
void CDrawingPanel::SetVisible( bool bState ) |
|
{ |
|
ClearAllLines(); |
|
|
|
BaseClass::SetVisible( bState ); |
|
} |
|
|
|
void CDrawingPanel::ReadColor( const char* pszToken, Color& color ) |
|
{ |
|
if ( pszToken && *pszToken ) |
|
{ |
|
int r = 0, g = 0, b = 0, a = 255; |
|
if ( sscanf( pszToken, "%d %d %d %d", &r, &g, &b, &a ) >= 3 ) |
|
{ |
|
// it's a direct color |
|
color = Color( r, g, b, a ); |
|
} |
|
else |
|
{ |
|
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); |
|
color = pScheme->GetColor( pszToken, Color( 0, 0, 0, 0 ) ); |
|
} |
|
} |
|
} |
|
|
|
void CDrawingPanel::ApplySettings( KeyValues *inResourceData ) |
|
{ |
|
BaseClass::ApplySettings( inResourceData ); |
|
|
|
ReadColor( inResourceData->GetString( "linecolor", "" ), m_colorLine ); |
|
m_bTeamColors = inResourceData->GetBool( "team_colors", false ); |
|
} |
|
|
|
void CDrawingPanel::Paint() |
|
{ |
|
for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ ) |
|
{ |
|
//Draw the lines |
|
for ( int i = 0; i < m_vecDrawnLines[iIndex].Count(); i++ ) |
|
{ |
|
if ( !m_vecDrawnLines[iIndex][i].bSetBlipCentre ) |
|
{ |
|
Vector vecBlipPos; |
|
vecBlipPos.x = m_vecDrawnLines[iIndex][i].worldpos.x; |
|
vecBlipPos.y = m_vecDrawnLines[iIndex][i].worldpos.y; |
|
vecBlipPos.z = 0; |
|
//Msg("drawing line with blippos %f, %f\n", vecBlipPos.x, vecBlipPos.y); |
|
m_vecDrawnLines[iIndex][i].blipcentre = m_vecDrawnLines[iIndex][i].worldpos; |
|
//Msg(" which is blipcentre=%f, %f\n", m_MapLines[i].blipcentre.x, m_MapLines[i].blipcentre.y); |
|
m_vecDrawnLines[iIndex][i].bSetBlipCentre = true; |
|
} |
|
|
|
float x = m_vecDrawnLines[iIndex][i].blipcentre.x; |
|
float y = m_vecDrawnLines[iIndex][i].blipcentre.y; |
|
|
|
if ( m_vecDrawnLines[iIndex][i].bLink ) |
|
{ |
|
if ( i > 1 ) |
|
{ |
|
m_vecDrawnLines[iIndex][i].linkpos = m_vecDrawnLines[iIndex][i-1].worldpos; |
|
|
|
if ( !m_vecDrawnLines[iIndex][i].bSetLinkBlipCentre ) |
|
{ |
|
Vector vecBlipPos2; |
|
vecBlipPos2.x = m_vecDrawnLines[iIndex][i].linkpos.x; |
|
vecBlipPos2.y = m_vecDrawnLines[iIndex][i].linkpos.y; |
|
vecBlipPos2.z = 0; |
|
m_vecDrawnLines[iIndex][i].linkblipcentre = m_vecDrawnLines[iIndex][i].linkpos; |
|
m_vecDrawnLines[iIndex][i].bSetLinkBlipCentre = true; |
|
} |
|
|
|
float x2 = m_vecDrawnLines[iIndex][i].linkblipcentre.x; |
|
float y2 = m_vecDrawnLines[iIndex][i].linkblipcentre.y; |
|
|
|
int alpha = 255; |
|
if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY ) |
|
{ |
|
float t = gpGlobals->curtime - m_vecDrawnLines[iIndex][i].created_time; |
|
|
|
if ( t < DRAWN_LINE_SOLID_TIME ) |
|
{ |
|
|
|
} |
|
else if ( t < DRAWN_LINE_SOLID_TIME + DRAWN_LINE_FADE_TIME ) |
|
{ |
|
alpha = 255 - ( ( t - DRAWN_LINE_SOLID_TIME ) / DRAWN_LINE_FADE_TIME ) * 255.0f; |
|
} |
|
else |
|
{ |
|
continue; |
|
} |
|
} |
|
|
|
//Msg("drawing line from %f,%f to %f,%f\n", x, y, x2, y2); |
|
|
|
vgui::surface()->DrawSetTexture( m_nWhiteTexture ); |
|
vgui::Vertex_t start, end; |
|
|
|
Color drawColor = m_colorLine; |
|
if ( m_bTeamColors ) |
|
{ |
|
C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iIndex ); |
|
if ( pPlayer ) |
|
{ |
|
drawColor = g_DrawPanel_TeamColors[ pPlayer->GetTeamNumber() ]; |
|
} |
|
} |
|
|
|
// draw main line |
|
vgui::surface()->DrawSetColor( Color( drawColor.r(), drawColor.g(), drawColor.b(), alpha ) ); |
|
start.Init( Vector2D( x, y ), Vector2D( 0, 0 ) ); |
|
end.Init( Vector2D( x2, y2 ), Vector2D( 1, 1 ) ); |
|
SoftLine::DrawPolygonLine( start, end ); |
|
|
|
// draw translucent ones around it to give it some softness |
|
vgui::surface()->DrawSetColor( Color( drawColor.r(), drawColor.g(), drawColor.b(), 0.5f * alpha ) ); |
|
|
|
start.Init( Vector2D( x - 0.50f, y - 0.50f ), Vector2D( 0, 0 ) ); |
|
end.Init( Vector2D( x2 - 0.50f, y2 - 0.50f ), Vector2D( 1, 1 ) ); |
|
SoftLine::DrawPolygonLine( start, end ); |
|
|
|
start.Init( Vector2D( x + 0.50f, y - 0.50f ), Vector2D( 0, 0 ) ); |
|
end.Init( Vector2D( x2 + 0.50f, y2 - 0.50f ), Vector2D( 1, 1 ) ); |
|
SoftLine::DrawPolygonLine( start, end ); |
|
|
|
start.Init( Vector2D( x - 0.50f, y + 0.50f ), Vector2D( 0, 0 ) ); |
|
end.Init( Vector2D( x2 - 0.50f, y2 + 0.50f ), Vector2D( 1, 1 ) ); |
|
SoftLine::DrawPolygonLine( start, end ); |
|
|
|
start.Init( Vector2D( x + 0.50f, y + 0.50f ), Vector2D( 0, 0 ) ); |
|
end.Init( Vector2D( x2 + 0.50f, y2 + 0.50f ), Vector2D( 1, 1 ) ); |
|
SoftLine::DrawPolygonLine( start, end ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CDrawingPanel::OnMousePressed( vgui::MouseCode code ) |
|
{ |
|
if ( code != MOUSE_LEFT ) |
|
return; |
|
|
|
SendMapLine( m_iMouseX, m_iMouseY, true ); |
|
m_bDrawingLines = true; |
|
} |
|
|
|
void CDrawingPanel::OnMouseReleased( vgui::MouseCode code ) |
|
{ |
|
if ( code != MOUSE_LEFT ) |
|
return; |
|
|
|
m_bDrawingLines = false; |
|
} |
|
|
|
void CDrawingPanel::OnCursorExited() |
|
{ |
|
//Msg("CDrawingPanel::OnCursorExited\n"); |
|
m_bDrawingLines = false; |
|
} |
|
|
|
void CDrawingPanel::OnThink() |
|
{ |
|
if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY ) |
|
{ |
|
// clean up any segments that have faded out |
|
for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ ) |
|
{ |
|
for ( int i = m_vecDrawnLines[iIndex].Count() - 1; i >= 0; i-- ) |
|
{ |
|
if ( gpGlobals->curtime - m_vecDrawnLines[iIndex][i].created_time > DRAWN_LINE_SOLID_TIME + DRAWN_LINE_FADE_TIME ) |
|
{ |
|
m_vecDrawnLines[iIndex].Remove( i ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CDrawingPanel::OnCursorMoved( int x, int y ) |
|
{ |
|
//Msg("CDrawingPanel::OnCursorMoved %d,%d\n", x, y); |
|
m_iMouseX = x; |
|
m_iMouseY = y; |
|
|
|
const float flLineInterval = 1.f / 60.f; |
|
|
|
if ( m_bDrawingLines && gpGlobals->curtime >= m_fLastMapLine + flLineInterval ) |
|
{ |
|
SendMapLine( x, y, false ); |
|
} |
|
|
|
} |
|
|
|
void CDrawingPanel::SendMapLine( int x, int y, bool bInitial ) |
|
{ |
|
if ( engine->IsPlayingDemo() ) |
|
return; |
|
|
|
int iIndex = GetLocalPlayerIndex(); |
|
int nMaxLines = 750; // 12.5 seconds of drawing at 60fps |
|
if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY ) |
|
{ |
|
nMaxLines = 120; // 2 seconds of drawing at 60fps |
|
} |
|
|
|
// Stop adding lines after this much |
|
if ( m_vecDrawnLines[iIndex].Count() >= nMaxLines ) |
|
return; |
|
|
|
int linetype = bInitial ? 0 : 1; |
|
|
|
m_fLastMapLine = gpGlobals->curtime; |
|
|
|
// short circuit add it to your own list |
|
MapLine line; |
|
line.worldpos.x = x; |
|
line.worldpos.y = y; |
|
line.created_time = gpGlobals->curtime; |
|
if ( linetype == 1 ) // links to a previous |
|
{ |
|
line.bLink = true; |
|
} |
|
|
|
m_vecDrawnLines[iIndex].AddToTail( line ); |
|
|
|
if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY ) |
|
{ |
|
// notify the server of this! |
|
KeyValues *kv = new KeyValues( "cl_drawline" ); |
|
kv->SetInt( "panel", m_iPanelType ); |
|
kv->SetInt( "line", linetype ); |
|
kv->SetFloat( "x", (float)x / (float)GetWide() ); |
|
kv->SetFloat( "y", (float)y / (float)GetTall() ); |
|
engine->ServerCmdKeyValues( kv ); |
|
} |
|
} |
|
|
|
void CDrawingPanel::ClearLines( int iIndex ) |
|
{ |
|
m_vecDrawnLines[iIndex].Purge(); |
|
} |
|
|
|
void CDrawingPanel::ClearAllLines() |
|
{ |
|
for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ ) |
|
{ |
|
m_vecDrawnLines[iIndex].Purge(); |
|
} |
|
} |
|
|
|
void CDrawingPanel::FireGameEvent( IGameEvent *event ) |
|
{ |
|
if ( FStrEq( event->GetName(), "cl_drawline" ) ) |
|
{ |
|
int iIndex = event->GetInt( "player" ); |
|
|
|
// if this is NOT the local player (we've already stored our own data) |
|
if ( ( iIndex != GetLocalPlayerIndex() ) || engine->IsPlayingDemo() ) |
|
{ |
|
// If a player is muted for voice, also mute them for lines because jerks gonna jerk. |
|
if ( cl_mute_all_comms.GetBool() && ( iIndex != 0 ) ) |
|
{ |
|
if ( GetClientVoiceMgr() && GetClientVoiceMgr()->IsPlayerBlocked( iIndex ) ) |
|
{ |
|
ClearLines( iIndex ); |
|
return; |
|
} |
|
} |
|
|
|
int iPanelType = event->GetInt( "panel" ); |
|
|
|
// if this message is about our panel type |
|
if ( iPanelType == m_iPanelType ) |
|
{ |
|
int iLineType = event->GetInt( "line" ); |
|
float x = event->GetFloat( "x" ); |
|
float y = event->GetFloat( "y" ); |
|
|
|
MapLine line; |
|
line.worldpos.x = (int)( x * GetWide() ); |
|
line.worldpos.y = (int)( y * GetTall() ); |
|
line.created_time = gpGlobals->curtime; |
|
if ( iLineType == 1 ) // links to a previous |
|
{ |
|
line.bLink = true; |
|
} |
|
|
|
m_vecDrawnLines[iIndex].AddToTail( line ); |
|
} |
|
} |
|
} |
|
} |