Counter Strike : Global Offensive Source Code
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.

564 lines
15 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "client_pch.h"
  7. #include <vgui/IClientPanel.h>
  8. #include <vgui_controls/TreeView.h>
  9. #include <vgui_controls/EditablePanel.h>
  10. #include <vgui_controls/Frame.h>
  11. #include <vgui_controls/CheckButton.h>
  12. #include "convar.h"
  13. #include "tier0/vprof.h"
  14. #include "vgui_baseui_interface.h"
  15. #include "vgui_helpers.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. using namespace vgui;
  19. bool g_bForceRefresh = true;
  20. void ChangeCallback_RefreshDrawTree( IConVar *var, const char *pOldString, float flValue )
  21. {
  22. g_bForceRefresh = true;
  23. }
  24. // Bunch of vgui debugging stuff
  25. static ConVar vgui_drawtree( "vgui_drawtree", "0", FCVAR_CHEAT, "Draws the vgui panel hiearchy to the specified depth level." );
  26. static ConVar vgui_drawtree_visible( "vgui_drawtree_visible", "1", 0, "Draw the visible panels.", ChangeCallback_RefreshDrawTree );
  27. static ConVar vgui_drawtree_hidden( "vgui_drawtree_hidden", "0", 0, "Draw the hidden panels.", ChangeCallback_RefreshDrawTree );
  28. static ConVar vgui_drawtree_popupsonly( "vgui_drawtree_popupsonly", "0", 0, "Draws the vgui popup list in hierarchy(1) or most recently used(2) order.", ChangeCallback_RefreshDrawTree );
  29. static ConVar vgui_drawtree_freeze( "vgui_drawtree_freeze", "0", 0, "Set to 1 to stop updating the vgui_drawtree view.", ChangeCallback_RefreshDrawTree );
  30. static ConVar vgui_drawtree_panelptr( "vgui_drawtree_panelptr", "0", 0, "Show the panel pointer values in the vgui_drawtree view.", ChangeCallback_RefreshDrawTree );
  31. static ConVar vgui_drawtree_panelalpha( "vgui_drawtree_panelalpha", "0", 0, "Show the panel alpha values in the vgui_drawtree view.", ChangeCallback_RefreshDrawTree );
  32. static ConVar vgui_drawtree_render_order( "vgui_drawtree_render_order", "0", 0, "List the vgui_drawtree panels in render order.", ChangeCallback_RefreshDrawTree );
  33. static ConVar vgui_drawtree_bounds( "vgui_drawtree_bounds", "0", 0, "Show panel bounds.", ChangeCallback_RefreshDrawTree );
  34. static ConVar vgui_drawtree_draw_selected( "vgui_drawtree_draw_selected", "0", 0, "Highlight the selected panel", ChangeCallback_RefreshDrawTree );
  35. static ConVar vgui_drawtree_scheme( "vgui_drawtree_scheme", "0", 0, "Show scheme file for each panel", ChangeCallback_RefreshDrawTree );
  36. extern ConVar vgui_drawfocus;
  37. void vgui_drawtree_on_f()
  38. {
  39. vgui_drawtree.SetValue( 1 );
  40. }
  41. void vgui_drawtree_off_f()
  42. {
  43. vgui_drawtree.SetValue( 0 );
  44. }
  45. ConCommand vgui_drawtree_on( "+vgui_drawtree", vgui_drawtree_on_f );
  46. ConCommand vgui_drawtree_off( "-vgui_drawtree", vgui_drawtree_off_f );
  47. extern CUtlVector< VPANEL > g_FocusPanelList;
  48. extern VPanelHandle g_DrawTreeSelectedPanel;
  49. class CVGuiTree : public TreeView
  50. {
  51. public:
  52. typedef TreeView BaseClass;
  53. CVGuiTree( Panel *parent, const char *pName ) :
  54. BaseClass( parent, pName )
  55. {
  56. }
  57. virtual void ApplySchemeSettings( IScheme *pScheme )
  58. {
  59. BaseClass::ApplySchemeSettings( pScheme );
  60. SetFont( pScheme->GetFont( "ConsoleText", false ) );
  61. //SetBgColor( Color( 0, 0, 0, 175 ) );
  62. SetPaintBackgroundEnabled( false );
  63. }
  64. };
  65. class CDrawTreeFrame : public Frame
  66. {
  67. public:
  68. DECLARE_CLASS_SIMPLE( CDrawTreeFrame, Frame );
  69. CDrawTreeFrame( Panel *parent, const char *pName ) :
  70. BaseClass( parent, pName )
  71. {
  72. // Init the frame.
  73. SetTitle( "VGUI Hierarchy", false );
  74. SetMenuButtonVisible( false );
  75. // Create the tree control itself.
  76. m_pTree = SETUP_PANEL( new CVGuiTree( this, "Tree view" ) );
  77. m_pTree->SetVisible( true );
  78. // Init the buttons.
  79. m_pShowVisible = SETUP_PANEL( new CConVarCheckButton( this, "show visible", "Show Visible" ) );
  80. m_pShowVisible->SetVisible( true );
  81. m_pShowVisible->SetConVar( &vgui_drawtree_visible );
  82. m_pShowHidden = SETUP_PANEL( new CConVarCheckButton( this, "show hidden", "Show Hidden" ) );
  83. m_pShowHidden->SetVisible( true );
  84. m_pShowHidden->SetConVar( &vgui_drawtree_hidden );
  85. m_pPopupsOnly = SETUP_PANEL( new CConVarCheckButton( this, "popups only", "Popups Only" ) );
  86. m_pPopupsOnly->SetVisible( true );
  87. m_pPopupsOnly->SetConVar( &vgui_drawtree_popupsonly );
  88. m_pDrawFocus = SETUP_PANEL( new CConVarCheckButton( this, "draw focus", "Highlight MouseOver" ) );
  89. m_pDrawFocus->SetVisible( true );
  90. m_pDrawFocus->SetConVar( &vgui_drawfocus );
  91. m_pFreeze = SETUP_PANEL( new CConVarCheckButton( this, "freeze option", "Freeze" ) );
  92. m_pFreeze->SetVisible( true );
  93. m_pFreeze->SetConVar( &vgui_drawtree_freeze );
  94. m_pShowPanelPtr = SETUP_PANEL( new CConVarCheckButton( this, "panel ptr option", "Show Addresses" ) );
  95. m_pShowPanelPtr->SetVisible( true );
  96. m_pShowPanelPtr->SetConVar( &vgui_drawtree_panelptr );
  97. m_pShowPanelAlpha = SETUP_PANEL( new CConVarCheckButton( this, "panel alpha option", "Show Alpha" ) );
  98. m_pShowPanelAlpha->SetVisible( true );
  99. m_pShowPanelAlpha->SetConVar( &vgui_drawtree_panelalpha );
  100. m_pRenderOrder = SETUP_PANEL( new CConVarCheckButton( this, "render order option", "In Render Order" ) );
  101. m_pRenderOrder->SetVisible( true );
  102. m_pRenderOrder->SetConVar( &vgui_drawtree_render_order );
  103. m_pShowBounds = SETUP_PANEL( new CConVarCheckButton( this, "show panel bounds", "Show Panel Bounds" ) );
  104. m_pShowBounds->SetVisible( true );
  105. m_pShowBounds->SetConVar( &vgui_drawtree_bounds );
  106. m_pHighlightSelected = SETUP_PANEL( new CConVarCheckButton( this, "highlight selected", "Highlight Selected" ) );
  107. m_pHighlightSelected->SetVisible( true );
  108. m_pHighlightSelected->SetConVar( &vgui_drawtree_draw_selected );
  109. m_pShowScheme = SETUP_PANEL( new CConVarCheckButton( this, "show scheme", "Show Scheme" ) );
  110. m_pShowScheme->SetVisible( true );
  111. m_pShowScheme->SetConVar( &vgui_drawtree_scheme );
  112. int r,g,b,a;
  113. GetBgColor().GetColor( r, g, b, a );
  114. a = 128;
  115. SetBgColor( Color( r, g, b, a ) );
  116. }
  117. virtual void PerformLayout()
  118. {
  119. BaseClass::PerformLayout();
  120. int x, y, w, t;
  121. GetClientArea( x, y, w, t );
  122. int yOffset = y;
  123. // Align the check boxes.
  124. m_pShowVisible->SetPos( x, yOffset );
  125. m_pShowVisible->SetWide( w/2 );
  126. yOffset += m_pShowVisible->GetTall();
  127. m_pShowHidden->SetPos( x, yOffset );
  128. m_pShowHidden->SetWide( w/2 );
  129. yOffset += m_pShowHidden->GetTall();
  130. m_pPopupsOnly->SetPos( x, yOffset );
  131. m_pPopupsOnly->SetWide( w/2 );
  132. yOffset += m_pPopupsOnly->GetTall();
  133. m_pDrawFocus->SetPos( x, yOffset );
  134. m_pDrawFocus->SetWide( w/2 );
  135. yOffset += m_pDrawFocus->GetTall();
  136. m_pShowBounds->SetPos( x, yOffset );
  137. m_pShowBounds->SetWide( w/2 );
  138. yOffset += m_pShowBounds->GetTall();
  139. m_pShowScheme->SetPos( x, yOffset );
  140. m_pShowScheme->SetWide( w/2 );
  141. yOffset += m_pShowScheme->GetTall();
  142. m_pTree->SetBounds( x, yOffset, w, t - (yOffset - y) );
  143. // Next column..
  144. yOffset = y;
  145. m_pFreeze->SetPos( x + w/2, yOffset );
  146. m_pFreeze->SetWide( w/2 );
  147. yOffset += m_pFreeze->GetTall();
  148. m_pShowPanelPtr->SetPos( x + w/2, yOffset );
  149. m_pShowPanelPtr->SetWide( w/2 );
  150. yOffset += m_pShowPanelPtr->GetTall();
  151. m_pShowPanelAlpha->SetPos( x + w/2, yOffset );
  152. m_pShowPanelAlpha->SetWide( w/2 );
  153. yOffset += m_pShowPanelAlpha->GetTall();
  154. m_pRenderOrder->SetPos( x + w/2, yOffset );
  155. m_pRenderOrder->SetWide( w/2 );
  156. yOffset += m_pRenderOrder->GetTall();
  157. m_pHighlightSelected->SetPos( x + w/2, yOffset );
  158. m_pHighlightSelected->SetWide( w/2 );
  159. yOffset += m_pHighlightSelected->GetTall();
  160. }
  161. MESSAGE_FUNC( OnItemSelected, "TreeViewItemSelected" )
  162. {
  163. RecalculateSelectedHighlight();
  164. }
  165. void RecalculateSelectedHighlight( void )
  166. {
  167. Assert( m_pTree );
  168. if ( !vgui_drawtree_draw_selected.GetBool() || m_pTree->GetSelectedItemCount() != 1 )
  169. {
  170. // clear the selection
  171. g_DrawTreeSelectedPanel = 0;
  172. }
  173. else
  174. {
  175. CUtlVector< int > list;
  176. m_pTree->GetSelectedItems( list );
  177. Assert( list.Count() == 1 );
  178. KeyValues *data = m_pTree->GetItemData( list.Element(0) );
  179. if ( data )
  180. {
  181. g_DrawTreeSelectedPanel = (data) ? (VPANEL)data->GetInt( "PanelPtr", 0 ) : 0;
  182. }
  183. else
  184. {
  185. g_DrawTreeSelectedPanel = 0;
  186. }
  187. }
  188. }
  189. virtual void OnClose()
  190. {
  191. vgui_drawtree.SetValue( 0 );
  192. g_DrawTreeSelectedPanel = 0;
  193. // fixme - g_DrawTreeSelectedPanel has a potential crash if you hilight a panel, and then spam hud_reloadscheme
  194. // you will sometimes end up on a different panel or on garbage.
  195. }
  196. public:
  197. CVGuiTree *m_pTree;
  198. CConVarCheckButton *m_pShowVisible;
  199. CConVarCheckButton *m_pShowHidden;
  200. CConVarCheckButton *m_pPopupsOnly;
  201. CConVarCheckButton *m_pFreeze;
  202. CConVarCheckButton *m_pShowPanelPtr;
  203. CConVarCheckButton *m_pShowPanelAlpha;
  204. CConVarCheckButton *m_pRenderOrder;
  205. CConVarCheckButton *m_pDrawFocus;
  206. CConVarCheckButton *m_pShowBounds;
  207. CConVarCheckButton *m_pHighlightSelected;
  208. CConVarCheckButton *m_pShowScheme;
  209. };
  210. CDrawTreeFrame *g_pDrawTreeFrame = 0;
  211. void VGui_RecursivePrintTree(
  212. VPANEL current,
  213. KeyValues *pCurrentParent,
  214. int popupDepthCounter )
  215. {
  216. if ( !current )
  217. return;
  218. IPanel *ipanel = vgui::ipanel();
  219. if ( !vgui_drawtree_visible.GetInt() && ipanel->IsVisible( current ) )
  220. return;
  221. else if ( !vgui_drawtree_hidden.GetInt() && !ipanel->IsVisible( current ) )
  222. return;
  223. else if ( popupDepthCounter <= 0 && ipanel->IsPopup( current ) )
  224. return;
  225. KeyValues *pNewParent = pCurrentParent;
  226. KeyValues *pVal = pCurrentParent->CreateNewKey();
  227. // Bind data to pVal.
  228. CUtlString name;
  229. const char *pInputName = ipanel->GetName( current );
  230. name = ( pInputName && *pInputName ) ? pInputName : "(no name)";
  231. if ( ipanel->IsMouseInputEnabled( current ) )
  232. {
  233. name += ", +m";
  234. }
  235. if ( ipanel->IsKeyBoardInputEnabled( current ) )
  236. {
  237. name += ", +k";
  238. }
  239. int dtb = vgui_drawtree_bounds.GetInt();
  240. if ( dtb > 0 )
  241. {
  242. name += ", ";
  243. int x, y, w, h;
  244. ipanel->GetSize( current, w, h );
  245. if ( dtb == 1 )
  246. {
  247. ipanel->GetPos( current, x, y );
  248. name += CFmtStr( "[%-4i %-4i %-4i %-4i]", x, y, w, h );
  249. }
  250. else
  251. {
  252. ipanel->GetAbsPos( current, x, y );
  253. name += CFmtStr( "abs [%d][%-4i %-4i %-4i %-4i]", ipanel->GetMessageContextId( current ), x, y, w, h );
  254. }
  255. }
  256. if ( vgui_drawtree_panelptr.GetBool() )
  257. {
  258. name += CFmtStr( " - [0x%x]", current );
  259. }
  260. if (vgui_drawtree_panelalpha.GetBool() )
  261. {
  262. KeyValues *kv = new KeyValues("alpha");
  263. ipanel->RequestInfo( current, kv );
  264. name += CFmtStr( " - [%d]", kv->GetInt("alpha") );
  265. kv->deleteThis();
  266. }
  267. if ( vgui_drawtree_scheme.GetBool() )
  268. {
  269. HScheme hScheme = ipanel->GetScheme( current );
  270. if ( hScheme )
  271. {
  272. IScheme *pScheme = scheme()->GetIScheme( hScheme );
  273. if ( pScheme )
  274. {
  275. name += CFmtStr( " [%s - %s]", pScheme->GetName(), pScheme->GetFileName() );
  276. }
  277. }
  278. }
  279. pVal->SetString( "Text", name.String() );
  280. pVal->SetInt( "PanelPtr", current );
  281. pNewParent = pVal;
  282. // Don't recurse past the tree itself because the tree control uses a panel for each
  283. // panel inside itself, and it'll infinitely create panels.
  284. if ( current == g_pDrawTreeFrame->m_pTree->GetVPanel() )
  285. return;
  286. int count = ipanel->GetChildCount( current );
  287. for ( int i = 0; i < count ; i++ )
  288. {
  289. VPANEL panel = ipanel->GetChild( current, i );
  290. VGui_RecursivePrintTree( panel, pNewParent, popupDepthCounter-1 );
  291. }
  292. }
  293. bool UpdateItemState(
  294. TreeView *pTree,
  295. int iChildItemId,
  296. KeyValues *pSub )
  297. {
  298. bool bRet = false;
  299. IPanel *ipanel = vgui::ipanel();
  300. KeyValues *pItemData = pTree->GetItemData( iChildItemId );
  301. if ( pItemData->GetInt( "PanelPtr" ) != pSub->GetInt( "PanelPtr" ) ||
  302. Q_stricmp( pItemData->GetString( "Text" ), pSub->GetString( "Text" ) ) != 0 )
  303. {
  304. pTree->ModifyItem( iChildItemId, pSub );
  305. bRet = true;
  306. }
  307. // Ok, this is a new panel.
  308. VPANEL vPanel = pSub->GetInt( "PanelPtr" );
  309. int iBaseColor[3] = { 255, 255, 255 };
  310. if ( ipanel->IsPopup( vPanel ) )
  311. {
  312. iBaseColor[0] = 255; iBaseColor[1] = 255; iBaseColor[2] = 0;
  313. }
  314. if ( g_FocusPanelList.Find( vPanel ) != -1 )
  315. {
  316. iBaseColor[0] = 0; iBaseColor[1] = 255; iBaseColor[2] = 0;
  317. pTree->ExpandItem( iChildItemId, true );
  318. }
  319. if ( !ipanel->IsVisible( vPanel ) )
  320. {
  321. iBaseColor[0] >>= 1; iBaseColor[1] >>= 1; iBaseColor[2] >>= 1;
  322. }
  323. pTree->SetItemFgColor( iChildItemId, Color( iBaseColor[0], iBaseColor[1], iBaseColor[2], 255 ) );
  324. return bRet;
  325. }
  326. void IncrementalUpdateTree(
  327. TreeView *pTree,
  328. KeyValues *pValues )
  329. {
  330. if ( !g_bForceRefresh && vgui_drawtree_freeze.GetInt() )
  331. return;
  332. g_bForceRefresh = false;
  333. bool bInvalidateLayout = IncrementalUpdateTree( pTree, pValues, UpdateItemState, -1 );
  334. pTree->ExpandItem( pTree->GetRootItemIndex(), true );
  335. if ( g_pDrawTreeFrame )
  336. g_pDrawTreeFrame->RecalculateSelectedHighlight();
  337. if ( bInvalidateLayout )
  338. pTree->InvalidateLayout();
  339. }
  340. bool WillPanelBeVisible( VPANEL hPanel )
  341. {
  342. while ( hPanel )
  343. {
  344. if ( !vgui::ipanel()->IsVisible( hPanel ) )
  345. return false;
  346. hPanel = vgui::ipanel()->GetParent( hPanel );
  347. }
  348. return true;
  349. }
  350. void VGui_AddPopupsToKeyValues( KeyValues *pCurrentParent )
  351. {
  352. // 'twould be nice if we could get the Panel* from the VPANEL, but we can't.
  353. int count = surface()->GetPopupCount();
  354. for ( int i=0; i < count; i++ )
  355. {
  356. VPANEL vPopup = surface()->GetPopup( i );
  357. if ( vgui_drawtree_hidden.GetInt() || WillPanelBeVisible( vPopup ) )
  358. {
  359. VGui_RecursivePrintTree(
  360. vPopup,
  361. pCurrentParent,
  362. 1 );
  363. }
  364. }
  365. }
  366. void VGui_FillKeyValues( KeyValues *pCurrentParent )
  367. {
  368. if ( !EngineVGui()->IsInitialized() )
  369. return;
  370. // Figure out the root panel to start at.
  371. // If they specified a name for a root panel, then use that one.
  372. VPANEL hBase = surface()->GetEmbeddedPanel();
  373. if ( vgui_drawtree_popupsonly.GetInt() )
  374. {
  375. VGui_AddPopupsToKeyValues( pCurrentParent );
  376. }
  377. else if ( vgui_drawtree_render_order.GetInt() )
  378. {
  379. VGui_RecursivePrintTree(
  380. hBase,
  381. pCurrentParent,
  382. 0 );
  383. VGui_AddPopupsToKeyValues( pCurrentParent );
  384. }
  385. else
  386. {
  387. VGui_RecursivePrintTree(
  388. hBase,
  389. pCurrentParent,
  390. 99999 );
  391. }
  392. }
  393. void VGui_DrawHierarchy( void )
  394. {
  395. VPROF( "VGui_DrawHierarchy" );
  396. if ( IsGameConsole() )
  397. return;
  398. if ( vgui_drawtree.GetInt() <= 0 )
  399. {
  400. g_pDrawTreeFrame->SetVisible( false );
  401. return;
  402. }
  403. g_pDrawTreeFrame->SetVisible( true );
  404. // Now reconstruct the tree control.
  405. KeyValues *pRoot = new KeyValues("");
  406. pRoot->SetString( "Text", "<shouldn't see this>" );
  407. VGui_FillKeyValues( pRoot );
  408. // Now incrementally update the tree control so we can preserve which nodes are open.
  409. IncrementalUpdateTree( g_pDrawTreeFrame->m_pTree, pRoot );
  410. // Delete the keyvalues.
  411. pRoot->deleteThis();
  412. }
  413. void VGui_CreateDrawTreePanel( Panel *parent )
  414. {
  415. int widths = 300;
  416. g_pDrawTreeFrame = SETUP_PANEL( new CDrawTreeFrame( parent, "DrawTreeFrame" ) );
  417. g_pDrawTreeFrame->SetVisible( false );
  418. g_pDrawTreeFrame->SetBounds( parent->GetWide() - widths, 0, widths, parent->GetTall() - 10 );
  419. g_pDrawTreeFrame->MakePopup( false, false );
  420. g_pDrawTreeFrame->SetKeyBoardInputEnabled( true );
  421. g_pDrawTreeFrame->SetMouseInputEnabled( true );
  422. }
  423. void VGui_MoveDrawTreePanelToFront()
  424. {
  425. if ( g_pDrawTreeFrame )
  426. g_pDrawTreeFrame->MoveToFront();
  427. }
  428. void VGui_UpdateDrawTreePanel()
  429. {
  430. VGui_DrawHierarchy();
  431. }
  432. void vgui_drawtree_clear_f()
  433. {
  434. if ( g_pDrawTreeFrame && g_pDrawTreeFrame->m_pTree )
  435. g_pDrawTreeFrame->m_pTree->RemoveAll();
  436. }
  437. ConCommand vgui_drawtree_clear( "vgui_drawtree_clear", vgui_drawtree_clear_f );