summaryrefslogtreecommitdiff
path: root/game/client/tf/vgui/drawing_panel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/tf/vgui/drawing_panel.cpp')
-rw-r--r--game/client/tf/vgui/drawing_panel.cpp335
1 files changed, 335 insertions, 0 deletions
diff --git a/game/client/tf/vgui/drawing_panel.cpp b/game/client/tf/vgui/drawing_panel.cpp
new file mode 100644
index 0000000..f6e764a
--- /dev/null
+++ b/game/client/tf/vgui/drawing_panel.cpp
@@ -0,0 +1,335 @@
+//========= 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 );
+ }
+ }
+ }
+} \ No newline at end of file