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.

731 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include <stdio.h>
  8. #include "GraphPanel.h"
  9. #include <vgui/ISystem.h>
  10. #include <vgui/ISurface.h>
  11. #include <vgui/IVGui.h>
  12. #include <vgui/IScheme.h>
  13. #include <vgui/ILocalize.h>
  14. #include <KeyValues.h>
  15. #include <vgui_controls/Label.h>
  16. #include <vgui_controls/TextEntry.h>
  17. #include <vgui_controls/Button.h>
  18. #include <vgui_controls/ToggleButton.h>
  19. #include <vgui_controls/RadioButton.h>
  20. #include <vgui_controls/ListPanel.h>
  21. #include <vgui_controls/ComboBox.h>
  22. #include <vgui_controls/PHandle.h>
  23. #include <vgui_controls/PropertySheet.h>
  24. #include <vgui_controls/CheckButton.h>
  25. #define max(a,b) (((a) > (b)) ? (a) : (b))
  26. #define STATS_UPDATE_RATE 5.0f
  27. // colors for the various graph lines+controls
  28. Color CGraphPanel::CGraphsImage::CPUColor= Color(0,255,0,255); // green
  29. Color CGraphPanel::CGraphsImage::FPSColor= Color(255,0,0,255); // red
  30. Color CGraphPanel::CGraphsImage::NetInColor = Color(255,255,0,255); // yellow
  31. Color CGraphPanel::CGraphsImage::NetOutColor = Color(0,255,255,255); // light blue
  32. Color CGraphPanel::CGraphsImage::PlayersColor = Color(255,0,255,255); // purple
  33. Color CGraphPanel::CGraphsImage::PingColor = Color(0,0,0,255); // black
  34. //Color CGraphPanel::CGraphsImage::lineColor = Color(76,88,68,255);
  35. using namespace vgui;
  36. //-----------------------------------------------------------------------------
  37. // Purpose: Constructor
  38. //-----------------------------------------------------------------------------
  39. CGraphPanel::CGraphPanel(vgui::Panel *parent, const char *name) : PropertyPage(parent, name)
  40. {
  41. SetMinimumSize(300,200);
  42. m_pGraphsPanel = new ImagePanel(this,"Graphs");
  43. m_pGraphs = new CGraphsImage();
  44. m_pGraphsPanel->SetImage(m_pGraphs);
  45. m_pInButton = new CheckButton(this,"InCheck","#Graph_In");
  46. m_pOutButton = new CheckButton(this,"OutCheck","#Graph_Out");
  47. m_pFPSButton = new CheckButton(this,"FPSCheck","#Graph_FPS");
  48. m_pCPUButton = new CheckButton(this,"CPUCheck","#Graph_CPU");
  49. m_pPINGButton = new CheckButton(this,"PingCheck","#Graph_Ping");
  50. m_pPlayerButton = new CheckButton(this,"PlayersCheck","#Graph_Players");
  51. m_pTimeCombo = new ComboBox(this, "TimeCombo",3,false);
  52. m_pTimeCombo->AddItem("#Graph_Minutes", NULL);
  53. int defaultItem = m_pTimeCombo->AddItem("#Graph_Hours", NULL);
  54. m_pTimeCombo->AddItem("#Graph_Day", NULL);
  55. m_pTimeCombo->ActivateItem(defaultItem);
  56. m_pVertCombo = new ComboBox(this, "VertCombo",6,false);
  57. m_pVertCombo->AddItem("#Graph_In", NULL);
  58. m_pVertCombo->AddItem("#Graph_Out", NULL);
  59. m_pVertCombo->AddItem("#Graph_FPS", NULL);
  60. defaultItem = m_pVertCombo->AddItem("#Graph_CPU", NULL);
  61. m_pVertCombo->AddItem("#Graph_Ping", NULL);
  62. m_pVertCombo->AddItem("#Graph_Players", NULL);
  63. m_pVertCombo->ActivateItem(defaultItem);
  64. // now setup defaults
  65. m_pCPUButton->SetSelected(true);
  66. m_pInButton->SetSelected(false);
  67. m_pOutButton->SetSelected(false);
  68. m_pFPSButton->SetSelected(false);
  69. m_pPINGButton->SetSelected(false);
  70. LoadControlSettings("Admin/GraphPanel.res", "PLATFORM");
  71. int w,h;
  72. m_pGraphsPanel->GetSize(w,h);
  73. m_pGraphs->SaveSize(w,h);
  74. m_pGraphs->SetDraw(m_pCPUButton->IsSelected(),m_pFPSButton->IsSelected(),
  75. m_pInButton->IsSelected(),m_pOutButton->IsSelected(),m_pPINGButton->IsSelected(),m_pPlayerButton->IsSelected());
  76. m_pPINGButton->SetFgColor(m_pGraphs->GetPingColor());
  77. m_pCPUButton->SetFgColor(m_pGraphs->GetCPUColor());
  78. m_pFPSButton->SetFgColor(m_pGraphs->GetFPSColor());
  79. m_pInButton->SetFgColor(m_pGraphs->GetInColor());
  80. m_pOutButton->SetFgColor(m_pGraphs->GetOutColor());
  81. m_pPlayerButton->SetFgColor(m_pGraphs->GetPlayersColor());
  82. ivgui()->AddTickSignal(GetVPanel());
  83. m_flNextStatsUpdateTime = 0;
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Purpose: Destructor
  87. //-----------------------------------------------------------------------------
  88. CGraphPanel::~CGraphPanel()
  89. {
  90. }
  91. void CGraphPanel::ApplySchemeSettings( IScheme *pScheme )
  92. {
  93. BaseClass::ApplySchemeSettings( pScheme );
  94. m_pGraphsPanel->SetBorder( pScheme->GetBorder("ButtonDepressedBorder"));
  95. m_pGraphs->SetBgColor(GetSchemeColor("WindowBG", pScheme));
  96. m_pGraphs->SetAxisColor(Color(76,88,68,255));
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Purpose: Activates the page
  100. //-----------------------------------------------------------------------------
  101. void CGraphPanel::OnPageShow()
  102. {
  103. BaseClass::OnPageShow();
  104. }
  105. //-----------------------------------------------------------------------------
  106. // Purpose: Hides the page
  107. //-----------------------------------------------------------------------------
  108. void CGraphPanel::OnPageHide()
  109. {
  110. BaseClass::OnPageHide();
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Purpose: called every frame to update stats page
  114. //-----------------------------------------------------------------------------
  115. void CGraphPanel::OnTick()
  116. {
  117. if (m_flNextStatsUpdateTime > system()->GetFrameTime())
  118. return;
  119. m_flNextStatsUpdateTime = (float)system()->GetFrameTime() + STATS_UPDATE_RATE;
  120. RemoteServer().RequestValue(this, "stats");
  121. }
  122. //-----------------------------------------------------------------------------
  123. // Purpose: tells the image about the new size
  124. //-----------------------------------------------------------------------------
  125. void CGraphPanel::PerformLayout()
  126. {
  127. BaseClass::PerformLayout();
  128. int w,h,x,y;
  129. m_pGraphsPanel->GetBounds(x,y,w,h);
  130. m_pGraphs->SaveSize(w,h); // tell the image about the resize
  131. // push the mid axis label to the middle of the image
  132. Label *entry = dynamic_cast<Label *>(FindChildByName("AxisMid"));
  133. if (entry)
  134. {
  135. int entry_x,entry_y;
  136. entry->GetPos(entry_x,entry_y);
  137. entry->SetPos(entry_x,y+(h/2)-8);
  138. }
  139. }
  140. //-----------------------------------------------------------------------------
  141. // Purpose: Handles stats command returns
  142. //-----------------------------------------------------------------------------
  143. void CGraphPanel::OnServerDataResponse(const char *value, const char *response)
  144. {
  145. if (!stricmp(value, "stats"))
  146. {
  147. // parse the stats out of the response
  148. Points_t p;
  149. float uptime, users;
  150. sscanf(response, "%f %f %f %f %f %f %f", &p.cpu, &p.in, &p.out, &uptime, &users, &p.fps, &p.players);
  151. p.cpu = p.cpu / 100; // its given as a value between 0<x<100, we want 0<x<1
  152. p.ping = 0;
  153. p.time = (float)system()->GetCurrentTime();
  154. m_pGraphs->AddPoint(p);
  155. // days:hours:minutes:seconds
  156. char timeText[64];
  157. _snprintf(timeText, sizeof(timeText), "%i", (int)p.players);
  158. SetControlString("TotalUsersLabel", timeText);
  159. // mark the vert combo has changed to force it to update graph ranges
  160. m_pVertCombo->GetText(timeText, 64);
  161. OnTextChanged(m_pVertCombo, timeText);
  162. }
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Purpose: the paint routine for the graph image. Handles the layout and drawing of the graph image
  166. //-----------------------------------------------------------------------------
  167. void CGraphPanel::CGraphsImage::Paint()
  168. {
  169. int x,y;
  170. float distPoints; // needs to be a float, rounding errors cause problems with lots of points
  171. int bottom=5; // be 5 pixels above the bottom
  172. int left=2;
  173. int *pCpuX=NULL, *pCpuY=NULL;
  174. int *pInX=NULL, *pInY=NULL;
  175. int *pOutX=NULL, *pOutY=NULL;
  176. int *pFPSX=NULL, *pFPSY=NULL;
  177. int *pPingX=NULL, *pPingY=NULL;
  178. int *pPlayersX=NULL, *pPlayersY=NULL;
  179. GetSize(x,y);
  180. SetColor(bgColor);
  181. SetBkColor(bgColor);
  182. DrawFilledRect(0,0,x,y);
  183. y-=4; // borders
  184. x-=4;
  185. if(!cpu && !fps && !net_i && !net_o && !ping && !players) // no graphs selected
  186. return;
  187. if(points.Count()<2)
  188. return; // not enough points yet...
  189. if(x<=200 || y<=100)
  190. return; // to small
  191. distPoints= static_cast<float>(x)/static_cast<float>(points.Count()-1);
  192. if(distPoints<=0)
  193. {
  194. distPoints=1;
  195. }
  196. SetColor(lineColor);
  197. SetBkColor(lineColor);
  198. //DrawLine(4,5,x,5);
  199. DrawLine(4,y/2,x,y/2);
  200. //DrawLine(4,y,x,y);
  201. float RangePing=maxPing;
  202. float RangeFPS=maxFPS;
  203. float Range=0;
  204. float RangePlayers=maxPlayers;
  205. if(ping)
  206. {
  207. RangePing+=static_cast<float>(maxPing*0.1); // don't let the top of the range touch the top of the panel
  208. if(RangePing<=1)
  209. { // don't let the zero be at the top of the screen
  210. RangePing=1.0;
  211. }
  212. pPingX = new int[points.Count()];
  213. pPingY = new int[points.Count()];
  214. }
  215. if(cpu)
  216. {
  217. pCpuX = new int[points.Count()];
  218. pCpuY = new int[points.Count()];
  219. }
  220. if(fps)
  221. {
  222. RangeFPS+=static_cast<float>(maxFPS*0.1); // don't let the top of the range touch the top of the panel
  223. if(RangeFPS<=1)
  224. { // don't let the zero be at the top of the screen
  225. RangeFPS=1.0;
  226. }
  227. pFPSX = new int[points.Count()];
  228. pFPSY = new int[points.Count()];
  229. }
  230. if(net_i)
  231. {
  232. // put them on a common scale, base it at zero
  233. Range = max(maxIn,maxOut);
  234. Range+=static_cast<float>(Range*0.1); // don't let the top of the range touch the top of the panel
  235. if(Range<=1)
  236. { // don't let the zero be at the top of the screen
  237. Range=1.0;
  238. }
  239. pInX = new int[points.Count()];
  240. pInY = new int[points.Count()];
  241. }
  242. if(net_o)
  243. {
  244. // put them on a common scale, base it at zero
  245. Range = max(maxIn,maxOut);
  246. Range+=static_cast<float>(Range*0.1); // don't let the top of the range touch the top of the panel
  247. if(Range<=1)
  248. { // don't let the zero be at the top of the screen
  249. Range=1.0;
  250. }
  251. pOutX = new int[points.Count()];
  252. pOutY = new int[points.Count()];
  253. }
  254. if(players)
  255. {
  256. RangePlayers+=static_cast<float>(maxPlayers*0.1); // don't let the top of the range touch the top of the panel
  257. pPlayersX = new int[points.Count()];
  258. pPlayersY = new int[points.Count()];
  259. }
  260. for(int i=0;i<points.Count();i++)
  261. // draw the graphs, left to right
  262. {
  263. if(cpu)
  264. {
  265. pCpuX[i] = left+static_cast<int>(i*distPoints);
  266. pCpuY[i] = static_cast<int>((1-points[i].cpu)*y);
  267. }
  268. if(net_i)
  269. {
  270. pInX[i] = left+static_cast<int>(i*distPoints);
  271. pInY[i] = static_cast<int>(( (Range-points[i].in)/Range)*y-bottom);
  272. }
  273. if(net_o)
  274. {
  275. pOutX[i] = left+static_cast<int>(i*distPoints);
  276. pOutY[i] = static_cast<int>(((Range-points[i].out)/Range)*y-bottom);
  277. }
  278. if(fps)
  279. {
  280. pFPSX[i] = left+static_cast<int>(i*distPoints);
  281. pFPSY[i] = static_cast<int>(( (RangeFPS-points[i].fps)/RangeFPS)*y-bottom);
  282. }
  283. if(ping)
  284. {
  285. pPingX[i] = left+static_cast<int>(i*distPoints);
  286. pPingY[i] = static_cast<int>(( (RangePing-points[i].ping)/RangePing)*y-bottom);
  287. }
  288. if(players)
  289. {
  290. pPlayersX[i] = left+static_cast<int>(i*distPoints);
  291. pPlayersY[i] = static_cast<int>(( (RangePlayers-points[i].players)/RangePlayers)*y-bottom);
  292. }
  293. }
  294. // we use DrawPolyLine, its much, much, much more efficient than calling lots of DrawLine()'s
  295. if(cpu)
  296. {
  297. SetColor(CPUColor); // green
  298. DrawPolyLine(pCpuX, pCpuY, points.Count());
  299. delete [] pCpuX;
  300. delete [] pCpuY;
  301. }
  302. if(net_i)
  303. {
  304. SetColor(NetInColor); // red
  305. DrawPolyLine(pInX, pInY, points.Count());
  306. delete [] pInX;
  307. delete [] pInY;
  308. }
  309. if(net_o)
  310. {
  311. SetColor(NetOutColor); //yellow
  312. DrawPolyLine(pOutX, pOutY, points.Count());
  313. delete [] pOutX;
  314. delete [] pOutY;
  315. }
  316. if(fps)
  317. {
  318. SetColor(FPSColor);
  319. DrawPolyLine(pFPSX, pFPSY, points.Count());
  320. delete [] pFPSX;
  321. delete [] pFPSY;
  322. }
  323. if(ping)
  324. {
  325. SetColor(PingColor);
  326. DrawPolyLine(pPingX, pPingY, points.Count());
  327. delete [] pPingX;
  328. delete [] pPingY;
  329. }
  330. if(players)
  331. {
  332. SetColor(PlayersColor);
  333. DrawPolyLine(pPlayersX, pPlayersY, points.Count());
  334. delete [] pPlayersX;
  335. delete [] pPlayersY;
  336. }
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Purpose: constructor for the graphs image
  340. //-----------------------------------------------------------------------------
  341. CGraphPanel::CGraphsImage::CGraphsImage(): vgui::Image(), points()
  342. {
  343. maxIn=maxOut=minIn=minOut=minFPS=maxFPS=minPing=maxPing=0;
  344. net_i=net_o=fps=cpu=ping=players=false;
  345. numAvgs=0;
  346. memset(&avgPoint,0x0,sizeof(Points_t));
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Purpose: sets which graph to draw, true means draw it
  350. //-----------------------------------------------------------------------------
  351. void CGraphPanel::CGraphsImage::SetDraw(bool cpu_in,bool fps_in,bool net_in,bool net_out,bool ping_in,bool players_in)
  352. {
  353. cpu=cpu_in;
  354. fps=fps_in;
  355. net_i=net_in;
  356. net_o=net_out;
  357. ping=ping_in;
  358. players=players_in;
  359. }
  360. //-----------------------------------------------------------------------------
  361. // Purpose: used to average points over a period of time
  362. //-----------------------------------------------------------------------------
  363. void CGraphPanel::CGraphsImage::AvgPoint(Points_t p)
  364. {
  365. avgPoint.cpu += p.cpu;
  366. avgPoint.fps += p.fps;
  367. avgPoint.in += p.in;
  368. avgPoint.out += p.out;
  369. avgPoint.ping += p.ping;
  370. avgPoint.players += p.players;
  371. numAvgs++;
  372. }
  373. //-----------------------------------------------------------------------------
  374. // Purpose: updates the current bounds of the points based on this new point
  375. //-----------------------------------------------------------------------------
  376. void CGraphPanel::CGraphsImage::CheckBounds(Points_t p)
  377. {
  378. if(p.in>maxIn)
  379. {
  380. maxIn=avgPoint.in;
  381. }
  382. if(p.out>maxOut)
  383. {
  384. maxOut=avgPoint.out;
  385. }
  386. if(p.in<minIn)
  387. {
  388. minIn=avgPoint.in;
  389. }
  390. if(p.out<minOut)
  391. {
  392. minOut=avgPoint.out;
  393. }
  394. if(p.fps>maxFPS)
  395. {
  396. maxFPS=avgPoint.fps;
  397. }
  398. if(p.fps<minFPS)
  399. {
  400. minFPS=avgPoint.fps;
  401. }
  402. if(p.ping>maxPing)
  403. {
  404. maxPing=avgPoint.ping;
  405. }
  406. if(p.ping<minPing)
  407. {
  408. minPing=avgPoint.ping;
  409. }
  410. if(p.players>maxPlayers)
  411. {
  412. maxPlayers=avgPoint.players;
  413. }
  414. if(p.players<minPlayers)
  415. {
  416. minPlayers=avgPoint.players;
  417. }
  418. }
  419. //-----------------------------------------------------------------------------
  420. // Purpose: adds a point to the graph image.
  421. //-----------------------------------------------------------------------------
  422. bool CGraphPanel::CGraphsImage::AddPoint(Points_t p)
  423. {
  424. int x,y;
  425. bool recalcBounds=false;
  426. GetSize(x,y);
  427. if(avgPoint.cpu>1) // cpu is a percent !
  428. {
  429. return false;
  430. }
  431. if(timeBetween==SECONDS) // most recent minute
  432. {
  433. while(points.Count() && (p.time-points[0].time)>60)
  434. {
  435. points.Remove(0);
  436. }
  437. }
  438. else if(timeBetween==HOURS) // most recent hour
  439. {
  440. while(points.Count() && (p.time-points[0].time)>60*60)
  441. {
  442. points.Remove(0);
  443. }
  444. }
  445. else if ( timeBetween==MINUTES) // most recent day
  446. {
  447. while(points.Count() && (p.time-points[0].time)>60*60*24)
  448. {
  449. points.Remove(0);
  450. }
  451. }
  452. AvgPoint(p);
  453. // now work out the average of all the values
  454. avgPoint.cpu /= numAvgs;
  455. avgPoint.fps /= numAvgs;
  456. avgPoint.in /= numAvgs;
  457. avgPoint.out /= numAvgs;
  458. avgPoint.ping /= numAvgs;
  459. avgPoint.players /= numAvgs;
  460. avgPoint.time = p.time;
  461. numAvgs=0;
  462. int k=0;
  463. if(x!=0 && points.Count()> x/2)
  464. // there are more points than pixels so thin them out
  465. {
  466. while(points.Count()> x/2)
  467. {
  468. // check that the bounds don't move
  469. if(points[0].in==maxIn ||
  470. points[0].out==maxOut ||
  471. points[0].fps==maxFPS ||
  472. points[0].ping==maxPing ||
  473. points[0].players==maxPlayers)
  474. {
  475. recalcBounds=true;
  476. }
  477. points.Remove(k); // remove the head node
  478. k+=2;
  479. if(k>points.Count())
  480. {
  481. k=0;
  482. }
  483. }
  484. }
  485. if(recalcBounds)
  486. {
  487. for(int i=0;i<points.Count();i++)
  488. {
  489. CheckBounds(points[i]);
  490. }
  491. }
  492. CheckBounds(avgPoint);
  493. points.AddToTail(avgPoint);
  494. memset(&avgPoint,0x0,sizeof(Points_t));
  495. return true;
  496. }
  497. void CGraphPanel::CGraphsImage::SetScale(intervals time)
  498. {
  499. timeBetween=time;
  500. // scale is reset so remove all the points
  501. points.RemoveAll();
  502. // and reset the maxes
  503. maxIn=maxOut=minIn=minOut=minFPS=maxFPS=minPing=maxPing=maxPlayers=minPlayers=0;
  504. }
  505. //-----------------------------------------------------------------------------
  506. // Purpose: clear button handler, clears the current points
  507. //-----------------------------------------------------------------------------
  508. void CGraphPanel::OnClearButton()
  509. {
  510. m_pGraphs->RemovePoints();
  511. }
  512. //-----------------------------------------------------------------------------
  513. // Purpose: passes the state of the check buttons (for graph line display) through to the graph image
  514. //-----------------------------------------------------------------------------
  515. void CGraphPanel::OnCheckButton()
  516. {
  517. m_pGraphs->SetDraw(m_pCPUButton->IsSelected(), m_pFPSButton->IsSelected(), m_pInButton->IsSelected(), m_pOutButton->IsSelected(), m_pPINGButton->IsSelected(), m_pPlayerButton->IsSelected());
  518. }
  519. //-----------------------------------------------------------------------------
  520. // Purpose:Handles the scale radio buttons, passes the scale to use through to the graph image
  521. //-----------------------------------------------------------------------------
  522. void CGraphPanel::OnTextChanged(Panel *panel, const char *text)
  523. {
  524. if (panel == m_pTimeCombo)
  525. {
  526. if (strstr(text, "Hour"))
  527. {
  528. m_pGraphs->SetScale(MINUTES);
  529. }
  530. else if (strstr(text, "Day"))
  531. {
  532. m_pGraphs->SetScale(HOURS);
  533. }
  534. else
  535. {
  536. m_pGraphs->SetScale(SECONDS);
  537. }
  538. }
  539. else if (panel == m_pVertCombo)
  540. {
  541. float maxVal, minVal;
  542. char minText[20], midText[20], maxText[20];
  543. if (strstr(text, "CPU"))
  544. {
  545. SetAxisLabels(m_pGraphs->GetCPUColor(), "100%", "50%", "0%");
  546. }
  547. else if (strstr(text, "FPS"))
  548. {
  549. m_pGraphs->GetFPSLimits(maxVal, minVal);
  550. sprintf(maxText,"%0.2f", maxVal);
  551. sprintf(midText,"%0.2f", (maxVal - minVal) / 2);
  552. sprintf(minText,"%0.2f", minVal);
  553. SetAxisLabels(m_pGraphs->GetFPSColor(), maxText, midText, minText);
  554. }
  555. else if (strstr(text, "In"))
  556. {
  557. m_pGraphs->GetInLimits(maxVal, minVal);
  558. sprintf(maxText,"%0.2f", maxVal);
  559. sprintf(midText,"%0.2f", (maxVal - minVal) / 2);
  560. sprintf(minText,"%0.2f", minVal);
  561. SetAxisLabels(m_pGraphs->GetInColor(), maxText, midText, minText);
  562. }
  563. else if (strstr(text, "Out"))
  564. {
  565. m_pGraphs->GetOutLimits(maxVal, minVal);
  566. sprintf(maxText,"%0.2f", maxVal);
  567. sprintf(midText,"%0.2f", (maxVal - minVal) / 2);
  568. sprintf(minText,"%0.2f", minVal);
  569. SetAxisLabels(m_pGraphs->GetOutColor(), maxText, midText, minText);
  570. }
  571. else if (strstr(text, "Ping"))
  572. {
  573. m_pGraphs->GetPingLimits(maxVal, minVal);
  574. sprintf(maxText,"%0.2f", maxVal);
  575. sprintf(midText,"%0.2f", (maxVal - minVal) / 2);
  576. sprintf(minText,"%0.2f", minVal);
  577. SetAxisLabels(m_pGraphs->GetPingColor(), maxText, midText, minText);
  578. }
  579. else if (strstr(text, "Players"))
  580. {
  581. m_pGraphs->GetPlayerLimits(maxVal, minVal);
  582. sprintf(maxText,"%0.2f", maxVal);
  583. sprintf(midText,"%0.2f", (maxVal - minVal) / 2);
  584. sprintf(minText,"%0.2f", minVal);
  585. SetAxisLabels(m_pGraphs->GetPlayersColor(), maxText, midText, minText);
  586. }
  587. }
  588. }
  589. //-----------------------------------------------------------------------------
  590. // Purpose:
  591. //-----------------------------------------------------------------------------
  592. void CGraphPanel::SetAxisLabels(Color c, char *max, char *mid, char *min)
  593. {
  594. Label *lab;
  595. lab= GetLabel("AxisMax");
  596. if(lab)
  597. {
  598. lab->SetFgColor(c);
  599. lab->SetText(max);
  600. }
  601. lab = GetLabel("AxisMid");
  602. if(lab)
  603. {
  604. lab->SetFgColor(c);
  605. lab->SetText(mid);
  606. }
  607. lab = GetLabel("AxisMin");
  608. if(lab)
  609. {
  610. lab->SetFgColor(c);
  611. lab->SetText(min);
  612. }
  613. }
  614. Label *CGraphPanel::GetLabel(const char *name)
  615. {
  616. Label *lab = dynamic_cast<Label *>(FindChildByName(name));
  617. return lab;
  618. }