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.

713 lines
18 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "client_pch.h"
  7. #include <vgui_controls/Frame.h>
  8. #include <vgui/ISystem.h>
  9. #include <vgui/ISurface.h>
  10. #include <vgui_controls/BuildGroup.h>
  11. #include <vgui_controls/Tooltip.h>
  12. #include <vgui_controls/TextImage.h>
  13. #include <vgui_controls/CheckButton.h>
  14. #include <vgui_controls/Label.h>
  15. #include <vgui_controls/PropertySheet.h>
  16. #include <vgui_controls/FileOpenDialog.h>
  17. #include <vgui_controls/ProgressBar.h>
  18. #include <vgui_controls/Slider.h>
  19. #include <vgui_controls/ComboBox.h>
  20. #include <vgui_controls/Controls.h>
  21. #include <vgui_controls/TextEntry.h>
  22. #include <vgui/IInput.h>
  23. #include "engineperftools.h"
  24. #include "vgui_baseui_interface.h"
  25. #include "ivideomode.h"
  26. #include "gl_cvars.h"
  27. #include "utlsymbol.h"
  28. #include "utldict.h"
  29. #include "filesystem.h"
  30. #include "filesystem_engine.h"
  31. #include "icliententitylist.h"
  32. #include "icliententity.h"
  33. #include "ModelInfo.h"
  34. // memdbgon must be the last include file in a .cpp file!!!
  35. #include "tier0/memdbgon.h"
  36. using namespace vgui;
  37. extern ConVar r_staticpropinfo;
  38. extern ConVar r_DrawPortals;
  39. extern ConVar r_visocclusion;
  40. extern ConVar r_occlusion;
  41. extern ConVar r_occluderminarea;
  42. extern ConVar r_occludeemaxarea;
  43. extern ConVar mat_wireframe;
  44. extern ConVar sv_cheats;
  45. // If you add a tool, add it to the string list and instance the panel in the constructor below
  46. enum PerformanceTool_t
  47. {
  48. PERF_TOOL_NONE = 0,
  49. PERF_TOOL_PROP_FADES,
  50. PERF_TOOL_AREA_PORTALS,
  51. PERF_TOOL_OCCLUSION,
  52. PERF_TOOL_COUNT,
  53. DEFAULT_PERF_TOOL = PERF_TOOL_NONE,
  54. };
  55. static const char *s_pPerfToolNames[PERF_TOOL_COUNT] =
  56. {
  57. "No Tool Active",
  58. "Prop Fade Distance Tool",
  59. "Area Portal Tool",
  60. "Occlusion Tool",
  61. };
  62. //-----------------------------------------------------------------------------
  63. // Base class for all perf tool panels
  64. //-----------------------------------------------------------------------------
  65. class CPerfUIChildPanel : public vgui::EditablePanel
  66. {
  67. DECLARE_CLASS_SIMPLE( CPerfUIChildPanel, vgui::EditablePanel );
  68. public:
  69. CPerfUIChildPanel( vgui::Panel *parent, const char *pName ) : BaseClass( parent, pName )
  70. {
  71. SetVisible( false );
  72. }
  73. virtual void Activate() {}
  74. virtual void Deactivate() {}
  75. };
  76. //-----------------------------------------------------------------------------
  77. //
  78. // The prop fade distance helper tool
  79. //
  80. //-----------------------------------------------------------------------------
  81. class CPropFadeUIPanel : public CPerfUIChildPanel
  82. {
  83. DECLARE_CLASS_SIMPLE( CPropFadeUIPanel, CPerfUIChildPanel );
  84. public:
  85. CPropFadeUIPanel( vgui::Panel *parent );
  86. ~CPropFadeUIPanel() {}
  87. void Activate();
  88. void Deactivate();
  89. protected:
  90. enum
  91. {
  92. VISUALIZE_NONE = 0,
  93. VISUALIZE_FADE_DISTANCE,
  94. VISUALIZE_FADE_SCREEN_WIDTH,
  95. VISUALIZE_TYPE_COUNT
  96. };
  97. void OnVisualizationSelected();
  98. MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
  99. vgui::ComboBox *m_pVisualization;
  100. vgui::TextEntry *m_pMinScreenArea;
  101. vgui::TextEntry *m_pMaxScreenArea;
  102. static const char *s_pFadeVisualizeLabel[VISUALIZE_TYPE_COUNT];
  103. };
  104. const char *CPropFadeUIPanel::s_pFadeVisualizeLabel[CPropFadeUIPanel::VISUALIZE_TYPE_COUNT] =
  105. {
  106. "No visualization",
  107. "Show Fade Distance",
  108. "Show Fade Screen Width"
  109. };
  110. //-----------------------------------------------------------------------------
  111. // Purpose:
  112. //-----------------------------------------------------------------------------
  113. CPropFadeUIPanel::CPropFadeUIPanel( vgui::Panel *parent ) : BaseClass( parent, "PropFadeUIPanel")
  114. {
  115. m_pVisualization = new ComboBox(this, "VisualizeMode", VISUALIZE_TYPE_COUNT, false);
  116. int i;
  117. for ( i = 0; i < ARRAYSIZE(s_pFadeVisualizeLabel); i++ )
  118. {
  119. m_pVisualization->AddItem( s_pFadeVisualizeLabel[i], NULL );
  120. }
  121. m_pVisualization->AddActionSignalTarget( this );
  122. m_pVisualization->ActivateItem( 0 );
  123. m_pMinScreenArea = new vgui::TextEntry( this, "MinFadeSize" );
  124. m_pMaxScreenArea = new vgui::TextEntry( this, "MaxFadeSize" );
  125. LoadControlSettings("Resource\\PerfPropFadeUIPanel.res");
  126. }
  127. //-----------------------------------------------------------------------------
  128. // Visualization changed
  129. //-----------------------------------------------------------------------------
  130. void CPropFadeUIPanel::OnTextChanged( KeyValues *data )
  131. {
  132. Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
  133. vgui::ComboBox *pBox = dynamic_cast<vgui::ComboBox *>( pPanel );
  134. if( pBox == m_pVisualization )
  135. {
  136. OnVisualizationSelected();
  137. return;
  138. }
  139. vgui::TextEntry *pText = dynamic_cast<vgui::TextEntry *>( pPanel );
  140. if (( pText == m_pMinScreenArea ) || ( pText == m_pMaxScreenArea ))
  141. {
  142. char buf[256];
  143. float flMinArea, flMaxArea;
  144. m_pMinScreenArea->GetText( buf, 256 );
  145. int nReadMin = sscanf( buf, "%f", &flMinArea );
  146. m_pMaxScreenArea->GetText( buf, 256 );
  147. int nReadMax = sscanf( buf, "%f", &flMaxArea );
  148. if ( nReadMin && nReadMax )
  149. {
  150. modelinfoclient->SetLevelScreenFadeRange( flMinArea, flMaxArea );
  151. }
  152. }
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Activate, deactivate:
  156. //-----------------------------------------------------------------------------
  157. void CPropFadeUIPanel::OnVisualizationSelected()
  158. {
  159. int tool = m_pVisualization->GetActiveItem();
  160. switch( tool )
  161. {
  162. case VISUALIZE_NONE:
  163. r_staticpropinfo.SetValue( 0 );
  164. break;
  165. case VISUALIZE_FADE_DISTANCE:
  166. r_staticpropinfo.SetValue( 3 );
  167. break;
  168. case VISUALIZE_FADE_SCREEN_WIDTH:
  169. r_staticpropinfo.SetValue( 4 );
  170. break;
  171. }
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Activate, deactivate:
  175. //-----------------------------------------------------------------------------
  176. void CPropFadeUIPanel::Activate()
  177. {
  178. float flMinArea, flMaxArea;
  179. modelinfoclient->GetLevelScreenFadeRange( &flMinArea, &flMaxArea );
  180. char buf[256];
  181. Q_snprintf( buf, 256, "%.2f", flMinArea );
  182. m_pMinScreenArea->SetText( buf );
  183. Q_snprintf( buf, 256, "%.2f", flMaxArea );
  184. m_pMaxScreenArea->SetText( buf );
  185. OnVisualizationSelected();
  186. }
  187. void CPropFadeUIPanel::Deactivate()
  188. {
  189. r_staticpropinfo.SetValue( 0 );
  190. }
  191. //-----------------------------------------------------------------------------
  192. // The areaportals helper tool
  193. //-----------------------------------------------------------------------------
  194. class CAreaPortalsUIPanel : public CPerfUIChildPanel
  195. {
  196. DECLARE_CLASS_SIMPLE( CAreaPortalsUIPanel, CPerfUIChildPanel );
  197. public:
  198. CAreaPortalsUIPanel( vgui::Panel *parent );
  199. ~CAreaPortalsUIPanel() {}
  200. void Activate();
  201. void Deactivate();
  202. };
  203. //-----------------------------------------------------------------------------
  204. // Purpose:
  205. //-----------------------------------------------------------------------------
  206. CAreaPortalsUIPanel::CAreaPortalsUIPanel( vgui::Panel *parent ) : BaseClass( parent, "AreaPortalUIPanel")
  207. {
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Activate, deactivate:
  211. //-----------------------------------------------------------------------------
  212. void CAreaPortalsUIPanel::Activate()
  213. {
  214. r_DrawPortals.SetValue( 1 );
  215. mat_wireframe.SetValue( 3 );
  216. }
  217. void CAreaPortalsUIPanel::Deactivate()
  218. {
  219. r_DrawPortals.SetValue( 0 );
  220. mat_wireframe.SetValue( 0 );
  221. }
  222. //-----------------------------------------------------------------------------
  223. // The occlusion helper tool
  224. //-----------------------------------------------------------------------------
  225. class COcclusionUIPanel : public CPerfUIChildPanel
  226. {
  227. DECLARE_CLASS_SIMPLE( COcclusionUIPanel, CPerfUIChildPanel );
  228. public:
  229. COcclusionUIPanel( vgui::Panel *parent );
  230. ~COcclusionUIPanel() {}
  231. void Activate();
  232. void Deactivate();
  233. protected:
  234. MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
  235. MESSAGE_FUNC_PTR( OnCheckButtonChecked, "CheckButtonChecked", panel );
  236. private:
  237. enum
  238. {
  239. VISUALIZE_NONE = 0,
  240. VISUALIZE_ON,
  241. VISUALIZE_TYPE_COUNT
  242. };
  243. void OnVisualizationSelected();
  244. void OnDeactivateOcclusion();
  245. vgui::ComboBox *m_pVisualization;
  246. vgui::TextEntry *m_pMinOccluderArea;
  247. vgui::TextEntry *m_pMaxOccludeeArea;
  248. vgui::CheckButton *m_pDeactivateOcclusion;
  249. static const char *s_pOccVisualizeLabel[VISUALIZE_TYPE_COUNT];
  250. };
  251. const char *COcclusionUIPanel::s_pOccVisualizeLabel[COcclusionUIPanel::VISUALIZE_TYPE_COUNT] =
  252. {
  253. "No visualization",
  254. "View occluders",
  255. };
  256. //-----------------------------------------------------------------------------
  257. // Purpose:
  258. //-----------------------------------------------------------------------------
  259. COcclusionUIPanel::COcclusionUIPanel( vgui::Panel *parent ) : BaseClass( parent, "AreaPortalUIPanel")
  260. {
  261. m_pVisualization = new ComboBox(this, "VisualizeMode", VISUALIZE_TYPE_COUNT, false);
  262. int i;
  263. for ( i = 0; i < VISUALIZE_TYPE_COUNT; i++ )
  264. {
  265. m_pVisualization->AddItem( s_pOccVisualizeLabel[i], NULL );
  266. }
  267. m_pVisualization->AddActionSignalTarget( this );
  268. m_pVisualization->ActivateItem( 0 );
  269. m_pMinOccluderArea = new vgui::TextEntry( this, "MinOccluderSize" );
  270. m_pMaxOccludeeArea = new vgui::TextEntry( this, "MaxOccludeeSize" );
  271. m_pDeactivateOcclusion = new vgui::CheckButton( this, "DeactivateOcclusion", "" );
  272. m_pDeactivateOcclusion->AddActionSignalTarget( this );
  273. LoadControlSettings("Resource\\PerfOcclusionUIPanel.res");
  274. }
  275. //-----------------------------------------------------------------------------
  276. // Activate, deactivate:
  277. //-----------------------------------------------------------------------------
  278. void COcclusionUIPanel::Activate()
  279. {
  280. OnVisualizationSelected();
  281. OnDeactivateOcclusion();
  282. char buf[256];
  283. Q_snprintf( buf, 256, "%.2f", r_occluderminarea.GetFloat() );
  284. m_pMinOccluderArea->SetText( buf );
  285. Q_snprintf( buf, 256, "%.2f", r_occludeemaxarea.GetFloat() );
  286. m_pMaxOccludeeArea->SetText( buf );
  287. }
  288. void COcclusionUIPanel::Deactivate()
  289. {
  290. r_visocclusion.SetValue( 0 );
  291. mat_wireframe.SetValue( 0 );
  292. }
  293. //-----------------------------------------------------------------------------
  294. // Visualization changed
  295. //-----------------------------------------------------------------------------
  296. void COcclusionUIPanel::OnTextChanged( KeyValues *data )
  297. {
  298. Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
  299. vgui::ComboBox *pBox = dynamic_cast<vgui::ComboBox *>( pPanel );
  300. if( pBox == m_pVisualization )
  301. {
  302. OnVisualizationSelected();
  303. return;
  304. }
  305. vgui::TextEntry *pText = dynamic_cast<vgui::TextEntry *>( pPanel );
  306. if (( pText == m_pMinOccluderArea ) || ( pText == m_pMaxOccludeeArea ))
  307. {
  308. char buf[256];
  309. float flMinArea, flMaxArea;
  310. m_pMinOccluderArea->GetText( buf, 256 );
  311. int nReadMin = sscanf( buf, "%f", &flMinArea );
  312. if ( nReadMin )
  313. {
  314. r_occluderminarea.SetValue( flMinArea );
  315. }
  316. m_pMaxOccludeeArea->GetText( buf, 256 );
  317. int nReadMax = sscanf( buf, "%f", &flMaxArea );
  318. if ( nReadMax )
  319. {
  320. r_occludeemaxarea.SetValue( flMaxArea );
  321. }
  322. }
  323. }
  324. //-----------------------------------------------------------------------------
  325. // Activate, deactivate:
  326. //-----------------------------------------------------------------------------
  327. void COcclusionUIPanel::OnVisualizationSelected()
  328. {
  329. int tool = m_pVisualization->GetActiveItem();
  330. switch( tool )
  331. {
  332. case VISUALIZE_NONE:
  333. r_visocclusion.SetValue( 0 );
  334. mat_wireframe.SetValue( 0 );
  335. break;
  336. case VISUALIZE_ON:
  337. r_visocclusion.SetValue( 1 );
  338. mat_wireframe.SetValue( 3 );
  339. break;
  340. }
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Activate, deactivate:
  344. //-----------------------------------------------------------------------------
  345. void COcclusionUIPanel::OnDeactivateOcclusion()
  346. {
  347. r_occlusion.SetValue( m_pDeactivateOcclusion->IsSelected() ? 0 : 1 );
  348. }
  349. void COcclusionUIPanel::OnCheckButtonChecked(Panel *panel)
  350. {
  351. if ( panel == m_pDeactivateOcclusion )
  352. {
  353. OnDeactivateOcclusion();
  354. }
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose:
  358. //-----------------------------------------------------------------------------
  359. class CPerfUIPanel : public vgui::Frame
  360. {
  361. DECLARE_CLASS_SIMPLE( CPerfUIPanel, vgui::Frame );
  362. public:
  363. CPerfUIPanel( vgui::Panel *parent );
  364. ~CPerfUIPanel();
  365. // Command issued
  366. virtual void OnCommand(const char *command);
  367. virtual void Activate();
  368. void Init();
  369. void Shutdown();
  370. virtual void OnKeyCodeTyped(KeyCode code);
  371. virtual void OnTick();
  372. protected:
  373. vgui::ComboBox *m_pPerformanceTool;
  374. MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
  375. private:
  376. void PopulateControls();
  377. void OnPerfToolSelected();
  378. PerformanceTool_t m_nPerfTool;
  379. CPerfUIChildPanel *m_pToolPanel[PERF_TOOL_COUNT];
  380. CPerfUIChildPanel *m_pCurrentToolPanel;
  381. };
  382. //-----------------------------------------------------------------------------
  383. // Purpose: Basic help dialog
  384. //-----------------------------------------------------------------------------
  385. CPerfUIPanel::CPerfUIPanel( vgui::Panel *parent ) : BaseClass( parent, "PerfUIPanel")
  386. {
  387. SetTitle("Level Performance Tools", true);
  388. m_pPerformanceTool = new ComboBox(this, "PerformanceTool", 10, false);
  389. vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
  390. LoadControlSettings("Resource\\PerfUIPanel.res");
  391. // Hidden by default
  392. SetVisible( false );
  393. SetSizeable( false );
  394. SetMoveable( true );
  395. int w = 250;
  396. int h = 400;
  397. int x = videomode->GetModeStereoWidth() - w - 10;
  398. int y = ( videomode->GetModeStereoHeight() - h ) / 2 + videomode->GetModeStereoHeight() * 0.2;
  399. SetBounds( x, y, w, h );
  400. // Create the child tool panels
  401. m_pToolPanel[PERF_TOOL_NONE] = new CPerfUIChildPanel( this, "PerfNone" );
  402. m_pToolPanel[PERF_TOOL_PROP_FADES] = new CPropFadeUIPanel( this );
  403. m_pToolPanel[PERF_TOOL_AREA_PORTALS] = new CAreaPortalsUIPanel( this );
  404. m_pToolPanel[PERF_TOOL_OCCLUSION] = new COcclusionUIPanel( this );
  405. for ( int i = 0; i < PERF_TOOL_COUNT; ++i )
  406. {
  407. m_pToolPanel[i]->SetBounds( 0, 75, w, h - 75 );
  408. }
  409. m_nPerfTool = PERF_TOOL_COUNT;
  410. m_pCurrentToolPanel = NULL;
  411. PopulateControls();
  412. }
  413. CPerfUIPanel::~CPerfUIPanel()
  414. {
  415. }
  416. //-----------------------------------------------------------------------------
  417. // Init, shutdown
  418. //-----------------------------------------------------------------------------
  419. void CPerfUIPanel::Init()
  420. {
  421. // Center the cursor on the panel
  422. int x, y, w, h;
  423. GetBounds( x, y, w, h );
  424. vgui::input()->SetCursorPos( x + w/2, y + h/2 );
  425. }
  426. void CPerfUIPanel::Shutdown()
  427. {
  428. if ( m_pCurrentToolPanel )
  429. {
  430. m_pCurrentToolPanel->Deactivate();
  431. m_pCurrentToolPanel->SetVisible( false );
  432. }
  433. }
  434. void CPerfUIPanel::PopulateControls()
  435. {
  436. m_pPerformanceTool->DeleteAllItems();
  437. int i;
  438. for ( i = 0; i < PERF_TOOL_COUNT; i++ )
  439. {
  440. m_pPerformanceTool->AddItem( s_pPerfToolNames[i], NULL );
  441. }
  442. m_pPerformanceTool->AddActionSignalTarget( this );
  443. m_pPerformanceTool->ActivateItem( 0 );
  444. }
  445. //-----------------------------------------------------------------------------
  446. // Don't allow this to be enabled without cheats turned on.
  447. //-----------------------------------------------------------------------------
  448. void CPerfUIPanel::OnTick()
  449. {
  450. // Go away if we were on and sv_cheats is now on.
  451. if ( !CanCheat() )
  452. {
  453. Shutdown();
  454. }
  455. BaseClass::OnTick();
  456. }
  457. //-----------------------------------------------------------------------------
  458. // A new performance tool was selected
  459. //-----------------------------------------------------------------------------
  460. void CPerfUIPanel::OnTextChanged( KeyValues *data )
  461. {
  462. Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
  463. vgui::ComboBox *pBox = dynamic_cast<vgui::ComboBox *>( pPanel );
  464. if( pBox == m_pPerformanceTool ) // don't change the text in the config setting combo
  465. {
  466. OnPerfToolSelected();
  467. }
  468. }
  469. void CPerfUIPanel::OnPerfToolSelected()
  470. {
  471. int tool = m_pPerformanceTool->GetActiveItem();
  472. if ( tool == m_nPerfTool )
  473. return;
  474. if ( m_pCurrentToolPanel )
  475. {
  476. m_pCurrentToolPanel->Deactivate();
  477. m_pCurrentToolPanel->SetVisible( false );
  478. }
  479. m_nPerfTool = (PerformanceTool_t)tool;
  480. m_pCurrentToolPanel = m_pToolPanel[tool];
  481. m_pCurrentToolPanel->SetVisible( true );
  482. m_pCurrentToolPanel->Activate();
  483. }
  484. //-----------------------------------------------------------------------------
  485. // Purpose: Shows the panel
  486. //-----------------------------------------------------------------------------
  487. void CPerfUIPanel::Activate()
  488. {
  489. if ( !CanCheat() )
  490. return;
  491. Init();
  492. BaseClass::Activate();
  493. }
  494. void CPerfUIPanel::OnCommand( char const *command )
  495. {
  496. if ( !Q_strcasecmp( command, "submit" ) )
  497. {
  498. // OnSubmit();
  499. }
  500. else if ( !Q_strcasecmp( command, "cancel" ) )
  501. {
  502. // Close();
  503. }
  504. else
  505. {
  506. BaseClass::OnCommand( command );
  507. }
  508. }
  509. //-----------------------------------------------------------------------------
  510. // Purpose:
  511. //-----------------------------------------------------------------------------
  512. void CPerfUIPanel::OnKeyCodeTyped(KeyCode code)
  513. {
  514. switch( code )
  515. {
  516. case KEY_ESCAPE:
  517. Close();
  518. break;
  519. default:
  520. BaseClass::OnKeyCodeTyped( code );
  521. break;
  522. }
  523. }
  524. //-----------------------------------------------------------------------------
  525. // Main interface to the performance tools
  526. //-----------------------------------------------------------------------------
  527. static CPerfUIPanel *g_pPerfUI = NULL;
  528. class CEnginePerfTools : public IEnginePerfTools
  529. {
  530. public:
  531. virtual void Init( void );
  532. virtual void Shutdown( void );
  533. virtual void InstallPerformanceToolsUI( vgui::Panel *parent );
  534. virtual bool ShouldPause() const;
  535. };
  536. static CEnginePerfTools g_PerfTools;
  537. IEnginePerfTools *perftools = &g_PerfTools;
  538. void CEnginePerfTools::Init( void )
  539. {
  540. }
  541. void CEnginePerfTools::Shutdown( void )
  542. {
  543. if ( g_pPerfUI )
  544. {
  545. g_pPerfUI->Shutdown();
  546. }
  547. }
  548. void CEnginePerfTools::InstallPerformanceToolsUI( vgui::Panel *parent )
  549. {
  550. if ( g_pPerfUI )
  551. return;
  552. g_pPerfUI = new CPerfUIPanel( parent );
  553. Assert( g_pPerfUI );
  554. }
  555. bool CEnginePerfTools::ShouldPause() const
  556. {
  557. return false;
  558. }
  559. void ShowHidePerfUI()
  560. {
  561. if ( !g_pPerfUI )
  562. return;
  563. bool wasvisible = g_pPerfUI->IsVisible();
  564. if ( wasvisible )
  565. {
  566. // hide
  567. g_pPerfUI->Close();
  568. }
  569. else
  570. {
  571. g_pPerfUI->Activate();
  572. }
  573. }
  574. static ConCommand perfui( "perfui", ShowHidePerfUI, "Show/hide the level performance tools UI.", FCVAR_CHEAT );