Team Fortress 2 Source Code as on 22/4/2020
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.

334 lines
8.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "drawing_panel.h"
  8. #include "softline.h"
  9. #include <vgui/IScheme.h>
  10. #include <vgui/IVGui.h>
  11. #include "voice_status.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include <tier0/memdbgon.h>
  14. extern ConVar cl_mute_all_comms;
  15. Color g_DrawPanel_TeamColors[TF_TEAM_COUNT] =
  16. {
  17. COLOR_TF_SPECTATOR, // unassigned
  18. COLOR_TF_SPECTATOR, // spectator
  19. COLOR_TF_RED, // red
  20. COLOR_TF_BLUE, // blue
  21. };
  22. DECLARE_BUILD_FACTORY( CDrawingPanel );
  23. CDrawingPanel::CDrawingPanel( Panel *parent, const char*name ) : Panel( parent, name )
  24. {
  25. m_bDrawingLines = false;
  26. m_fLastMapLine = 0;
  27. m_iMouseX = 0;
  28. m_iMouseY = 0;
  29. m_iPanelType = DRAWING_PANEL_TYPE_NONE;
  30. m_bTeamColors = false;
  31. m_nWhiteTexture = vgui::surface()->CreateNewTextureID();
  32. vgui::surface()->DrawSetTextureFile( m_nWhiteTexture, "vgui/white", true, false );
  33. ListenForGameEvent( "cl_drawline" );
  34. }
  35. void CDrawingPanel::SetVisible( bool bState )
  36. {
  37. ClearAllLines();
  38. BaseClass::SetVisible( bState );
  39. }
  40. void CDrawingPanel::ReadColor( const char* pszToken, Color& color )
  41. {
  42. if ( pszToken && *pszToken )
  43. {
  44. int r = 0, g = 0, b = 0, a = 255;
  45. if ( sscanf( pszToken, "%d %d %d %d", &r, &g, &b, &a ) >= 3 )
  46. {
  47. // it's a direct color
  48. color = Color( r, g, b, a );
  49. }
  50. else
  51. {
  52. vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
  53. color = pScheme->GetColor( pszToken, Color( 0, 0, 0, 0 ) );
  54. }
  55. }
  56. }
  57. void CDrawingPanel::ApplySettings( KeyValues *inResourceData )
  58. {
  59. BaseClass::ApplySettings( inResourceData );
  60. ReadColor( inResourceData->GetString( "linecolor", "" ), m_colorLine );
  61. m_bTeamColors = inResourceData->GetBool( "team_colors", false );
  62. }
  63. void CDrawingPanel::Paint()
  64. {
  65. for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ )
  66. {
  67. //Draw the lines
  68. for ( int i = 0; i < m_vecDrawnLines[iIndex].Count(); i++ )
  69. {
  70. if ( !m_vecDrawnLines[iIndex][i].bSetBlipCentre )
  71. {
  72. Vector vecBlipPos;
  73. vecBlipPos.x = m_vecDrawnLines[iIndex][i].worldpos.x;
  74. vecBlipPos.y = m_vecDrawnLines[iIndex][i].worldpos.y;
  75. vecBlipPos.z = 0;
  76. //Msg("drawing line with blippos %f, %f\n", vecBlipPos.x, vecBlipPos.y);
  77. m_vecDrawnLines[iIndex][i].blipcentre = m_vecDrawnLines[iIndex][i].worldpos;
  78. //Msg(" which is blipcentre=%f, %f\n", m_MapLines[i].blipcentre.x, m_MapLines[i].blipcentre.y);
  79. m_vecDrawnLines[iIndex][i].bSetBlipCentre = true;
  80. }
  81. float x = m_vecDrawnLines[iIndex][i].blipcentre.x;
  82. float y = m_vecDrawnLines[iIndex][i].blipcentre.y;
  83. if ( m_vecDrawnLines[iIndex][i].bLink )
  84. {
  85. if ( i > 1 )
  86. {
  87. m_vecDrawnLines[iIndex][i].linkpos = m_vecDrawnLines[iIndex][i-1].worldpos;
  88. if ( !m_vecDrawnLines[iIndex][i].bSetLinkBlipCentre )
  89. {
  90. Vector vecBlipPos2;
  91. vecBlipPos2.x = m_vecDrawnLines[iIndex][i].linkpos.x;
  92. vecBlipPos2.y = m_vecDrawnLines[iIndex][i].linkpos.y;
  93. vecBlipPos2.z = 0;
  94. m_vecDrawnLines[iIndex][i].linkblipcentre = m_vecDrawnLines[iIndex][i].linkpos;
  95. m_vecDrawnLines[iIndex][i].bSetLinkBlipCentre = true;
  96. }
  97. float x2 = m_vecDrawnLines[iIndex][i].linkblipcentre.x;
  98. float y2 = m_vecDrawnLines[iIndex][i].linkblipcentre.y;
  99. int alpha = 255;
  100. if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY )
  101. {
  102. float t = gpGlobals->curtime - m_vecDrawnLines[iIndex][i].created_time;
  103. if ( t < DRAWN_LINE_SOLID_TIME )
  104. {
  105. }
  106. else if ( t < DRAWN_LINE_SOLID_TIME + DRAWN_LINE_FADE_TIME )
  107. {
  108. alpha = 255 - ( ( t - DRAWN_LINE_SOLID_TIME ) / DRAWN_LINE_FADE_TIME ) * 255.0f;
  109. }
  110. else
  111. {
  112. continue;
  113. }
  114. }
  115. //Msg("drawing line from %f,%f to %f,%f\n", x, y, x2, y2);
  116. vgui::surface()->DrawSetTexture( m_nWhiteTexture );
  117. vgui::Vertex_t start, end;
  118. Color drawColor = m_colorLine;
  119. if ( m_bTeamColors )
  120. {
  121. C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iIndex );
  122. if ( pPlayer )
  123. {
  124. drawColor = g_DrawPanel_TeamColors[ pPlayer->GetTeamNumber() ];
  125. }
  126. }
  127. // draw main line
  128. vgui::surface()->DrawSetColor( Color( drawColor.r(), drawColor.g(), drawColor.b(), alpha ) );
  129. start.Init( Vector2D( x, y ), Vector2D( 0, 0 ) );
  130. end.Init( Vector2D( x2, y2 ), Vector2D( 1, 1 ) );
  131. SoftLine::DrawPolygonLine( start, end );
  132. // draw translucent ones around it to give it some softness
  133. vgui::surface()->DrawSetColor( Color( drawColor.r(), drawColor.g(), drawColor.b(), 0.5f * alpha ) );
  134. start.Init( Vector2D( x - 0.50f, y - 0.50f ), Vector2D( 0, 0 ) );
  135. end.Init( Vector2D( x2 - 0.50f, y2 - 0.50f ), Vector2D( 1, 1 ) );
  136. SoftLine::DrawPolygonLine( start, end );
  137. start.Init( Vector2D( x + 0.50f, y - 0.50f ), Vector2D( 0, 0 ) );
  138. end.Init( Vector2D( x2 + 0.50f, y2 - 0.50f ), Vector2D( 1, 1 ) );
  139. SoftLine::DrawPolygonLine( start, end );
  140. start.Init( Vector2D( x - 0.50f, y + 0.50f ), Vector2D( 0, 0 ) );
  141. end.Init( Vector2D( x2 - 0.50f, y2 + 0.50f ), Vector2D( 1, 1 ) );
  142. SoftLine::DrawPolygonLine( start, end );
  143. start.Init( Vector2D( x + 0.50f, y + 0.50f ), Vector2D( 0, 0 ) );
  144. end.Init( Vector2D( x2 + 0.50f, y2 + 0.50f ), Vector2D( 1, 1 ) );
  145. SoftLine::DrawPolygonLine( start, end );
  146. }
  147. }
  148. }
  149. }
  150. }
  151. void CDrawingPanel::OnMousePressed( vgui::MouseCode code )
  152. {
  153. if ( code != MOUSE_LEFT )
  154. return;
  155. SendMapLine( m_iMouseX, m_iMouseY, true );
  156. m_bDrawingLines = true;
  157. }
  158. void CDrawingPanel::OnMouseReleased( vgui::MouseCode code )
  159. {
  160. if ( code != MOUSE_LEFT )
  161. return;
  162. m_bDrawingLines = false;
  163. }
  164. void CDrawingPanel::OnCursorExited()
  165. {
  166. //Msg("CDrawingPanel::OnCursorExited\n");
  167. m_bDrawingLines = false;
  168. }
  169. void CDrawingPanel::OnThink()
  170. {
  171. if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY )
  172. {
  173. // clean up any segments that have faded out
  174. for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ )
  175. {
  176. for ( int i = m_vecDrawnLines[iIndex].Count() - 1; i >= 0; i-- )
  177. {
  178. if ( gpGlobals->curtime - m_vecDrawnLines[iIndex][i].created_time > DRAWN_LINE_SOLID_TIME + DRAWN_LINE_FADE_TIME )
  179. {
  180. m_vecDrawnLines[iIndex].Remove( i );
  181. }
  182. }
  183. }
  184. }
  185. }
  186. void CDrawingPanel::OnCursorMoved( int x, int y )
  187. {
  188. //Msg("CDrawingPanel::OnCursorMoved %d,%d\n", x, y);
  189. m_iMouseX = x;
  190. m_iMouseY = y;
  191. const float flLineInterval = 1.f / 60.f;
  192. if ( m_bDrawingLines && gpGlobals->curtime >= m_fLastMapLine + flLineInterval )
  193. {
  194. SendMapLine( x, y, false );
  195. }
  196. }
  197. void CDrawingPanel::SendMapLine( int x, int y, bool bInitial )
  198. {
  199. if ( engine->IsPlayingDemo() )
  200. return;
  201. int iIndex = GetLocalPlayerIndex();
  202. int nMaxLines = 750; // 12.5 seconds of drawing at 60fps
  203. if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY )
  204. {
  205. nMaxLines = 120; // 2 seconds of drawing at 60fps
  206. }
  207. // Stop adding lines after this much
  208. if ( m_vecDrawnLines[iIndex].Count() >= nMaxLines )
  209. return;
  210. int linetype = bInitial ? 0 : 1;
  211. m_fLastMapLine = gpGlobals->curtime;
  212. // short circuit add it to your own list
  213. MapLine line;
  214. line.worldpos.x = x;
  215. line.worldpos.y = y;
  216. line.created_time = gpGlobals->curtime;
  217. if ( linetype == 1 ) // links to a previous
  218. {
  219. line.bLink = true;
  220. }
  221. m_vecDrawnLines[iIndex].AddToTail( line );
  222. if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY )
  223. {
  224. // notify the server of this!
  225. KeyValues *kv = new KeyValues( "cl_drawline" );
  226. kv->SetInt( "panel", m_iPanelType );
  227. kv->SetInt( "line", linetype );
  228. kv->SetFloat( "x", (float)x / (float)GetWide() );
  229. kv->SetFloat( "y", (float)y / (float)GetTall() );
  230. engine->ServerCmdKeyValues( kv );
  231. }
  232. }
  233. void CDrawingPanel::ClearLines( int iIndex )
  234. {
  235. m_vecDrawnLines[iIndex].Purge();
  236. }
  237. void CDrawingPanel::ClearAllLines()
  238. {
  239. for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ )
  240. {
  241. m_vecDrawnLines[iIndex].Purge();
  242. }
  243. }
  244. void CDrawingPanel::FireGameEvent( IGameEvent *event )
  245. {
  246. if ( FStrEq( event->GetName(), "cl_drawline" ) )
  247. {
  248. int iIndex = event->GetInt( "player" );
  249. // if this is NOT the local player (we've already stored our own data)
  250. if ( ( iIndex != GetLocalPlayerIndex() ) || engine->IsPlayingDemo() )
  251. {
  252. // If a player is muted for voice, also mute them for lines because jerks gonna jerk.
  253. if ( cl_mute_all_comms.GetBool() && ( iIndex != 0 ) )
  254. {
  255. if ( GetClientVoiceMgr() && GetClientVoiceMgr()->IsPlayerBlocked( iIndex ) )
  256. {
  257. ClearLines( iIndex );
  258. return;
  259. }
  260. }
  261. int iPanelType = event->GetInt( "panel" );
  262. // if this message is about our panel type
  263. if ( iPanelType == m_iPanelType )
  264. {
  265. int iLineType = event->GetInt( "line" );
  266. float x = event->GetFloat( "x" );
  267. float y = event->GetFloat( "y" );
  268. MapLine line;
  269. line.worldpos.x = (int)( x * GetWide() );
  270. line.worldpos.y = (int)( y * GetTall() );
  271. line.created_time = gpGlobals->curtime;
  272. if ( iLineType == 1 ) // links to a previous
  273. {
  274. line.bLink = true;
  275. }
  276. m_vecDrawnLines[iIndex].AddToTail( line );
  277. }
  278. }
  279. }
  280. }