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.

3380 lines
94 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "client_pch.h"
  7. #include "ivideomode.h"
  8. #include "client_class.h"
  9. #include "icliententitylist.h"
  10. #include "vgui_basepanel.h"
  11. #include <vgui_controls/Controls.h>
  12. #include <vgui/ISurface.h>
  13. #include <vgui/IScheme.h>
  14. #include <vgui/IVGui.h>
  15. #include <vgui_controls/Frame.h>
  16. #include <vgui_controls/TreeView.h>
  17. #include <vgui_controls/ListPanel.h>
  18. #include <vgui_controls/ListViewPanel.h>
  19. #include <vgui_controls/TreeViewListControl.h>
  20. #include <vgui/ISystem.h>
  21. #include "tier0/vprof.h"
  22. #include "KeyValues.h"
  23. #include "vgui_helpers.h"
  24. #include "utlsymbol.h"
  25. #include "tier1/UtlStringMap.h"
  26. #include "bitvec.h"
  27. #include "utldict.h"
  28. #include "vgui/ILocalize.h"
  29. #include "con_nprint.h"
  30. #include "gl_matsysiface.h"
  31. #include "VGuiMatSurface/IMatSystemSurface.h"
  32. #include "materialsystem/imaterial.h"
  33. #include "materialsystem/imaterialvar.h"
  34. #include "materialsystem/imesh.h"
  35. #include "materialsystem/idebugtextureinfo.h"
  36. #include "materialsystem/itexture.h"
  37. #include "vtf/vtf.h"
  38. #include "tier2/tier2.h"
  39. #include "smartptr.h"
  40. #include "igame.h"
  41. #include "client.h"
  42. #include "tier2/p4helpers.h"
  43. #include "p4lib/ip4.h"
  44. #include "ivtex.h"
  45. #include "tier2/fileutils.h"
  46. // For character manipulations isupper/tolower
  47. #include <ctype.h>
  48. // memdbgon must be the last include file in a .cpp file!!!
  49. #include "tier0/memdbgon.h"
  50. #define KEYNAME_NAME "Name"
  51. #define KEYNAME_PATH "Path"
  52. #define KEYNAME_BINDS_MAX "BindsMax"
  53. #define KEYNAME_BINDS_FRAME "BindsFrame"
  54. #define KEYNAME_SIZE "Size"
  55. #define KEYNAME_FORMAT "Format"
  56. #define KEYNAME_WIDTH "Width"
  57. #define KEYNAME_HEIGHT "Height"
  58. #define KEYNAME_TEXTURE_GROUP "TexGroup"
  59. #define COPYTOCLIPBOARD_CMDNAME "CopyToClipboard"
  60. #if defined( _X360 )
  61. CON_COMMAND( mat_get_textures, "VXConsole command" )
  62. {
  63. g_pMaterialSystemDebugTextureInfo->EnableDebugTextureList( true );
  64. g_pMaterialSystemDebugTextureInfo->EnableGetAllTextures( args.ArgC() >= 2 && ( Q_stricmp( args[1], "all" ) == 0 ) );
  65. }
  66. #endif
  67. static ConVar mat_texture_list( "mat_texture_list", "0", FCVAR_CHEAT, "For debugging, show a list of used textures per frame" );
  68. static enum TxListPanelRequest
  69. {
  70. TXR_NONE,
  71. TXR_SHOW,
  72. TXR_RUNNING,
  73. TXR_HIDE
  74. } s_eTxListPanelRequest = TXR_NONE;
  75. IVTex* VTex_Load( CSysModule** pModule );
  76. void VTex_Unload( CSysModule *pModule );
  77. void* CubemapsFSFactory( const char *pName, int *pReturnCode );
  78. bool StripDirName( char *pFilename );
  79. // These are here so you can bind a key to +mat_texture_list and toggle it on and off.
  80. void mat_texture_list_on_f();
  81. void mat_texture_list_off_f();
  82. ConCommand mat_texture_list_on( "+mat_texture_list", mat_texture_list_on_f );
  83. ConCommand mat_texture_list_off( "-mat_texture_list", mat_texture_list_off_f );
  84. ConVar mat_texture_list_all( "mat_texture_list_all", "0", FCVAR_NEVER_AS_STRING|FCVAR_CHEAT, "If this is nonzero, then the texture list panel will show all currently-loaded textures." );
  85. ConVar mat_texture_list_view( "mat_texture_list_view", "1", FCVAR_NEVER_AS_STRING|FCVAR_CHEAT, "If this is nonzero, then the texture list panel will render thumbnails of currently-loaded textures." );
  86. ConVar mat_show_texture_memory_usage( "mat_show_texture_memory_usage", "0", FCVAR_NEVER_AS_STRING|FCVAR_CHEAT, "Display the texture memory usage on the HUD." );
  87. static int g_warn_texkbytes = 1499;
  88. static int g_warn_texdimensions = 1024;
  89. static bool g_warn_enable = true;
  90. static bool g_cursorset = false;
  91. class CTextureListPanel;
  92. static CTextureListPanel *g_pTextureListPanel = NULL;
  93. static bool g_bRecursiveRequestToShowTextureList = false;
  94. static int g_nSaveQueueState = INT_MIN;
  95. //
  96. // A class to mimic a list view
  97. //
  98. namespace vgui
  99. {
  100. class TileViewPanelEx : public Panel
  101. {
  102. DECLARE_CLASS_SIMPLE( TileViewPanelEx, Panel );
  103. public:
  104. TileViewPanelEx( Panel *parent, const char *panelName );
  105. ~TileViewPanelEx();
  106. public:
  107. virtual void SetFont( HFont hFont );
  108. virtual HFont GetFont();
  109. public:
  110. enum HitTest_t
  111. {
  112. HT_NOTHING = 0,
  113. HT_TILE
  114. };
  115. virtual int HitTest( int x, int y, int &iTile );
  116. virtual bool GetTileOrg( int iTile, int &x, int &y );
  117. protected: // Overrides for contents
  118. virtual int GetNumTiles() = 0;
  119. virtual void GetTileSize( int &wide, int &tall ) = 0;
  120. virtual void RenderTile( int iTile, int x, int y ) = 0;
  121. protected:
  122. // Handlers
  123. virtual void OnMouseWheeled( int delta );
  124. virtual void OnSizeChanged( int wide, int tall );
  125. virtual void PerformLayout();
  126. virtual void Paint();
  127. virtual void ApplySchemeSettings( IScheme *pScheme );
  128. MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" );
  129. protected:
  130. virtual bool ComputeLayoutInfo();
  131. int m_li_numTiles; //!< Total number of tiles
  132. int m_li_numVisibleTiles; //!< Number of tiles fitting in the client area
  133. int m_li_wide, m_li_tall; //!< Tile area width/height
  134. int m_li_wideItem, m_li_tallItem; //!< Every item width/height
  135. int m_li_colVisible, m_li_rowVisible; //!< Num columns/rows fitting in the client area
  136. int m_li_rowNeeded; //!< Num rows required to fit all numTiles
  137. int m_li_startTile, m_li_endTile; //!< Start/end tile that are rendered in the client area
  138. private:
  139. ScrollBar *m_hbar;
  140. HFont m_hFont;
  141. };
  142. //
  143. // Implementation details
  144. //
  145. TileViewPanelEx::TileViewPanelEx( Panel *parent, const char *panelName ) :
  146. Panel( parent, panelName ),
  147. m_hbar( NULL ),
  148. m_hFont( INVALID_FONT )
  149. {
  150. m_hbar = new ScrollBar( this, "VerticalScrollBar", true );
  151. m_hbar->AddActionSignalTarget( this );
  152. m_hbar->SetVisible( true );
  153. }
  154. TileViewPanelEx::~TileViewPanelEx()
  155. {
  156. delete m_hbar;
  157. }
  158. void TileViewPanelEx::SetFont( HFont hFont )
  159. {
  160. m_hFont = hFont;
  161. Repaint();
  162. }
  163. HFont TileViewPanelEx::GetFont()
  164. {
  165. return m_hFont;
  166. }
  167. int TileViewPanelEx::HitTest( int x, int y, int &iTile )
  168. {
  169. iTile = -1;
  170. if ( !ComputeLayoutInfo() )
  171. return HT_NOTHING;
  172. int hitCol = ( x / m_li_wideItem );
  173. int hitRow = ( y / m_li_tallItem );
  174. if ( hitCol >= m_li_colVisible )
  175. return HT_NOTHING;
  176. if ( hitRow > m_li_rowVisible )
  177. return HT_NOTHING;
  178. int hitTile = m_li_startTile + hitCol + hitRow * m_li_colVisible;
  179. if ( hitTile >= m_li_endTile )
  180. return HT_NOTHING;
  181. // Hit tile
  182. iTile = hitTile;
  183. return HT_TILE;
  184. }
  185. bool TileViewPanelEx::GetTileOrg( int iTile, int &x, int &y )
  186. {
  187. if ( m_li_colVisible <= 0 )
  188. return false;
  189. if ( iTile < m_li_startTile || iTile >= m_li_endTile )
  190. return false;
  191. x = 0 + ( ( iTile - m_li_startTile ) % m_li_colVisible ) * m_li_wideItem;
  192. y = 0 + ( ( iTile - m_li_startTile ) / m_li_colVisible ) * m_li_tallItem;
  193. return true;
  194. }
  195. void TileViewPanelEx::OnMouseWheeled( int delta )
  196. {
  197. if ( m_hbar->IsVisible() )
  198. {
  199. int val = m_hbar->GetValue();
  200. val -= delta;
  201. m_hbar->SetValue( val );
  202. }
  203. }
  204. void TileViewPanelEx::OnSizeChanged( int wide, int tall )
  205. {
  206. BaseClass::OnSizeChanged( wide, tall );
  207. InvalidateLayout();
  208. Repaint();
  209. }
  210. void TileViewPanelEx::PerformLayout()
  211. {
  212. int numTiles = GetNumTiles();
  213. m_hbar->SetVisible( false );
  214. int wide, tall;
  215. GetSize( wide, tall );
  216. wide -= m_hbar->GetWide();
  217. m_hbar->SetPos( wide - 2, 0 );
  218. m_hbar->SetTall( tall );
  219. if ( !numTiles )
  220. return;
  221. int wideItem = 1, tallItem = 1;
  222. GetTileSize( wideItem, tallItem );
  223. if ( !wideItem || !tallItem )
  224. return;
  225. int colVisible = wide / wideItem;
  226. int rowVisible = tall / tallItem;
  227. if ( rowVisible <= 0 || colVisible <= 0 )
  228. return;
  229. int rowNeeded = ( numTiles + colVisible - 1 ) / colVisible;
  230. int startTile = 0;
  231. if ( rowNeeded > rowVisible )
  232. {
  233. m_hbar->SetRange( 0, rowNeeded );
  234. m_hbar->SetRangeWindow( rowVisible );
  235. m_hbar->SetButtonPressedScrollValue( 1 );
  236. m_hbar->SetVisible( true );
  237. m_hbar->InvalidateLayout();
  238. int val = m_hbar->GetValue();
  239. startTile = val * colVisible;
  240. }
  241. }
  242. bool TileViewPanelEx::ComputeLayoutInfo()
  243. {
  244. m_li_numTiles = GetNumTiles();
  245. if ( !m_li_numTiles )
  246. return false;
  247. GetSize( m_li_wide, m_li_tall );
  248. m_li_wide -= m_hbar->GetWide();
  249. m_li_wideItem = 1, m_li_tallItem = 1;
  250. GetTileSize( m_li_wideItem, m_li_tallItem );
  251. if ( !m_li_wideItem || !m_li_tallItem )
  252. return false;
  253. m_li_colVisible = m_li_wide / m_li_wideItem;
  254. m_li_rowVisible = m_li_tall / m_li_tallItem;
  255. if ( m_li_rowVisible <= 0 || m_li_colVisible <= 0 )
  256. return false;
  257. m_li_rowNeeded = ( m_li_numTiles + m_li_colVisible - 1 ) / m_li_colVisible;
  258. m_li_numVisibleTiles = m_li_colVisible * m_li_rowVisible;
  259. m_li_startTile = 0;
  260. if ( m_li_rowNeeded > m_li_rowVisible )
  261. {
  262. int val = m_hbar->GetValue();
  263. m_li_startTile = val * m_li_colVisible;
  264. }
  265. if ( m_li_startTile >= m_li_numTiles )
  266. m_li_startTile = m_li_numTiles - m_li_numVisibleTiles;
  267. if ( m_li_startTile < 0 )
  268. m_li_startTile = 0;
  269. m_li_endTile = m_li_startTile + m_li_numVisibleTiles + m_li_colVisible; // draw the partly visible items
  270. if ( m_li_endTile > m_li_numTiles )
  271. m_li_endTile = m_li_numTiles;
  272. return true;
  273. }
  274. void TileViewPanelEx::Paint()
  275. {
  276. BaseClass::Paint();
  277. // Now render all our tiles
  278. if ( !ComputeLayoutInfo() )
  279. return;
  280. for ( int iRenderTile = m_li_startTile; iRenderTile < m_li_endTile; ++ iRenderTile )
  281. {
  282. int x = 0 + ( ( iRenderTile - m_li_startTile ) % m_li_colVisible ) * m_li_wideItem;
  283. int y = 0 + ( ( iRenderTile - m_li_startTile ) / m_li_colVisible ) * m_li_tallItem;
  284. RenderTile( iRenderTile, x, y );
  285. }
  286. }
  287. void TileViewPanelEx::ApplySchemeSettings( IScheme *pScheme )
  288. {
  289. BaseClass::ApplySchemeSettings( pScheme );
  290. SetBgColor( GetSchemeColor( "ListPanel.BgColor", pScheme ) );
  291. SetBorder( pScheme->GetBorder("ButtonDepressedBorder" ) );
  292. SetFont( pScheme->GetFont( "Default", IsProportional() ) );
  293. }
  294. void TileViewPanelEx::OnSliderMoved()
  295. {
  296. InvalidateLayout();
  297. Repaint();
  298. }
  299. }; // namespace vgui
  300. //////////////////////////////////////////////////////////////////////////
  301. //
  302. // Material access
  303. //
  304. //////////////////////////////////////////////////////////////////////////
  305. class CAutoMatSysDebugMode
  306. {
  307. public:
  308. CAutoMatSysDebugMode();
  309. ~CAutoMatSysDebugMode();
  310. void ScheduleCleanupTextureVar( IMaterialVar *pVar );
  311. protected:
  312. bool bOldDebugMode;
  313. CUtlRBTree< IMaterialVar * > arrCleanupVars;
  314. };
  315. CAutoMatSysDebugMode::CAutoMatSysDebugMode() :
  316. arrCleanupVars( DefLessFunc(IMaterialVar *) )
  317. {
  318. g_pMaterialSystem->Flush();
  319. bOldDebugMode = g_pMaterialSystemDebugTextureInfo->SetDebugTextureRendering( true );
  320. }
  321. CAutoMatSysDebugMode::~CAutoMatSysDebugMode()
  322. {
  323. g_pMaterialSystem->Flush();
  324. g_pMaterialSystemDebugTextureInfo->SetDebugTextureRendering( bOldDebugMode );
  325. for ( uint32 k = 0; k < arrCleanupVars.Count(); ++ k )
  326. {
  327. IMaterialVar *pVar = arrCleanupVars.Element( k );
  328. pVar->SetUndefined();
  329. }
  330. }
  331. void CAutoMatSysDebugMode::ScheduleCleanupTextureVar( IMaterialVar *pVar )
  332. {
  333. if ( !pVar )
  334. return;
  335. arrCleanupVars.InsertIfNotFound( pVar );
  336. }
  337. static IMaterial * UseDebugMaterial( char const *szMaterial, ITexture *pMatTexture, CAutoMatSysDebugMode *pRestoreVars )
  338. {
  339. if ( !szMaterial || !pMatTexture )
  340. return NULL;
  341. bool foundVar;
  342. IMaterial *pMaterial = materials->FindMaterial( szMaterial, TEXTURE_GROUP_OTHER, false );
  343. // IMaterial *pMaterial = materials->FindMaterial( "debug/debugempty", TEXTURE_GROUP_OTHER, false );
  344. if ( !pMaterial )
  345. return NULL;
  346. IMaterialVar *BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false );
  347. // IMaterialVar *BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false );
  348. if ( !foundVar || !BaseTextureVar )
  349. return NULL;
  350. IMaterialVar *FrameVar = pMaterial->FindVar( "$frame", &foundVar, false );
  351. if ( foundVar && FrameVar )
  352. {
  353. int numAnimFrames = pMatTexture->GetNumAnimationFrames();
  354. if ( pMatTexture->IsRenderTarget() || pMatTexture->IsProcedural() )
  355. numAnimFrames = 0; // Cannot use the stencil parts of the render targets and shouldn't use the other frames of procedural textures
  356. FrameVar->SetIntValue( ( numAnimFrames > 0 ) ? ( g_ClientGlobalVariables.tickcount % numAnimFrames ) : 0 );
  357. }
  358. BaseTextureVar->SetTextureValue( pMatTexture );
  359. if ( pRestoreVars )
  360. {
  361. pRestoreVars->ScheduleCleanupTextureVar( BaseTextureVar );
  362. }
  363. return pMaterial;
  364. }
  365. static void RenderTexturedRect( vgui::Panel *pPanel, IMaterial *pMaterial, int x, int y, int x1, int y1, int xoff = 0, int yoff = 0 )
  366. {
  367. CAutoMatSysDebugMode auto_matsysdebugmode;
  368. int tall = pPanel->GetTall();
  369. float fHeightUV = 1.0f;
  370. if ( y1 > tall )
  371. {
  372. fHeightUV = float( tall - y ) / float( y1 - y );
  373. y1 = tall;
  374. }
  375. if ( y1 <= y )
  376. return;
  377. pPanel->LocalToScreen( x, y );
  378. pPanel->LocalToScreen( x1, y1 );
  379. x += xoff; x1 += xoff; y += yoff; y1 += yoff;
  380. CMatRenderContextPtr pRenderContext( materials );
  381. pRenderContext->Bind( pMaterial );
  382. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  383. CMeshBuilder meshBuilder;
  384. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  385. meshBuilder.Position3f( x, y, 0.0f );
  386. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  387. meshBuilder.AdvanceVertex();
  388. meshBuilder.Position3f( x1, y, 0.0f );
  389. meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
  390. meshBuilder.AdvanceVertex();
  391. meshBuilder.Position3f( x1, y1, 0.0f );
  392. meshBuilder.TexCoord2f( 0, 1.0f, fHeightUV );
  393. meshBuilder.AdvanceVertex();
  394. meshBuilder.Position3f( x, y1, 0.0f );
  395. meshBuilder.TexCoord2f( 0, 0.0f, fHeightUV );
  396. meshBuilder.AdvanceVertex();
  397. meshBuilder.End();
  398. pMesh->Draw();
  399. }
  400. static bool ShallWarnTx( KeyValues *kv, ITexture *tx )
  401. {
  402. if ( !tx )
  403. {
  404. return false;
  405. }
  406. if ( tx->GetFlags() & ( TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_ONEBITALPHA ) )
  407. return true;
  408. if ( stricmp( "DXT1", kv->GetString( KEYNAME_FORMAT ) ) && stricmp( "DXT5", kv->GetString( KEYNAME_FORMAT ) ) &&
  409. stricmp( "ATI1N", kv->GetString( KEYNAME_FORMAT ) ) && stricmp( "ATI2N", kv->GetString( KEYNAME_FORMAT ) ) &&
  410. stricmp( "DXT5_RUNTIME", kv->GetString( KEYNAME_FORMAT ) ) )
  411. return true;
  412. if ( kv->GetInt( KEYNAME_SIZE ) > g_warn_texkbytes )
  413. return true;
  414. if ( kv->GetInt( KEYNAME_WIDTH ) > g_warn_texdimensions )
  415. return true;
  416. if ( kv->GetInt( KEYNAME_HEIGHT ) > g_warn_texdimensions )
  417. return true;
  418. return false;
  419. }
  420. static void FmtCommaNumber( char *pchBuffer, unsigned int uiNumber )
  421. {
  422. pchBuffer[0] = 0;
  423. for ( unsigned int uiDivisor = 1000 * 1000 * 1000; uiDivisor > 0; uiDivisor /= 1000 )
  424. {
  425. if ( uiNumber > uiDivisor )
  426. {
  427. unsigned int uiPrint = ( uiNumber / uiDivisor ) % 1000;
  428. sprintf( pchBuffer + strlen( pchBuffer ), ( uiNumber / uiDivisor < 1000 ) ? "%d," : "%03d,", uiPrint );
  429. }
  430. }
  431. int len = strlen( pchBuffer );
  432. if ( !len )
  433. sprintf( pchBuffer, "0" );
  434. else if ( pchBuffer[ len - 1 ] == ',' )
  435. pchBuffer[ len - 1 ] = 0;
  436. }
  437. namespace
  438. {
  439. char s_chLastViewedTextureBuffer[ 0x200 ] = {0};
  440. }; // end `anonymous` namespace
  441. bool CanAdjustTextureSize( char const *szTextureName, bool bMoveSizeUp )
  442. {
  443. ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
  444. if ( !pMatTexture )
  445. return false;
  446. // Determine the texture current size
  447. if ( !bMoveSizeUp )
  448. {
  449. return ( pMatTexture->GetActualWidth() > 4 || pMatTexture->GetActualHeight() > 4 );
  450. }
  451. else
  452. {
  453. return ( pMatTexture->GetActualWidth() < pMatTexture->GetMappingWidth() ||
  454. pMatTexture->GetActualHeight() < pMatTexture->GetMappingHeight() );
  455. }
  456. }
  457. bool AdjustTextureSize( char const *szTextureName, bool bMoveSizeUp )
  458. {
  459. ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
  460. if ( !pMatTexture )
  461. return false;
  462. pMatTexture->ForceLODOverride( bMoveSizeUp ? +1 : -1 );
  463. return true;
  464. }
  465. CON_COMMAND_F( mat_texture_list_txlod, "Adjust LOD of the last viewed texture +1 to inc resolution, -1 to dec resolution", FCVAR_DONTRECORD )
  466. {
  467. if ( args.ArgC() == 2 )
  468. {
  469. int iAdjustment = atoi( args.Arg( 1 ) );
  470. switch ( iAdjustment )
  471. {
  472. case 1:
  473. case -1:
  474. if ( !CanAdjustTextureSize( s_chLastViewedTextureBuffer, iAdjustment > 0 ) )
  475. Warning( "mat_texture_list_txlod cannot adjust lod for '%s'\n", s_chLastViewedTextureBuffer );
  476. else if ( !AdjustTextureSize( s_chLastViewedTextureBuffer, iAdjustment > 0 ) )
  477. Warning( "mat_texture_list_txlod failed adjusting lod for '%s'\n", s_chLastViewedTextureBuffer );
  478. else
  479. Msg( "mat_texture_list_txlod adjusted lod %c1 for '%s'\n", ( iAdjustment > 0 ) ? '+' : '-' , s_chLastViewedTextureBuffer );
  480. return;
  481. default:
  482. break;
  483. }
  484. }
  485. Warning( "Usage: 'mat_texture_list_txlod +1' to inc lod | 'mat_texture_list_txlod -1' to dec lod\n" );
  486. }
  487. static bool SaveTextureImage( char const *szTextureName )
  488. {
  489. bool bRet;
  490. char fileName[ MAX_PATH ];
  491. char baseName[ MAX_PATH ];
  492. ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
  493. if ( !pMatTexture )
  494. {
  495. Msg( "materials->FindTexture( '%s' ) failed.\n", szTextureName );
  496. return false;
  497. }
  498. V_FileBase( szTextureName, baseName, ARRAYSIZE( baseName ) );
  499. Q_snprintf( fileName, ARRAYSIZE( fileName ), "//MOD/tex_%s.tga", baseName );
  500. bRet = pMatTexture->SaveToFile( fileName );
  501. Msg( "SaveTextureImage( '%s' ): %s\n", fileName, bRet ? "succeeded" : "failed" );
  502. return bRet;
  503. }
  504. namespace MatViewOverride
  505. {
  506. //
  507. // View override parameters request
  508. //
  509. struct ViewParamsReq
  510. {
  511. CUtlVector< UtlSymId_t > lstMaterials;
  512. }
  513. s_viewParamsReq;
  514. void RequestSelectNone( void )
  515. {
  516. s_viewParamsReq.lstMaterials.RemoveAll();
  517. }
  518. void RequestSelected( int nCount, UtlSymId_t const *pNameIds )
  519. {
  520. s_viewParamsReq.lstMaterials.AddMultipleToTail( nCount, pNameIds );
  521. }
  522. //
  523. // View override last parameters
  524. //
  525. struct ViewParamsLast
  526. {
  527. ViewParamsLast() : lstMaterials( DefLessFunc( UtlSymId_t ) ), flTime( 0.f ), bHighlighted( false ) {}
  528. float flTime;
  529. bool bHighlighted;
  530. struct TxInfo
  531. {
  532. ITexture *pTx;
  533. CUtlSymbol name;
  534. };
  535. struct VarMap : public CUtlMap< UtlSymId_t, TxInfo >
  536. {
  537. VarMap() : CUtlMap< UtlSymId_t, TxInfo >( DefLessFunc( UtlSymId_t ) ) {}
  538. VarMap( VarMap const &x ) { const_cast< VarMap & >( x ).Swap( *this ); m_matInfo = x.m_matInfo; } // Fast-swap data
  539. struct MatInfo
  540. {
  541. // MatInfo() : ignorez( false ) {}
  542. // bool ignorez;
  543. MatInfo() {}
  544. } m_matInfo;
  545. };
  546. CUtlMap< UtlSymId_t, VarMap > lstMaterials;
  547. }
  548. s_viewParamsLast;
  549. //
  550. // DisplaySelectedTextures
  551. // Executed every frame to toggle the selected/unselected
  552. // textures for a list of materials.
  553. //
  554. void DisplaySelectedTextures()
  555. {
  556. // Nothing selected
  557. if ( !s_viewParamsLast.lstMaterials.Count() &&
  558. !s_viewParamsReq.lstMaterials.Count() )
  559. return;
  560. if ( !s_viewParamsLast.lstMaterials.Count() &&
  561. s_viewParamsReq.lstMaterials.Count() )
  562. {
  563. // First time selection
  564. s_viewParamsLast.flTime = Plat_FloatTime();
  565. s_viewParamsLast.bHighlighted = false;
  566. }
  567. else
  568. {
  569. // Wait for the flash-time
  570. float fCurTime = Plat_FloatTime();
  571. if ( fCurTime >= s_viewParamsLast.flTime &&
  572. fCurTime < s_viewParamsLast.flTime + 0.4 )
  573. return;
  574. s_viewParamsLast.flTime = fCurTime;
  575. s_viewParamsLast.bHighlighted = !s_viewParamsLast.bHighlighted;
  576. }
  577. // Find the empty texture
  578. ITexture *txEmpty = materials->FindTexture( "debugempty", "", false );
  579. typedef unsigned short MapIdx;
  580. // Now walk over all the materials in the req list and push them to the params
  581. for ( int k = 0, kEnd = s_viewParamsReq.lstMaterials.Count(); k < kEnd; ++ k )
  582. {
  583. UtlSymId_t idMat = s_viewParamsReq.lstMaterials[ k ];
  584. MapIdx idx = s_viewParamsLast.lstMaterials.Find( idMat );
  585. if ( idx == s_viewParamsLast.lstMaterials.InvalidIndex() )
  586. {
  587. // Insert the new material
  588. idx = s_viewParamsLast.lstMaterials.Insert( idMat );
  589. ViewParamsLast::VarMap &vars = s_viewParamsLast.lstMaterials.Element( idx );
  590. // Locate the material
  591. char const *szMaterialName = CUtlSymbol( idMat ).String();
  592. IMaterial *pMat = materials->FindMaterial( szMaterialName, TEXTURE_GROUP_OTHER, false );
  593. if ( pMat )
  594. {
  595. int numParams = pMat->ShaderParamCount();
  596. IMaterialVar **arrVars = pMat->GetShaderParams();
  597. for ( int idxParam = 0; idxParam < numParams; ++ idxParam )
  598. {
  599. // if ( !stricmp( arrVars[ idxParam ]->GetName(), "$ignorez" ) )
  600. // {
  601. // vars.m_matInfo.ignorez = arrVars[ idxParam ]->GetIntValue() ? true : false;
  602. // arrVars[ idxParam ]->SetIntValue( 1 );
  603. // continue;
  604. // }
  605. if ( !arrVars[ idxParam ]->IsTexture() )
  606. continue;
  607. ITexture *pTex = arrVars[ idxParam ]->GetTextureValue();
  608. if ( !pTex || pTex->IsError() )
  609. continue;
  610. ViewParamsLast::TxInfo txinfo;
  611. txinfo.name = CUtlSymbol( pTex->GetName() );
  612. txinfo.pTx = pTex;
  613. vars.Insert( CUtlSymbol( arrVars[ idxParam ]->GetName() ), txinfo );
  614. }
  615. }
  616. }
  617. }
  618. // Now walk over all the materials that we have to highlight or unhighlight
  619. for ( MapIdx idx = s_viewParamsLast.lstMaterials.FirstInorder();
  620. idx != s_viewParamsLast.lstMaterials.InvalidIndex();
  621. /* advance inside */ )
  622. {
  623. UtlSymId_t idMat = s_viewParamsLast.lstMaterials.Key( idx );
  624. ViewParamsLast::VarMap &vars = s_viewParamsLast.lstMaterials.Element( idx );
  625. bool bRemovedSelection = ( s_viewParamsReq.lstMaterials.Find( idMat ) < 0 );
  626. char const *szMaterialName = CUtlSymbol( idMat ).String();
  627. IMaterial *pMat = materials->FindMaterial( szMaterialName, TEXTURE_GROUP_OTHER, false );
  628. if ( pMat )
  629. {
  630. int numParams = pMat->ShaderParamCount();
  631. IMaterialVar **arrVars = pMat->GetShaderParams();
  632. for ( int idxParam = 0; idxParam < numParams; ++ idxParam )
  633. {
  634. // if ( bRemovedSelection && !stricmp( arrVars[ idxParam ]->GetName(), "$ignorez" ) )
  635. // {
  636. // arrVars[ idxParam ]->SetIntValue( vars.m_matInfo.ignorez ? 1 : 0 );
  637. // continue;
  638. // }
  639. char const *szVarName = arrVars[ idxParam ]->GetName();
  640. CUtlSymbol symVarName( szVarName );
  641. MapIdx idxVarsTxInfo = vars.Find( symVarName );
  642. if ( idxVarsTxInfo != vars.InvalidIndex() )
  643. {
  644. ViewParamsLast::TxInfo &ti = vars.Element( idxVarsTxInfo );
  645. ITexture *pTx = ( s_viewParamsLast.bHighlighted && !bRemovedSelection ) ? txEmpty : ti.pTx;
  646. Assert( ti.pTx && !ti.pTx->IsError() );
  647. arrVars[ idxParam ]->SetTextureValue( pTx );
  648. }
  649. }
  650. }
  651. // Index advance
  652. if ( bRemovedSelection )
  653. {
  654. MapIdx idxRemove = idx;
  655. idx = s_viewParamsLast.lstMaterials.NextInorder( idx );
  656. s_viewParamsLast.lstMaterials.RemoveAt( idxRemove );
  657. }
  658. else
  659. {
  660. idx = s_viewParamsLast.lstMaterials.NextInorder( idx );
  661. }
  662. }
  663. }
  664. }; // end namespace MatViewOverride
  665. //////////////////////////////////////////////////////////////////////////
  666. //
  667. // Custom text entry with "Open" for vmt's
  668. //
  669. //////////////////////////////////////////////////////////////////////////
  670. class CVmtTextEntry : public vgui::TextEntry
  671. {
  672. DECLARE_CLASS_SIMPLE( CVmtTextEntry, vgui::TextEntry );
  673. public:
  674. CVmtTextEntry( vgui::Panel *parent, char const *szName ) : BaseClass( parent, szName ) {}
  675. public:
  676. MESSAGE_FUNC( OpenVmtSelected, "DoOpenVmtSelected" );
  677. virtual void OpenEditMenu();
  678. };
  679. void CVmtTextEntry::OpenEditMenu()
  680. {
  681. vgui::Menu *pEditMenu = BaseClass::GetEditMenu();
  682. int pos = pEditMenu->AddMenuItem( "Open VMT", new KeyValues("DoOpenVmtSelected"), this );
  683. pEditMenu->MoveMenuItem( pos, 0 );
  684. int x0, x1;
  685. pEditMenu->SetItemEnabled( "Open VMT", GetSelectedRange(x0, x1) );
  686. BaseClass::OpenEditMenu();
  687. }
  688. void CVmtTextEntry::OpenVmtSelected()
  689. {
  690. int x0, x1;
  691. if ( !GetSelectedRange(x0, x1) )
  692. return;
  693. CUtlVector<char> buf;
  694. buf.SetCount( x1 - x0 + 1 );
  695. GetTextRange( buf.Base(), x0, x1 - x0 );
  696. for ( char *pchName = buf.Base(), *pchNext = NULL; pchName; pchName = pchNext )
  697. {
  698. if ( ( pchNext = strchr( pchName, '\n' ) ) != NULL )
  699. *( pchNext ++ ) = 0;
  700. char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
  701. Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vmt", pchName );
  702. char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
  703. if ( szResolvedName )
  704. vgui::system()->ShellExecuteEx( "open", szResolvedName, "" );
  705. }
  706. }
  707. #ifdef IS_WINDOWS_PC
  708. bool IsSpaceOrQuote( char val )
  709. {
  710. return (isspace(val) || val == '\"');
  711. }
  712. static bool SetBufferValue( char *chTxtFileBuffer, char const *szLookupKey, char const *szNewValue )
  713. {
  714. bool bResult = false;
  715. size_t lenTmp = strlen( szNewValue );
  716. size_t nTxtFileBufferLen = strlen( chTxtFileBuffer );
  717. for ( char *pch = chTxtFileBuffer;
  718. ( NULL != ( pch = strstr( pch, szLookupKey ) ) );
  719. ++ pch )
  720. {
  721. char *val = pch + strlen( szLookupKey );
  722. if ( !IsSpaceOrQuote( *val ) )
  723. continue;
  724. else
  725. ++ val;
  726. // Skip over the whitespace and quotes
  727. while ( *val && IsSpaceOrQuote( *val ) )
  728. ++ val;
  729. char *pValStart = val;
  730. // Okay, here comes the value
  731. while ( *val && IsSpaceOrQuote( *val ) )
  732. ++ val;
  733. while ( *val && !IsSpaceOrQuote( *val ) )
  734. ++ val;
  735. char *pValEnd = val; // Okay, here ends the value
  736. memmove( pValStart + lenTmp, pValEnd, chTxtFileBuffer + nTxtFileBufferLen + 1 - pValEnd );
  737. memcpy( pValStart, szNewValue, lenTmp );
  738. nTxtFileBufferLen += ( lenTmp - ( pValEnd - pValStart ) );
  739. bResult = true;
  740. }
  741. if ( !bResult )
  742. {
  743. char *pchAdd = chTxtFileBuffer + nTxtFileBufferLen;
  744. strcpy( pchAdd + strlen( pchAdd ), "\n" );
  745. strcpy( pchAdd + strlen( pchAdd ), szLookupKey );
  746. strcpy( pchAdd + strlen( pchAdd ), " " );
  747. strcpy( pchAdd + strlen( pchAdd ), szNewValue );
  748. strcpy( pchAdd + strlen( pchAdd ), "\n" );
  749. bResult = true;
  750. }
  751. return bResult;
  752. }
  753. // Replaces the first occurrence of "szFindData" with "szNewData"
  754. // Returns the remaining buffer past the replaced data or NULL if
  755. // no replacement occurred.
  756. static char * BufferReplace( char *buf, char const *szFindData, char const *szNewData )
  757. {
  758. size_t len = strlen( buf ), lFind = strlen( szFindData ), lNew = strlen( szNewData );
  759. if ( char *pBegin = strstr( buf, szFindData ) )
  760. {
  761. memmove( pBegin + lNew, pBegin + lFind, buf + len - ( pBegin + lFind ) );
  762. memmove( pBegin, szNewData, lNew );
  763. return pBegin + lNew;
  764. }
  765. return NULL;
  766. }
  767. class CP4Requirement
  768. {
  769. public:
  770. CP4Requirement();
  771. ~CP4Requirement();
  772. protected:
  773. bool m_bLoadedModule;
  774. CSysModule *m_pP4Module;
  775. };
  776. CP4Requirement::CP4Requirement() :
  777. m_bLoadedModule( false ),
  778. m_pP4Module( NULL )
  779. {
  780. #ifdef STAGING_ONLY
  781. if ( p4 )
  782. return;
  783. // load the p4 lib
  784. m_pP4Module = Sys_LoadModule( "p4lib" );
  785. m_bLoadedModule = true;
  786. if ( m_pP4Module )
  787. {
  788. CreateInterfaceFn factory = Sys_GetFactory( m_pP4Module );
  789. if ( factory )
  790. {
  791. p4 = ( IP4 * )factory( P4_INTERFACE_VERSION, NULL );
  792. if ( p4 )
  793. {
  794. extern CreateInterfaceFn g_AppSystemFactory;
  795. p4->Connect( g_AppSystemFactory );
  796. p4->Init();
  797. }
  798. }
  799. }
  800. #endif // STAGING_ONLY
  801. if ( !p4 )
  802. {
  803. Warning( "Can't load p4lib.dll\n" );
  804. }
  805. }
  806. CP4Requirement::~CP4Requirement()
  807. {
  808. if ( m_bLoadedModule && m_pP4Module )
  809. {
  810. if ( p4 )
  811. {
  812. p4->Shutdown();
  813. p4->Disconnect();
  814. }
  815. Sys_UnloadModule( m_pP4Module );
  816. m_pP4Module = NULL;
  817. p4 = NULL;
  818. }
  819. }
  820. #endif // #ifdef IS_WINDOWS_PC
  821. //////////////////////////////////////////////////////////////////////////
  822. //
  823. // Render textures edit panel
  824. //
  825. //////////////////////////////////////////////////////////////////////////
  826. class CRenderTextureEditor : public vgui::Frame
  827. {
  828. DECLARE_CLASS_SIMPLE( CRenderTextureEditor, vgui::Frame );
  829. public:
  830. CRenderTextureEditor( vgui::Panel *parent, char const *szName );
  831. ~CRenderTextureEditor();
  832. public:
  833. virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
  834. virtual void PerformLayout();
  835. virtual void OnCommand( const char *command );
  836. virtual void SetFont( vgui::HFont hFont ) { m_hFont = hFont; Repaint(); }
  837. virtual vgui::HFont GetFont() { return m_hFont; }
  838. public:
  839. virtual void OnMousePressed( vgui::MouseCode code );
  840. virtual void OnMouseDoublePressed( vgui::MouseCode code ) { OnMousePressed( code ); }
  841. virtual void Activate();
  842. virtual void Close();
  843. public:
  844. void SetDispInfo( KeyValues *kv, int iHint );
  845. void GetDispInfo( KeyValues *&kv, int &iHint );
  846. public:
  847. virtual void Paint();
  848. enum
  849. {
  850. TILE_BORDER = 10,
  851. TILE_SIZE = 550,
  852. TILE_TEXTURE_SIZE = 256,
  853. TILE_TEXT = 70
  854. };
  855. protected:
  856. vgui::HFont m_hFont;
  857. CVmtTextEntry *m_pMaterials;
  858. vgui::Button *m_pExplore;
  859. vgui::Button *m_pReload;
  860. vgui::Button *m_pRebuild;
  861. vgui::Button *m_pToggleNoMip;
  862. vgui::Button *m_pCopyTxt;
  863. #ifndef POSIX
  864. vgui::Button *m_pCopyImg;
  865. #endif
  866. vgui::Button *m_pSaveImg;
  867. vgui::Button *m_pSizeControls[2];
  868. vgui::Button *m_pFlashBtn;
  869. KeyValues *m_pInfo;
  870. CUtlBuffer m_bufInfoText;
  871. CUtlVector< UtlSymId_t > m_lstMaterials;
  872. int m_iInfoHint;
  873. };
  874. CRenderTextureEditor::CRenderTextureEditor( vgui::Panel *parent, char const *szName ) :
  875. BaseClass( parent, szName ),
  876. m_pInfo( NULL ),
  877. m_iInfoHint( 0 ),
  878. m_hFont( vgui::INVALID_FONT ),
  879. m_bufInfoText( 0, 0, CUtlBuffer::TEXT_BUFFER )
  880. {
  881. m_pMaterials = vgui::SETUP_PANEL( new CVmtTextEntry( this, "Materials" ) );
  882. m_pMaterials->SetMultiline( true );
  883. m_pMaterials->SetEditable( false );
  884. m_pMaterials->SetEnabled( false );
  885. m_pMaterials->SetVerticalScrollbar( true );
  886. m_pMaterials->SetVisible( true );
  887. m_pExplore = vgui::SETUP_PANEL( new vgui::Button( this, "Explore", "Open", this, "Explore" ) );
  888. m_pExplore->SetVisible( true );
  889. m_pReload = vgui::SETUP_PANEL( new vgui::Button( this, "Reload", "Reload", this, "Reload" ) );
  890. m_pReload->SetVisible( true );
  891. m_pRebuild = vgui::SETUP_PANEL( new vgui::Button( this, "RebuildVTF", "Rebuild VTF", this, "RebuildVTF" ) );
  892. m_pRebuild->SetVisible( true );
  893. m_pToggleNoMip = vgui::SETUP_PANEL( new vgui::Button( this, "ToggleNoMip", "ToggleNoMip", this, "ToggleNoMip" ) );
  894. m_pToggleNoMip->SetVisible( true );
  895. m_pCopyTxt = vgui::SETUP_PANEL( new vgui::Button( this, "CopyTxt", "Copy Text", this, "CopyTxt" ) );
  896. m_pCopyTxt->SetVisible( true );
  897. #ifndef POSIX
  898. m_pCopyImg = vgui::SETUP_PANEL( new vgui::Button( this, "CopyImg", "Copy Image", this, "CopyImg" ) );
  899. m_pCopyImg->SetVisible( true );
  900. #endif
  901. m_pSaveImg = vgui::SETUP_PANEL( new vgui::Button( this, "SaveImg", "Save Image", this, "SaveImg" ) );
  902. m_pSaveImg->SetVisible( true );
  903. m_pFlashBtn = vgui::SETUP_PANEL( new vgui::Button( this, "FlashBtn", "Flash in Game", this, "FlashBtn" ) );
  904. m_pFlashBtn->SetVisible( true );
  905. m_pSizeControls[0] = vgui::SETUP_PANEL( new vgui::Button( this, "--", "--", this, "size-" ) );
  906. m_pSizeControls[1] = vgui::SETUP_PANEL( new vgui::Button( this, "+", "+", this, "size+" ) );
  907. }
  908. CRenderTextureEditor::~CRenderTextureEditor()
  909. {
  910. SetDispInfo( NULL, 0 );
  911. }
  912. void CRenderTextureEditor::GetDispInfo( KeyValues *&kv, int &iHint )
  913. {
  914. iHint = m_iInfoHint;
  915. kv = m_pInfo;
  916. }
  917. void CRenderTextureEditor::SetDispInfo( KeyValues *kv, int iHint )
  918. {
  919. m_iInfoHint = iHint;
  920. if ( m_pInfo )
  921. m_pInfo->deleteThis();
  922. m_pInfo = kv ? kv->MakeCopy() : NULL;
  923. CUtlStringMap< bool > arrMaterials, arrMaterialsFullNames;
  924. if ( kv )
  925. {
  926. char const *szTextureName = kv->GetString( KEYNAME_NAME );
  927. for ( MaterialHandle_t hm = materials->FirstMaterial();
  928. hm != materials->InvalidMaterial(); hm = materials->NextMaterial( hm ) )
  929. {
  930. IMaterial *pMat = materials->GetMaterial( hm );
  931. if ( !pMat )
  932. continue;
  933. int numParams = pMat->ShaderParamCount();
  934. IMaterialVar **arrVars = pMat->GetShaderParams();
  935. for ( int idxParam = 0; idxParam < numParams; ++ idxParam )
  936. {
  937. if ( !arrVars[ idxParam ]->IsTexture() )
  938. continue;
  939. ITexture *pTex = arrVars[ idxParam ]->GetTextureValue();
  940. if ( !pTex || pTex->IsError() )
  941. continue;
  942. if ( !stricmp( pTex->GetName(), szTextureName ) )
  943. {
  944. bool bRealMaterial = true;
  945. if ( StringHasPrefix( pMat->GetName(), "debug/debugtexture" ) )
  946. bRealMaterial = false;
  947. if ( StringHasPrefix( pMat->GetName(), "maps/" ) )
  948. {
  949. // Format: maps/mapname/[matname]_x_y_z
  950. bRealMaterial = false;
  951. char chName[ MAX_PATH ];
  952. Q_strncpy( chName, pMat->GetName() + 5, sizeof( chName ) - 1 );
  953. if ( char *szMatName = strchr( chName, '/' ) )
  954. {
  955. ++ szMatName;
  956. for ( int k = 0; k < 3; ++ k )
  957. {
  958. if ( char *rUnderscore = strrchr( szMatName, '_' ) )
  959. *rUnderscore = 0;
  960. }
  961. sprintf( szMatName + strlen( szMatName ), " (cubemap)" );
  962. arrMaterials[ szMatName ] = true;
  963. }
  964. arrMaterialsFullNames[ pMat->GetName() ] = true;
  965. }
  966. if ( bRealMaterial )
  967. {
  968. arrMaterials[ pMat->GetName() ] = true;
  969. arrMaterialsFullNames[ pMat->GetName() ] = true;
  970. }
  971. break;
  972. }
  973. }
  974. }
  975. }
  976. // Now that we have a list of materials make a printable version
  977. CUtlBuffer bufText( 0, 0, CUtlBuffer::TEXT_BUFFER );
  978. if ( !arrMaterials.GetNumStrings() )
  979. {
  980. bufText.Printf( "-- no materials --" );
  981. }
  982. else
  983. {
  984. int c = arrMaterials.GetNumStrings();
  985. bufText.Printf( " %d material%s:", c, ( c%10 == 1 && c != 11 ) ? "" : "s" );
  986. }
  987. for ( int k = 0; k < arrMaterials.GetNumStrings(); ++ k )
  988. {
  989. bufText.Printf( "\n%s", arrMaterials.String( k ) );
  990. }
  991. m_pSaveImg->SetVisible( false );
  992. // Set text except for the cases when m_pInfo and no materials found
  993. if ( !( m_pInfo && !arrMaterials.GetNumStrings() ) )
  994. {
  995. if ( kv )
  996. {
  997. int iTxWidth = kv->GetInt( KEYNAME_WIDTH );
  998. int iTxHeight = kv->GetInt( KEYNAME_HEIGHT );
  999. char const *szTxFormat = kv->GetString( KEYNAME_FORMAT );
  1000. bufText.Printf( "\n%dx%d Format:%s", iTxWidth, iTxHeight, szTxFormat );
  1001. // We support saving the 8888 formats right now: "RGBA8888", "ABGR8888", "ARGB8888", "BGRA8888", "BGRX8888"
  1002. if( Q_strstr( szTxFormat, "8888" ) )
  1003. {
  1004. m_pSaveImg->SetVisible( true );
  1005. }
  1006. }
  1007. m_pMaterials->SetText( ( char const * ) bufText.Base() );
  1008. m_lstMaterials.RemoveAll();
  1009. m_lstMaterials.EnsureCapacity( arrMaterialsFullNames.GetNumStrings() );
  1010. for ( int k = 0; k < arrMaterialsFullNames.GetNumStrings(); ++ k )
  1011. {
  1012. m_lstMaterials.AddToTail( CUtlSymbol( arrMaterialsFullNames.String( k ) ) );
  1013. }
  1014. }
  1015. m_bufInfoText.Clear();
  1016. InvalidateLayout();
  1017. }
  1018. void CRenderTextureEditor::Close()
  1019. {
  1020. BaseClass::Close();
  1021. SetDispInfo( NULL, 0 );
  1022. }
  1023. void CRenderTextureEditor::Activate()
  1024. {
  1025. BaseClass::Activate();
  1026. }
  1027. void CRenderTextureEditor::PerformLayout()
  1028. {
  1029. BaseClass::PerformLayout();
  1030. int iRenderedHeight = 4 * TILE_BORDER + TILE_TEXT + TILE_SIZE;
  1031. SetSize( 4 * TILE_BORDER + TILE_SIZE,
  1032. iRenderedHeight + 90 + TILE_BORDER );
  1033. m_pMaterials->SetPos( TILE_BORDER, iRenderedHeight + 2 );
  1034. m_pMaterials->SetSize( 2 * TILE_BORDER + TILE_SIZE, 90 );
  1035. m_pExplore->SetPos( 2 * TILE_BORDER + TILE_SIZE - 50, 2 * TILE_BORDER );
  1036. m_pExplore->SetWide( 50 );
  1037. m_pReload->SetPos( 2 * TILE_BORDER + TILE_SIZE - 50 - 65, 2 * TILE_BORDER );
  1038. m_pReload->SetWide( 60 );
  1039. m_pReload->SetVisible( m_lstMaterials.Count() > 0 );
  1040. m_pRebuild->SetPos( 2 * TILE_BORDER + TILE_SIZE - 50 - 65 - 95, 2 * TILE_BORDER );
  1041. m_pRebuild->SetWide( 90 );
  1042. m_pRebuild->SetVisible( m_lstMaterials.Count() > 0 );
  1043. m_pToggleNoMip->SetPos( 2 * TILE_BORDER + TILE_SIZE - 50 - 95, (2 * TILE_BORDER) + m_pReload->GetTall() + 1 );
  1044. m_pToggleNoMip->SetWide( 90 );
  1045. m_pToggleNoMip->SetVisible( m_lstMaterials.Count() > 0 );
  1046. m_pExplore->SetVisible( false );
  1047. m_pSizeControls[0]->SetVisible( false );
  1048. m_pSizeControls[1]->SetVisible( false );
  1049. if ( m_pInfo )
  1050. {
  1051. char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
  1052. Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vtf", m_pInfo->GetString( KEYNAME_NAME ) );
  1053. char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
  1054. if ( szResolvedName )
  1055. {
  1056. m_pExplore->SetVisible( true );
  1057. }
  1058. if ( !m_pInfo->GetInt( "SpecialTx" ) )
  1059. {
  1060. m_pSizeControls[0]->SetVisible( true );
  1061. m_pSizeControls[1]->SetVisible( true );
  1062. m_pSizeControls[0]->SetEnabled( CanAdjustTextureSize( m_pInfo->GetString( KEYNAME_NAME ), false ) );
  1063. m_pSizeControls[1]->SetEnabled( CanAdjustTextureSize( m_pInfo->GetString( KEYNAME_NAME ), true ) );
  1064. int posX, posY;
  1065. m_pExplore->GetPos( posX, posY );
  1066. m_pSizeControls[0]->SetPos( posX, posY + m_pExplore->GetTall() + 1 );
  1067. m_pSizeControls[0]->SetWide( m_pExplore->GetWide() / 2 );
  1068. m_pSizeControls[1]->SetPos( posX + m_pSizeControls[0]->GetWide() + 1, posY + m_pExplore->GetTall() + 1 );
  1069. m_pSizeControls[1]->SetWide( m_pExplore->GetWide() - ( m_pSizeControls[0]->GetWide() + 1 ) );
  1070. }
  1071. }
  1072. {
  1073. int posX, posY;
  1074. m_pExplore->GetPos( posX, posY );
  1075. posY += m_pExplore->GetTall() * 2 + 2;
  1076. posX += m_pExplore->GetWide();
  1077. posX -= 80;
  1078. m_pSaveImg->SetPos( posX, posY );
  1079. m_pSaveImg->SetWide( 80 );
  1080. #ifndef POSIX
  1081. posX -= 80 + 5;
  1082. m_pCopyImg->SetPos( posX, posY );
  1083. m_pCopyImg->SetWide( 80 );
  1084. #endif
  1085. posX -= 80 + 5;
  1086. m_pCopyTxt->SetPos( posX, posY );
  1087. m_pCopyTxt->SetWide( 80 );
  1088. posX -= 95 + 5;
  1089. m_pFlashBtn->SetPos( posX, posY );
  1090. m_pFlashBtn->SetWide( 95 );
  1091. }
  1092. }
  1093. #ifdef IS_WINDOWS_PC
  1094. bool GetTextureContentPath( const char *pszVTF, char *szTextureContentPath, int nBufSize )
  1095. {
  1096. char vhRelVTF[MAX_PATH];
  1097. Q_snprintf( vhRelVTF, sizeof( vhRelVTF ) - 1, "materials/%s.vtf", pszVTF );
  1098. ConVarRef mat_texture_list_content_path( "mat_texture_list_content_path" );
  1099. if ( !mat_texture_list_content_path.GetString()[0] )
  1100. {
  1101. szTextureContentPath = const_cast< char * >( g_pFileSystem->RelativePathToFullPath( vhRelVTF, "game", szTextureContentPath, nBufSize - 1 ) );
  1102. if ( !szTextureContentPath )
  1103. {
  1104. Warning( " texture '%s' is not loaded from file system.\n", pszVTF );
  1105. return false;
  1106. }
  1107. if ( !BufferReplace( szTextureContentPath, "\\game\\", "\\content\\" ) ||
  1108. !BufferReplace( szTextureContentPath, "\\materials\\", "\\materialsrc\\" ) )
  1109. {
  1110. Warning( " texture '%s' cannot be mapped to content directory.\n", pszVTF );
  1111. return false;
  1112. }
  1113. }
  1114. else
  1115. {
  1116. V_strncpy( szTextureContentPath, mat_texture_list_content_path.GetString(), MAX_PATH );
  1117. V_strncat( szTextureContentPath, "/", MAX_PATH );
  1118. V_strncat( szTextureContentPath, pszVTF, MAX_PATH );
  1119. V_strncat( szTextureContentPath, ".vtf", MAX_PATH );
  1120. }
  1121. return true;
  1122. }
  1123. #endif // #ifdef IS_WINDOWS_PC
  1124. void CRenderTextureEditor::OnCommand( const char *command )
  1125. {
  1126. BaseClass::OnCommand( command );
  1127. if ( !stricmp( command, "Explore" ) && m_pInfo )
  1128. {
  1129. char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
  1130. Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vtf", m_pInfo->GetString( KEYNAME_NAME ) );
  1131. char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
  1132. char params[256];
  1133. Q_snprintf( params, sizeof( params ) - 1, "/E,/SELECT,%s", szResolvedName );
  1134. vgui::system()->ShellExecuteEx( "open", "explorer.exe", params );
  1135. }
  1136. if ( !stricmp( command, "Reload" ) && m_lstMaterials.Count() )
  1137. {
  1138. CUtlBuffer bufCommand( 0, 0, CUtlBuffer::TEXT_BUFFER );
  1139. int idxMaterial = 0;
  1140. //
  1141. // Issue the console command several times in case we overflow the
  1142. // console command buffer size.
  1143. //
  1144. Cbuf_Execute();
  1145. for ( ; idxMaterial < m_lstMaterials.Count(); )
  1146. {
  1147. int iOldIdx = idxMaterial;
  1148. bufCommand.Printf( "mat_reloadmaterial \"" );
  1149. for ( ; idxMaterial < m_lstMaterials.Count(); ++ idxMaterial )
  1150. {
  1151. int iOldSize = bufCommand.TellPut();
  1152. int const iSizeLimit = CCommand::MaxCommandLength() - 3;
  1153. char const *szString = CUtlSymbol( m_lstMaterials[idxMaterial] ).String();
  1154. bufCommand.Printf( "%s%s", ( idxMaterial > iOldIdx ) ? "*" : "", szString );
  1155. if ( bufCommand.TellPut() > iSizeLimit &&
  1156. idxMaterial > iOldIdx )
  1157. {
  1158. bufCommand.SeekPut( CUtlBuffer::SEEK_HEAD, iOldSize );
  1159. break;
  1160. }
  1161. }
  1162. bufCommand.Printf( "\"\n" );
  1163. bufCommand.PutChar( 0 );
  1164. Cbuf_AddText( ( char const * ) bufCommand.Base() );
  1165. bufCommand.Clear();
  1166. Cbuf_Execute();
  1167. }
  1168. }
  1169. if ( !stricmp( command, "CopyTxt" ) )
  1170. {
  1171. char const *szName = ( char const * ) m_bufInfoText.Base();
  1172. if ( !m_bufInfoText.TellPut() || !szName )
  1173. szName = "";
  1174. vgui::system()->SetClipboardText( szName, strlen( szName ) + 1 );
  1175. }
  1176. if ( !stricmp( command, "CopyImg" ) )
  1177. {
  1178. int x = 0, y = 0;
  1179. this->LocalToScreen( x, y );
  1180. void *pMainWnd = game->GetMainWindow();
  1181. vgui::system()->SetClipboardImage( pMainWnd, x, y, x + GetWide(), y + GetTall() );
  1182. }
  1183. if ( !stricmp( command, "SaveImg" ) )
  1184. {
  1185. SaveTextureImage( m_pInfo->GetString( KEYNAME_NAME ) );
  1186. }
  1187. if ( !stricmp( command, "FlashBtn" ) )
  1188. {
  1189. MatViewOverride::RequestSelectNone();
  1190. MatViewOverride::RequestSelected( m_lstMaterials.Count(), m_lstMaterials.Base() );
  1191. mat_texture_list_off_f();
  1192. }
  1193. if ( ( !stricmp( command, "size-" ) || !stricmp( command, "size+" ) ) && m_pInfo )
  1194. {
  1195. bool bSizeUp = ( command[4] == '+' );
  1196. bool bResult = AdjustTextureSize( m_pInfo->GetString( KEYNAME_NAME ), bSizeUp );
  1197. if ( bResult )
  1198. {
  1199. CAutoPushPop<bool> auto_g_bRecursiveRequestToShowTextureList( g_bRecursiveRequestToShowTextureList, true );
  1200. mat_texture_list_on_f();
  1201. }
  1202. InvalidateLayout();
  1203. }
  1204. if ( !stricmp( command, "ToggleNoMip" ) )
  1205. {
  1206. #ifdef IS_WINDOWS_PC
  1207. CP4Requirement p4req;
  1208. if ( !p4 )
  1209. g_p4factory->SetDummyMode( true );
  1210. char const *szTextureFile = m_pInfo->GetString( KEYNAME_NAME );
  1211. char const *szTextureGroup = m_pInfo->GetString( KEYNAME_TEXTURE_GROUP );
  1212. ITexture *pMatTexture = NULL;
  1213. if ( *szTextureFile )
  1214. pMatTexture = materials->FindTexture( szTextureFile, szTextureGroup, false );
  1215. if ( !pMatTexture )
  1216. pMatTexture = materials->FindTexture( "debugempty", "", false );
  1217. bool bNewNoMip = !(pMatTexture->GetFlags() & TEXTUREFLAGS_NOMIP);
  1218. char szFileName[MAX_PATH];
  1219. if ( !GetTextureContentPath( szTextureFile, szFileName, sizeof(szFileName) ) )
  1220. return;
  1221. // Figure out what kind of source content is there:
  1222. // 1. look for TGA - if found, get the txt file (if txt file missing, create one)
  1223. // 2. otherwise look for PSD - affecting psdinfo
  1224. // 3. else error
  1225. char *pExtPut = szFileName + strlen( szFileName ) - strlen( ".vtf" ); // compensating the TEXTURE_FNAME_EXTENSION(.vtf) extension
  1226. // 1.tga
  1227. sprintf( pExtPut, ".tga" );
  1228. if ( g_pFullFileSystem->FileExists( szFileName ) )
  1229. {
  1230. // Have tga - pump in the txt file
  1231. sprintf( pExtPut, ".txt" );
  1232. CUtlBuffer bufTxtFileBuffer( 0, 0, CUtlBuffer::TEXT_BUFFER );
  1233. g_pFullFileSystem->ReadFile( szFileName, 0, bufTxtFileBuffer );
  1234. for ( int k = 0; k < 1024; ++ k ) bufTxtFileBuffer.PutChar( 0 );
  1235. // Now fix maxwidth/maxheight settings
  1236. SetBufferValue( ( char * ) bufTxtFileBuffer.Base(), "nomip", bNewNoMip ? "1" : "0" );
  1237. bufTxtFileBuffer.SeekPut( CUtlBuffer::SEEK_HEAD, strlen( ( char * ) bufTxtFileBuffer.Base() ) );
  1238. // Check out or add the file
  1239. g_p4factory->SetOpenFileChangeList( "Texture LOD Autocheckout" );
  1240. CP4AutoEditFile autop4_edit( szFileName );
  1241. // Save the file contents
  1242. if ( g_pFullFileSystem->WriteFile( szFileName, 0, bufTxtFileBuffer ) )
  1243. {
  1244. Msg(" '%s' : saved.\n", szFileName );
  1245. CP4AutoAddFile autop4_add( szFileName );
  1246. }
  1247. else
  1248. {
  1249. Warning( " '%s' : failed to save - toggle \"nomip\" manually.\n",
  1250. szFileName );
  1251. }
  1252. }
  1253. else
  1254. {
  1255. // 2.psd
  1256. sprintf( pExtPut, ".psd" );
  1257. if ( g_pFullFileSystem->FileExists( szFileName ) )
  1258. {
  1259. char chCommand[MAX_PATH];
  1260. char szTxtFileName[MAX_PATH] = {0};
  1261. GetModSubdirectory( "tmp_lod_psdinfo.txt", szTxtFileName, sizeof( szTxtFileName ) );
  1262. sprintf( chCommand, "/C psdinfo \"%s\" > \"%s\"", szFileName, szTxtFileName);
  1263. vgui::system()->ShellExecuteEx( "open", "cmd.exe", chCommand );
  1264. Sys_Sleep( 200 );
  1265. CUtlBuffer bufTxtFileBuffer( 0, 0, CUtlBuffer::TEXT_BUFFER );
  1266. g_pFullFileSystem->ReadFile( szTxtFileName, 0, bufTxtFileBuffer );
  1267. for ( int k = 0; k < 1024; ++ k ) bufTxtFileBuffer.PutChar( 0 );
  1268. // Now fix maxwidth/maxheight settings
  1269. SetBufferValue( ( char * ) bufTxtFileBuffer.Base(), "nomip", bNewNoMip ? "1" : "0" );
  1270. bufTxtFileBuffer.SeekPut( CUtlBuffer::SEEK_HEAD, strlen( ( char * ) bufTxtFileBuffer.Base() ) );
  1271. // Check out or add the file
  1272. // Save the file contents
  1273. if ( g_pFullFileSystem->WriteFile( szTxtFileName, 0, bufTxtFileBuffer ) )
  1274. {
  1275. g_p4factory->SetOpenFileChangeList( "Texture LOD Autocheckout" );
  1276. CP4AutoEditFile autop4_edit( szFileName );
  1277. sprintf( chCommand, "/C psdinfo -write \"%s\" < \"%s\"", szFileName, szTxtFileName );
  1278. Sys_Sleep( 200 );
  1279. vgui::system()->ShellExecuteEx( "open", "cmd.exe", chCommand );
  1280. Sys_Sleep( 200 );
  1281. Msg(" '%s' : saved.\n", szFileName );
  1282. CP4AutoAddFile autop4_add( szFileName );
  1283. }
  1284. else
  1285. {
  1286. Warning( " '%s' : failed to save - toggle \"nomip\" manually.\n",
  1287. szFileName );
  1288. }
  1289. }
  1290. else
  1291. {
  1292. // 3. - error
  1293. sprintf( pExtPut, "" );
  1294. Warning( " '%s' : doesn't specify a valid TGA or PSD file!\n", szFileName );
  1295. return;
  1296. }
  1297. }
  1298. // Now reload the texture
  1299. OnCommand( "RebuildVTF" );
  1300. #endif // #ifdef IS_WINDOWS_PC
  1301. }
  1302. if ( !stricmp( command, "RebuildVTF" ) )
  1303. {
  1304. #ifdef IS_WINDOWS_PC
  1305. CP4Requirement p4req;
  1306. if ( !p4 )
  1307. g_p4factory->SetDummyMode( true );
  1308. CSysModule *pModule;
  1309. IVTex *pIVTex = VTex_Load( &pModule );
  1310. if ( !pIVTex )
  1311. return;
  1312. char const *szTextureFile = m_pInfo->GetString( KEYNAME_NAME );
  1313. char szContentFilename[MAX_PATH];
  1314. if ( !GetTextureContentPath( szTextureFile, szContentFilename, sizeof(szContentFilename) ) )
  1315. return;
  1316. char pGameDir[MAX_OSPATH];
  1317. COM_GetGameDir( pGameDir, sizeof( pGameDir ) );
  1318. // Check out the VTF
  1319. char szVTFFilename[MAX_PATH];
  1320. Q_snprintf( szVTFFilename, sizeof( szVTFFilename ) - 1, "%s/materials/%s.vtf", pGameDir, szTextureFile );
  1321. g_p4factory->SetOpenFileChangeList( "Texture LOD Autocheckout" );
  1322. CP4AutoEditFile autop4_edit( szVTFFilename );
  1323. // Get the directory for the outdir
  1324. StripDirName( szVTFFilename );
  1325. // Now we've modified the source, rebuild the texture
  1326. char *argv[64];
  1327. int iArg = 0;
  1328. argv[iArg++] = "";
  1329. argv[iArg++] = "-quiet";
  1330. argv[iArg++] = "-UseStandardError"; // These are only here for the -currently released- version of vtex.dll.
  1331. argv[iArg++] = "-WarningsAsErrors";
  1332. argv[iArg++] = "-outdir";
  1333. argv[iArg++] = szVTFFilename;
  1334. argv[iArg++] = szContentFilename;
  1335. pIVTex->VTex( CubemapsFSFactory, pGameDir, iArg, argv );
  1336. VTex_Unload( pModule );
  1337. Sys_Sleep( 200 );
  1338. // Now reload the texture
  1339. OnCommand( "Reload" );
  1340. #endif // #ifdef IS_WINDOWS_PC
  1341. }
  1342. }
  1343. void CRenderTextureEditor::ApplySchemeSettings( vgui::IScheme *pScheme )
  1344. {
  1345. BaseClass::ApplySchemeSettings( pScheme );
  1346. SetFont( pScheme->GetFont( "Default", IsProportional() ) );
  1347. }
  1348. void CRenderTextureEditor::OnMousePressed( vgui::MouseCode code )
  1349. {
  1350. Close();
  1351. }
  1352. void CRenderTextureEditor::Paint()
  1353. {
  1354. CAutoMatSysDebugMode auto_matsysdebugmode;
  1355. DisableFadeEffect();
  1356. SetBgColor( Color( 10, 50, 10, 255 ) );
  1357. BaseClass::Paint();
  1358. KeyValues *kv = m_pInfo;
  1359. if ( !kv )
  1360. return;
  1361. char const *szTextureFile = kv->GetString( KEYNAME_NAME );
  1362. Q_strncpy( s_chLastViewedTextureBuffer, szTextureFile, sizeof( s_chLastViewedTextureBuffer ) );
  1363. char const *szTextureGroup = kv->GetString( KEYNAME_TEXTURE_GROUP );
  1364. ITexture *pMatTexture = NULL;
  1365. if ( *szTextureFile )
  1366. pMatTexture = materials->FindTexture( szTextureFile, szTextureGroup, false );
  1367. if ( !pMatTexture )
  1368. pMatTexture = materials->FindTexture( "debugempty", "", false );
  1369. // Determine the texture size
  1370. int iTxWidth = kv->GetInt( KEYNAME_WIDTH );
  1371. int iTxHeight = kv->GetInt( KEYNAME_HEIGHT );
  1372. int iTxSize = kv->GetInt( KEYNAME_SIZE );
  1373. char const *szTxFormat = kv->GetString( KEYNAME_FORMAT );
  1374. int x = TILE_BORDER, y = TILE_BORDER;
  1375. // Dimensions to draw
  1376. int iDrawWidth = iTxWidth;
  1377. int iDrawHeight = iTxHeight;
  1378. if ( pMatTexture && pMatTexture->IsCubeMap() )
  1379. {
  1380. iDrawWidth = 1024;
  1381. iDrawHeight = 1024;
  1382. }
  1383. if ( iDrawHeight >= iDrawWidth )
  1384. {
  1385. if ( iDrawHeight > TILE_TEXTURE_SIZE )
  1386. {
  1387. iDrawWidth = iDrawWidth * ( float( TILE_TEXTURE_SIZE ) / iDrawHeight );
  1388. iDrawHeight = TILE_TEXTURE_SIZE;
  1389. }
  1390. if ( iDrawHeight < 64 )
  1391. {
  1392. iDrawWidth = iDrawWidth * ( float( 64 ) / iDrawHeight );
  1393. iDrawHeight = 64;
  1394. }
  1395. }
  1396. else
  1397. {
  1398. if ( iDrawWidth > TILE_TEXTURE_SIZE )
  1399. {
  1400. iDrawHeight = iDrawHeight * ( float( TILE_TEXTURE_SIZE ) / iDrawWidth );
  1401. iDrawWidth = TILE_TEXTURE_SIZE;
  1402. }
  1403. if ( iDrawWidth < 64 )
  1404. {
  1405. iDrawHeight = iDrawHeight * ( float( 64 ) / iDrawWidth );
  1406. iDrawWidth = 64;
  1407. }
  1408. }
  1409. iDrawHeight = iDrawHeight / ( float( TILE_TEXTURE_SIZE ) / float( TILE_SIZE ) );
  1410. iDrawWidth = iDrawWidth / ( float( TILE_TEXTURE_SIZE ) / float( TILE_SIZE ) );
  1411. iDrawHeight = max( iDrawHeight, 4 );
  1412. iDrawWidth = max( iDrawWidth, 4 );
  1413. //
  1414. // Draw frame
  1415. //
  1416. {
  1417. int tileWidth = 2 * TILE_BORDER + TILE_SIZE;
  1418. int tileHeight = 3 * TILE_BORDER + TILE_SIZE + TILE_TEXT;
  1419. g_pMatSystemSurface->DrawSetColor( 255, 255, 255, 255 );
  1420. g_pMatSystemSurface->DrawOutlinedRect( x + 1, y + 1,
  1421. x + tileWidth - 2 , y + tileHeight - 2 );
  1422. }
  1423. //
  1424. // Draw all
  1425. //
  1426. x += TILE_BORDER;
  1427. y += TILE_BORDER;
  1428. char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
  1429. Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vtf", szTextureFile );
  1430. char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
  1431. char const *szPrintFilePrefix = szResolvedName ? "" : "[?]/";
  1432. char const *szPrintFileName = szResolvedName ? szResolvedName : szTextureFile;
  1433. char chSizeBuf[20] = { 0 };
  1434. if ( iTxSize >= 0 )
  1435. FmtCommaNumber( chSizeBuf, iTxSize );
  1436. else
  1437. chSizeBuf[0] = '-';
  1438. g_pMatSystemSurface->DrawColoredTextRect( GetFont(), x, y, TILE_SIZE, TILE_TEXT / 2,
  1439. 255, 255, 255, 255,
  1440. "%s%s\n"
  1441. "%s Kb %dx%d %s",
  1442. szPrintFilePrefix, szPrintFileName,
  1443. chSizeBuf,
  1444. iTxWidth, iTxHeight,
  1445. szTxFormat
  1446. );
  1447. if ( !m_bufInfoText.TellPut() )
  1448. {
  1449. m_bufInfoText.Printf(
  1450. "%s%s\r\n"
  1451. "%s Kb %dx%d %s",
  1452. szPrintFilePrefix, szPrintFileName,
  1453. chSizeBuf,
  1454. iTxWidth, iTxHeight,
  1455. szTxFormat );
  1456. }
  1457. if ( !kv->GetInt( "SpecialTx" ) )
  1458. {
  1459. char chLine1[256] = {0};
  1460. char chLine2[256] = {0};
  1461. //
  1462. // Line 1
  1463. //
  1464. if ( iTxSize > g_warn_texkbytes )
  1465. sprintf( chLine1 + strlen( chLine1 ), " Size(%s Kb)", chSizeBuf );
  1466. if ( ( iTxWidth > g_warn_texdimensions ) ||
  1467. ( iTxHeight > g_warn_texdimensions ) )
  1468. sprintf( chLine1 + strlen( chLine1 ), " Dimensions(%dx%d)", iTxWidth, iTxHeight );
  1469. if ( stricmp( szTxFormat, "DXT1" ) &&
  1470. stricmp( szTxFormat, "DXT5" ) )
  1471. sprintf( chLine1 + strlen( chLine1 ), " Format(%s)", szTxFormat );
  1472. if ( pMatTexture->GetFlags() & TEXTUREFLAGS_NOLOD )
  1473. sprintf( chLine1 + strlen( chLine1 ), " NoLod" );
  1474. if ( pMatTexture->GetFlags() & TEXTUREFLAGS_NOMIP )
  1475. sprintf( chLine1 + strlen( chLine1 ), " NoMip" );
  1476. if ( pMatTexture->GetFlags() & TEXTUREFLAGS_ONEBITALPHA )
  1477. sprintf( chLine1 + strlen( chLine1 ), " OneBitAlpha" );
  1478. //
  1479. // Line 2
  1480. //
  1481. // Always show stats for higher/lower mips
  1482. {
  1483. int wmap = pMatTexture->GetMappingWidth(), hmap = pMatTexture->GetMappingHeight(), dmap = pMatTexture->GetMappingDepth();
  1484. int wact = pMatTexture->GetActualWidth(), hact = pMatTexture->GetActualHeight(), dact = pMatTexture->GetActualDepth();
  1485. ImageFormat fmt = pMatTexture->GetImageFormat();
  1486. if ( wact > 4 || hact > 4 )
  1487. {
  1488. char chbuf[50];
  1489. int mem = ImageLoader::GetMemRequired( max( min( wact, 4 ), wact / 2 ), max( min( hact, 4 ), hact / 2 ), max( 1, dact / 2 ), fmt, true );
  1490. mem = ( mem + 511 ) / 1024;
  1491. FmtCommaNumber( chbuf, mem );
  1492. sprintf ( chLine2 + strlen( chLine2 ), " %s Kb @ lower mip", chbuf );
  1493. }
  1494. if ( wmap > wact || hmap > hact || dmap > dact )
  1495. {
  1496. char chbuf[ 50 ];
  1497. int mem = ImageLoader::GetMemRequired( min( wmap, wact * 2 ), min( hmap, hact * 2 ), min( dmap, dact * 2 ), fmt, true );
  1498. mem = ( mem + 511 ) / 1024;
  1499. FmtCommaNumber( chbuf, mem );
  1500. sprintf ( chLine2 + strlen( chLine2 ), " %s Kb @ higher mip", chbuf );
  1501. }
  1502. }
  1503. if ( chLine1[0] )
  1504. {
  1505. g_pMatSystemSurface->DrawSetColor( 200, 0, 0, 255 );
  1506. g_pMatSystemSurface->DrawFilledRect( x - TILE_BORDER/2, y + TILE_TEXT/2, x + TILE_BORDER/2 + (TILE_SIZE * 0.5), y + TILE_TEXT/2 + TILE_TEXT/4 );
  1507. g_pMatSystemSurface->DrawColoredTextRect( GetFont(), x, y + TILE_TEXT/2, TILE_SIZE, TILE_TEXT / 4,
  1508. 255, 255, 255, 255,
  1509. "%s", chLine1 );
  1510. }
  1511. if ( chLine2[0] )
  1512. {
  1513. // g_pMatSystemSurface->DrawSetColor( 200, 0, 0, 255 );
  1514. // g_pMatSystemSurface->DrawFilledRect( x - TILE_BORDER/2, y + TILE_TEXT/2 + TILE_TEXT/4, x + TILE_BORDER/2 + TILE_SIZE, y + TILE_TEXT );
  1515. g_pMatSystemSurface->DrawColoredTextRect( GetFont(), x, y + TILE_TEXT/2 + TILE_TEXT/4, TILE_SIZE, TILE_TEXT / 4,
  1516. 255, 255, 255, 255,
  1517. "%s", chLine2 );
  1518. }
  1519. }
  1520. y += TILE_TEXT + TILE_BORDER;
  1521. // Images placement
  1522. bool bHasAlpha = !!stricmp( szTxFormat, "DXT1" );
  1523. int extTxWidth = TILE_SIZE;
  1524. int extTxHeight = TILE_SIZE;
  1525. int orgTxX = 0, orgTxXA = 0;
  1526. int orgTxY = 0, orgTxYA = 0;
  1527. if ( bHasAlpha )
  1528. {
  1529. if ( iTxWidth >= iTxHeight * 2 )
  1530. {
  1531. extTxHeight /= 2;
  1532. orgTxYA = extTxHeight + TILE_BORDER/2;
  1533. extTxHeight -= 1;
  1534. }
  1535. else if ( iTxHeight >= iTxWidth * 2 )
  1536. {
  1537. extTxWidth /= 2;
  1538. orgTxXA = extTxWidth + TILE_BORDER/2;
  1539. extTxWidth -= 3;
  1540. }
  1541. else
  1542. {
  1543. extTxHeight /= 2;
  1544. orgTxYA = extTxHeight + TILE_BORDER/2;
  1545. orgTxX = extTxWidth / 4;
  1546. extTxWidth /= 2;
  1547. if ( iDrawWidth > extTxWidth )
  1548. {
  1549. iDrawWidth /= 2;
  1550. iDrawHeight /= 2;
  1551. }
  1552. extTxWidth -= 1;
  1553. extTxHeight -= 1;
  1554. }
  1555. }
  1556. enum { IMG_FRAME_OFF = 2 };
  1557. if ( IMaterial *pMaterial = UseDebugMaterial( "debug/debugtexturecolor", pMatTexture, &auto_matsysdebugmode ) )
  1558. {
  1559. g_pMatSystemSurface->DrawSetColor( 255, 255, 255, 255 );
  1560. g_pMatSystemSurface->DrawOutlinedRect( x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
  1561. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
  1562. RenderTexturedRect( this, pMaterial,
  1563. x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
  1564. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 );
  1565. if ( bHasAlpha )
  1566. {
  1567. orgTxX += orgTxXA;
  1568. orgTxY += orgTxYA;
  1569. if ( IMaterial *pMaterialDebug = UseDebugMaterial( "debug/debugtexturealpha", pMatTexture, &auto_matsysdebugmode ) )
  1570. {
  1571. g_pMatSystemSurface->DrawOutlinedRect( x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
  1572. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
  1573. RenderTexturedRect( this, pMaterialDebug,
  1574. x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
  1575. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 );
  1576. }
  1577. }
  1578. }
  1579. else
  1580. {
  1581. g_pMatSystemSurface->DrawSetColor( 255, 0, 255, 100 );
  1582. g_pMatSystemSurface->DrawFilledRect(
  1583. x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxWidth - iDrawHeight ) / 2,
  1584. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxWidth + iDrawHeight ) / 2 );
  1585. }
  1586. y += TILE_SIZE + TILE_BORDER;
  1587. }
  1588. //////////////////////////////////////////////////////////////////////////
  1589. //
  1590. // Render textures view panel
  1591. //
  1592. //////////////////////////////////////////////////////////////////////////
  1593. class CRenderTexturesListViewPanel : public vgui::TileViewPanelEx
  1594. {
  1595. DECLARE_CLASS_SIMPLE( CRenderTexturesListViewPanel, vgui::TileViewPanelEx );
  1596. public:
  1597. CRenderTexturesListViewPanel( vgui::Panel *parent, char const *szName );
  1598. ~CRenderTexturesListViewPanel();
  1599. protected:
  1600. virtual int GetNumTiles();
  1601. virtual void GetTileSize( int &wide, int &tall );
  1602. virtual void RenderTile( int iTile, int x, int y );
  1603. protected:
  1604. virtual void PerformLayout();
  1605. virtual void OnMousePressed( vgui::MouseCode code );
  1606. virtual void OnMouseDoublePressed( vgui::MouseCode code ) { OnMousePressed( code ); }
  1607. public:
  1608. void SetDataListPanel( vgui::ListPanel *pPanel );
  1609. void SetPaintAlpha( bool bPaintAlpha );
  1610. CRenderTextureEditor * GetRenderTxEditor() const { return m_pRenderTxEditor; }
  1611. protected:
  1612. vgui::ListPanel *m_pListPanel;
  1613. KeyValues * GetTileData( int iTile );
  1614. protected:
  1615. CRenderTextureEditor *m_pRenderTxEditor;
  1616. protected:
  1617. enum
  1618. {
  1619. TILE_BORDER = 20,
  1620. TILE_SIZE = 192,
  1621. TILE_TEXTURE_SIZE = 256,
  1622. TILE_TEXT = 35
  1623. };
  1624. bool m_bPaintAlpha;
  1625. };
  1626. CRenderTexturesListViewPanel::CRenderTexturesListViewPanel( vgui::Panel *parent, char const *szName ) :
  1627. vgui::TileViewPanelEx( parent, szName ),
  1628. m_pListPanel( NULL ),
  1629. m_bPaintAlpha( false )
  1630. {
  1631. m_pRenderTxEditor = new CRenderTextureEditor( this, "TxEdt" );
  1632. m_pRenderTxEditor->SetPos( 10, 10 );
  1633. m_pRenderTxEditor->PerformLayout();
  1634. m_pRenderTxEditor->SetMoveable( true );
  1635. m_pRenderTxEditor->SetSizeable( false );
  1636. m_pRenderTxEditor->SetClipToParent( true );
  1637. m_pRenderTxEditor->SetTitle( "", true );
  1638. m_pRenderTxEditor->SetCloseButtonVisible( false );
  1639. m_pRenderTxEditor->SetVisible( false );
  1640. }
  1641. CRenderTexturesListViewPanel::~CRenderTexturesListViewPanel()
  1642. {
  1643. NULL;
  1644. }
  1645. void CRenderTexturesListViewPanel::PerformLayout()
  1646. {
  1647. BaseClass::PerformLayout();
  1648. }
  1649. void CRenderTexturesListViewPanel::OnMousePressed( vgui::MouseCode code )
  1650. {
  1651. BaseClass::OnMousePressed( code );
  1652. // Figure out which tile got hit and pass its data for preview
  1653. m_pRenderTxEditor->Close();
  1654. if ( !m_pListPanel )
  1655. return;
  1656. int x, y;
  1657. vgui::input()->GetCursorPos( x, y );
  1658. this->ScreenToLocal( x, y );
  1659. // Hit test the click
  1660. int iTile, tileX, tileY;
  1661. int htResult = HitTest( x, y, iTile );
  1662. if ( HT_NOTHING == htResult )
  1663. return;
  1664. if ( !GetTileOrg( iTile, tileX, tileY ) )
  1665. return;
  1666. // Now having the tile retrieve the keyvalues
  1667. int itemId = m_pListPanel->GetItemIDFromRow( iTile );
  1668. if ( itemId < 0 )
  1669. return;
  1670. KeyValues *kv = m_pListPanel->GetItem( itemId );
  1671. if ( !kv )
  1672. return;
  1673. // Display the tx editor
  1674. m_pRenderTxEditor->SetDispInfo( kv, itemId );
  1675. if ( tileX + m_pRenderTxEditor->GetWide() > m_li_wide - 2 )
  1676. tileX -= tileX + m_pRenderTxEditor->GetWide() - ( m_li_wide - 2 );
  1677. if ( tileY + m_pRenderTxEditor->GetTall() > m_li_tall - 2 )
  1678. tileY -= tileY + m_pRenderTxEditor->GetTall() - ( m_li_tall - 2 );
  1679. int iTopLeftX = 0, iTopLeftY = 0;
  1680. for ( vgui::Panel *pPanel = this; ( pPanel = pPanel->GetParent() ) != NULL; )
  1681. {
  1682. iTopLeftX = iTopLeftY = 0;
  1683. pPanel->LocalToScreen( iTopLeftX, iTopLeftY );
  1684. }
  1685. LocalToScreen( tileX, tileY );
  1686. if ( tileX < iTopLeftX ) tileX = iTopLeftX;
  1687. if ( tileY < iTopLeftY ) tileY = iTopLeftY;
  1688. m_pRenderTxEditor->SetPos( tileX, tileY );
  1689. m_pRenderTxEditor->Activate();
  1690. }
  1691. int CRenderTexturesListViewPanel::GetNumTiles()
  1692. {
  1693. return m_pListPanel ? m_pListPanel->GetItemCount() : 0;
  1694. }
  1695. void CRenderTexturesListViewPanel::GetTileSize( int &wide, int &tall )
  1696. {
  1697. wide = 2 * TILE_BORDER + TILE_SIZE;
  1698. tall = 2 * TILE_BORDER + TILE_SIZE + TILE_TEXT;
  1699. };
  1700. KeyValues * CRenderTexturesListViewPanel::GetTileData( int iTile )
  1701. {
  1702. int iData = m_pListPanel->GetItemIDFromRow( iTile );
  1703. if ( iData < 0 )
  1704. return NULL;
  1705. return m_pListPanel->GetItem( iData );
  1706. }
  1707. void CRenderTexturesListViewPanel::RenderTile( int iTile, int x, int y )
  1708. {
  1709. CAutoMatSysDebugMode auto_matsysdebugmode;
  1710. KeyValues *kv = GetTileData( iTile );
  1711. if ( !kv )
  1712. return;
  1713. char const *szTextureFile = kv->GetString( KEYNAME_NAME );
  1714. char const *szTextureGroup = kv->GetString( KEYNAME_TEXTURE_GROUP );
  1715. ITexture *pMatTexture = NULL;
  1716. if ( *szTextureFile )
  1717. pMatTexture = materials->FindTexture( szTextureFile, szTextureGroup, false );
  1718. if ( !pMatTexture )
  1719. pMatTexture = materials->FindTexture( "debugempty", "", false );
  1720. // Determine the texture size
  1721. int iTxWidth = kv->GetInt( KEYNAME_WIDTH );
  1722. int iTxHeight = kv->GetInt( KEYNAME_HEIGHT );
  1723. int iTxSize = kv->GetInt( KEYNAME_SIZE );
  1724. char const *szTxFormat = kv->GetString( KEYNAME_FORMAT );
  1725. int iTxFormatLen = strlen( szTxFormat );
  1726. char *szTxFormatSuffix = "";
  1727. if ( iTxFormatLen > 4 )
  1728. {
  1729. fmtlenreduce:
  1730. switch ( szTxFormat[ iTxFormatLen - 1 ] )
  1731. {
  1732. case '8':
  1733. {
  1734. while ( ( iTxFormatLen > 4 ) &&
  1735. ( szTxFormat[ iTxFormatLen - 2 ] == '8' ) )
  1736. -- iTxFormatLen;
  1737. }
  1738. break;
  1739. case '6':
  1740. {
  1741. while ( ( iTxFormatLen > 4 ) &&
  1742. ( szTxFormat[ iTxFormatLen - 2 ] == '1' ) &&
  1743. ( szTxFormat[ iTxFormatLen - 3 ] == '6' ) )
  1744. iTxFormatLen -= 2;
  1745. }
  1746. break;
  1747. case 'F':
  1748. if ( !*szTxFormatSuffix )
  1749. {
  1750. iTxFormatLen --;
  1751. szTxFormatSuffix = "F";
  1752. goto fmtlenreduce;
  1753. }
  1754. break;
  1755. }
  1756. }
  1757. // Dimensions to draw
  1758. int iDrawWidth = iTxWidth;
  1759. int iDrawHeight = iTxHeight;
  1760. if ( pMatTexture && pMatTexture->IsCubeMap() )
  1761. {
  1762. iDrawWidth = 1024;
  1763. iDrawHeight = 1024;
  1764. }
  1765. if ( iDrawHeight >= iDrawWidth )
  1766. {
  1767. if ( iDrawHeight > TILE_TEXTURE_SIZE )
  1768. {
  1769. iDrawWidth = iDrawWidth * ( float( TILE_TEXTURE_SIZE ) / iDrawHeight );
  1770. iDrawHeight = TILE_TEXTURE_SIZE;
  1771. }
  1772. if ( iDrawHeight < 64 )
  1773. {
  1774. iDrawWidth = iDrawWidth * ( float( 64 ) / iDrawHeight );
  1775. iDrawHeight = 64;
  1776. }
  1777. }
  1778. else
  1779. {
  1780. if ( iDrawWidth > TILE_TEXTURE_SIZE )
  1781. {
  1782. iDrawHeight = iDrawHeight * ( float( TILE_TEXTURE_SIZE ) / iDrawWidth );
  1783. iDrawWidth = TILE_TEXTURE_SIZE;
  1784. }
  1785. if ( iDrawWidth < 64 )
  1786. {
  1787. iDrawHeight = iDrawHeight * ( float( 64 ) / iDrawWidth );
  1788. iDrawWidth = 64;
  1789. }
  1790. }
  1791. iDrawHeight = iDrawHeight / ( float( TILE_TEXTURE_SIZE ) / float( TILE_SIZE ) );
  1792. iDrawWidth = iDrawWidth / ( float( TILE_TEXTURE_SIZE ) / float( TILE_SIZE ) );
  1793. iDrawHeight = max( iDrawHeight, 4 );
  1794. iDrawWidth = max( iDrawWidth, 4 );
  1795. //
  1796. // Draw frame
  1797. //
  1798. {
  1799. int tileWidth, tileHeight;
  1800. GetTileSize( tileWidth, tileHeight );
  1801. g_pMatSystemSurface->DrawSetColor( 255, 255, 255, 255 );
  1802. g_pMatSystemSurface->DrawOutlinedRect( x + 1, y + 1,
  1803. x + tileWidth - 2 , y + tileHeight - 2 );
  1804. }
  1805. //
  1806. // Draw all
  1807. //
  1808. x += TILE_BORDER;
  1809. y += TILE_BORDER/2;
  1810. int iLenFile = strlen( szTextureFile );
  1811. char const *szPrintFilePrefix = ( iLenFile > 22 ) ? "..." : "";
  1812. char const *szPrintFileName = ( iLenFile > 22 ) ? ( szTextureFile + iLenFile - 22 ) : szTextureFile;
  1813. char chSizeBuf[20] = {0};
  1814. if ( iTxSize >= 0 )
  1815. {
  1816. FmtCommaNumber( chSizeBuf, iTxSize );
  1817. }
  1818. else
  1819. {
  1820. chSizeBuf[0] = '-';
  1821. }
  1822. static Color clrLblNormal( 25, 50, 25, 255 );
  1823. static Color clrLblWarn( 75, 75, 0, 255 );
  1824. static Color clrLblError( 200, 0, 0, 255 );
  1825. bool bWarnTile = ( !kv->GetInt( "SpecialTx" ) ) && ( g_warn_enable && ShallWarnTx( kv, pMatTexture ) );
  1826. g_pMatSystemSurface->DrawSetColor( bWarnTile ? clrLblWarn : clrLblNormal );
  1827. g_pMatSystemSurface->DrawFilledRect( x - TILE_BORDER/2, y, x + TILE_BORDER/2 + TILE_SIZE, y + TILE_TEXT );
  1828. char chInfoText[256] = { 0 };
  1829. sprintf( chInfoText, "%s Kb %dx%d %.*s%s %s",
  1830. chSizeBuf,
  1831. iTxWidth, iTxHeight,
  1832. iTxFormatLen, szTxFormat, szTxFormatSuffix,
  1833. ( pMatTexture->GetFlags() & (
  1834. TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_ONEBITALPHA
  1835. ) ) ? "***" : "" );
  1836. int iTextMargins[4] = { 0 };
  1837. int iTextHeight = g_pMatSystemSurface->GetFontTall( GetFont() );
  1838. {
  1839. // Compute text extents
  1840. int iTextLen[4] = { 0 };
  1841. iTextLen[0] = 5 + strlen( chSizeBuf );
  1842. iTextLen[1] = strchr( chInfoText, 'x' ) + 1 - chInfoText;
  1843. while ( chInfoText[ iTextLen[1] ] != ' ' )
  1844. ++ iTextLen[1];
  1845. ++ iTextLen[1];
  1846. iTextLen[2] = 2 + iTextLen[1] + iTxFormatLen + strlen( szTxFormatSuffix );
  1847. iTextLen[3] = strlen( chInfoText );
  1848. for ( int k = 0; k < 4; ++ k )
  1849. iTextMargins[k] = g_pMatSystemSurface->DrawTextLen( GetFont(), "%.*s", iTextLen[k], chInfoText );
  1850. }
  1851. // Highlights
  1852. if ( bWarnTile )
  1853. {
  1854. g_pMatSystemSurface->DrawSetColor( clrLblError );
  1855. if ( iTxSize > g_warn_texkbytes )
  1856. g_pMatSystemSurface->DrawFilledRect( x - 2, y + iTextHeight + 1, x + iTextMargins[0] - 5, y + TILE_TEXT );
  1857. if ( iTxWidth > g_warn_texdimensions || iTxHeight > g_warn_texdimensions )
  1858. g_pMatSystemSurface->DrawFilledRect( x + iTextMargins[0] - 2, y + iTextHeight + 1, x + iTextMargins[1] - 1, y + TILE_TEXT );
  1859. if ( strcmp( szTxFormat, "DXT1" ) && strcmp( szTxFormat, "DXT5" ) )
  1860. g_pMatSystemSurface->DrawFilledRect( x + iTextMargins[1] + 2, y + iTextHeight + 1, x + iTextMargins[2] - 1, y + TILE_TEXT );
  1861. if ( pMatTexture->GetFlags() & (
  1862. TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_ONEBITALPHA
  1863. ) )
  1864. g_pMatSystemSurface->DrawFilledRect( x + iTextMargins[2] + 3, y + iTextHeight + 1, x + iTextMargins[3] + 2, y + TILE_TEXT );
  1865. }
  1866. g_pMatSystemSurface->DrawColoredTextRect( GetFont(), x, y, TILE_SIZE, TILE_TEXT,
  1867. 255, 255, 255, 255,
  1868. "%s%s\n"
  1869. "%s",
  1870. szPrintFilePrefix, szPrintFileName,
  1871. chInfoText
  1872. );
  1873. y += TILE_TEXT + TILE_BORDER/2;
  1874. // Images placement
  1875. bool bHasAlpha = m_bPaintAlpha && stricmp( szTxFormat, "DXT1" );
  1876. int extTxWidth = TILE_SIZE;
  1877. int extTxHeight = TILE_SIZE;
  1878. int orgTxX = 0, orgTxXA = 0;
  1879. int orgTxY = 0, orgTxYA = 0;
  1880. if ( bHasAlpha )
  1881. {
  1882. if ( iTxWidth >= iTxHeight * 2 )
  1883. {
  1884. extTxHeight /= 2;
  1885. orgTxYA = extTxHeight + TILE_BORDER/2;
  1886. }
  1887. else if ( iTxHeight >= iTxWidth * 2 )
  1888. {
  1889. extTxWidth /= 2;
  1890. orgTxXA = extTxWidth + TILE_BORDER/2;
  1891. x -= TILE_BORDER/4 + 1;
  1892. }
  1893. else
  1894. {
  1895. extTxHeight /= 2;
  1896. orgTxYA = extTxHeight + TILE_BORDER/2;
  1897. orgTxX = extTxWidth / 4;
  1898. extTxWidth /= 2;
  1899. x -= TILE_BORDER/4 + 1;
  1900. if ( iDrawWidth > extTxWidth )
  1901. {
  1902. iDrawWidth /= 2;
  1903. iDrawHeight /= 2;
  1904. }
  1905. }
  1906. }
  1907. enum { IMG_FRAME_OFF = 2 };
  1908. if ( IMaterial *pMaterial = UseDebugMaterial( "debug/debugtexturecolor", pMatTexture, &auto_matsysdebugmode ) )
  1909. {
  1910. g_pMatSystemSurface->DrawSetColor( 255, 255, 255, 255 );
  1911. g_pMatSystemSurface->DrawOutlinedRect( x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
  1912. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
  1913. RenderTexturedRect( this, pMaterial,
  1914. x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
  1915. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2,
  1916. 2, 1 );
  1917. if ( bHasAlpha )
  1918. {
  1919. orgTxX += orgTxXA;
  1920. orgTxY += orgTxYA;
  1921. if ( IMaterial *pMaterialDebug = UseDebugMaterial( "debug/debugtexturealpha", pMatTexture, &auto_matsysdebugmode ) )
  1922. {
  1923. g_pMatSystemSurface->DrawOutlinedRect( x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
  1924. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
  1925. RenderTexturedRect( this, pMaterialDebug,
  1926. x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
  1927. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2,
  1928. 2, 1 );
  1929. }
  1930. }
  1931. }
  1932. else
  1933. {
  1934. g_pMatSystemSurface->DrawSetColor( 255, 0, 255, 100 );
  1935. g_pMatSystemSurface->DrawFilledRect(
  1936. x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxWidth - iDrawHeight ) / 2,
  1937. x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxWidth + iDrawHeight ) / 2 );
  1938. }
  1939. y += TILE_SIZE + TILE_BORDER;
  1940. }
  1941. void CRenderTexturesListViewPanel::SetDataListPanel( vgui::ListPanel *pPanel )
  1942. {
  1943. m_pListPanel = pPanel;
  1944. InvalidateLayout();
  1945. }
  1946. void CRenderTexturesListViewPanel::SetPaintAlpha( bool bPaintAlpha )
  1947. {
  1948. m_bPaintAlpha = bPaintAlpha;
  1949. Repaint();
  1950. }
  1951. //-----------------------------------------------------------------------------
  1952. // Purpose: Shows entity status report if cl_entityreport cvar is set
  1953. //-----------------------------------------------------------------------------
  1954. class CTextureListPanel : public vgui::Frame
  1955. {
  1956. DECLARE_CLASS_SIMPLE( CTextureListPanel, vgui::Frame );
  1957. public:
  1958. // Construction
  1959. CTextureListPanel( vgui::Panel *parent );
  1960. virtual ~CTextureListPanel( void );
  1961. // Refresh
  1962. virtual void Paint();
  1963. void EndPaint(); // Still inside paint
  1964. virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
  1965. virtual bool ShouldDraw();
  1966. virtual void PerformLayout();
  1967. virtual void Close();
  1968. void OnTurnedOn();
  1969. private:
  1970. void UpdateTotalUsageLabel();
  1971. virtual void OnCommand( const char *command );
  1972. MESSAGE_FUNC( OnTextChanged, "TextChanged" );
  1973. int AddListItem( KeyValues *kv );
  1974. bool UpdateDisplayedItem( KeyValues *pDispData, KeyValues *kv );
  1975. private:
  1976. // Font to use for drawing
  1977. vgui::HFont m_hFont;
  1978. vgui::ListPanel *m_pListPanel;
  1979. CRenderTexturesListViewPanel *m_pViewPanel;
  1980. vgui::CheckButton *m_pSpecialTexs;
  1981. vgui::CheckButton *m_pResolveTexturePath;
  1982. CConVarCheckButton *m_pShowTextureMemoryUsageOption;
  1983. CConVarCheckButton *m_pAllTextures;
  1984. CConVarCheckButton *m_pViewTextures;
  1985. vgui::Button *m_pCopyToClipboardButton;
  1986. vgui::ToggleButton *m_pCollapse;
  1987. vgui::CheckButton *m_pAlpha;
  1988. vgui::CheckButton *m_pThumbWarnings;
  1989. vgui::CheckButton *m_pHideMipped;
  1990. vgui::CheckButton *m_pFilteringChk;
  1991. vgui::TextEntry *m_pFilteringText;
  1992. int m_numDisplayedSizeKB;
  1993. vgui::Button *m_pReloadAllMaterialsButton;
  1994. vgui::Button *m_pCommitChangesButton;
  1995. vgui::Button *m_pDiscardChangesButton;
  1996. vgui::Label *m_pCVarListLabel;
  1997. vgui::Label *m_pTotalUsageLabel;
  1998. };
  1999. static int __cdecl KilobytesSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
  2000. {
  2001. // Reverse sort order so the bigger textures show up first
  2002. const char *string1 = item1.kv->GetString( KEYNAME_SIZE );
  2003. const char *string2 = item2.kv->GetString( KEYNAME_SIZE );
  2004. int a = atoi( string1 );
  2005. int b = atoi( string2 );
  2006. if( a < b )
  2007. {
  2008. return 1;
  2009. }
  2010. if( a > b )
  2011. {
  2012. return -1;
  2013. }
  2014. return 0;
  2015. }
  2016. //
  2017. // Smart texture list
  2018. //
  2019. class CSmartTextureKeyValues
  2020. {
  2021. private:
  2022. CSmartTextureKeyValues( CSmartTextureKeyValues const &x );
  2023. CSmartTextureKeyValues& operator = ( CSmartTextureKeyValues const &x );
  2024. public:
  2025. CSmartTextureKeyValues() : m_p( NULL ) { if ( KeyValues *p = g_pMaterialSystemDebugTextureInfo->GetDebugTextureList() ) m_p = p->MakeCopy(); }
  2026. ~CSmartTextureKeyValues() { if ( m_p ) m_p->deleteThis(); m_p = NULL; }
  2027. KeyValues * Get() const { return m_p; };
  2028. protected:
  2029. KeyValues *m_p;
  2030. };
  2031. //-----------------------------------------------------------------------------
  2032. // Purpose: Instances the entity report panel
  2033. // Input : *parent -
  2034. //-----------------------------------------------------------------------------
  2035. CTextureListPanel::CTextureListPanel( vgui::Panel *parent ) :
  2036. BaseClass( parent, "CTextureListPanel" ),
  2037. m_numDisplayedSizeKB( 0 )
  2038. {
  2039. // Need parent here, before loading up textures, so getSurfaceBase
  2040. // will work on this panel ( it's null otherwise )
  2041. SetSize( videomode->GetModeStereoWidth() - 20, videomode->GetModeStereoHeight() - 20 );
  2042. SetPos( 10, 10 );
  2043. SetVisible( true );
  2044. SetCursor( null );
  2045. SetTitle( "Texture list", false );
  2046. SetMenuButtonVisible( false );
  2047. m_hFont = vgui::INVALID_FONT;
  2048. SetFgColor( Color( 0, 0, 0, 255 ) );
  2049. SetPaintBackgroundEnabled( true );
  2050. // Init the buttons.
  2051. m_pCVarListLabel = vgui::SETUP_PANEL( new vgui::Label( this, "m_pCVarListLabel",
  2052. "cvars: mat_texture_limit, mat_texture_list, mat_picmip, mat_texture_list_txlod, mat_texture_list_txlod_sync" ) );
  2053. m_pCVarListLabel->SetVisible( false ); // m_pCVarListLabel->SetVisible( true );
  2054. m_pTotalUsageLabel = vgui::SETUP_PANEL( new vgui::Label( this, "m_pTotalUsageLabel", "" ) );
  2055. m_pTotalUsageLabel->SetVisible( true );
  2056. m_pSpecialTexs = vgui::SETUP_PANEL( new vgui::CheckButton( this, "service", "Render Targets and Special Textures" ) );
  2057. m_pSpecialTexs->SetVisible( true );
  2058. m_pSpecialTexs->AddActionSignalTarget( this );
  2059. m_pSpecialTexs->SetCommand( "service" );
  2060. m_pResolveTexturePath = vgui::SETUP_PANEL( new vgui::CheckButton( this, "resolvepath", "Resolve Full Texture Path" ) );
  2061. m_pResolveTexturePath->SetVisible( true );
  2062. m_pResolveTexturePath->AddActionSignalTarget( this );
  2063. m_pResolveTexturePath->SetCommand( "resolvepath" );
  2064. m_pShowTextureMemoryUsageOption = vgui::SETUP_PANEL( new CConVarCheckButton( this, "m_pShowTextureMemoryUsageOption", "Show Memory Usage on HUD" ) );
  2065. m_pShowTextureMemoryUsageOption->SetVisible( true );
  2066. m_pShowTextureMemoryUsageOption->SetConVar( &mat_show_texture_memory_usage );
  2067. m_pAllTextures = vgui::SETUP_PANEL( new CConVarCheckButton( this, "m_pAllTextures", "Show ALL textures" ) );
  2068. m_pAllTextures->SetVisible( true );
  2069. m_pAllTextures->SetConVar( &mat_texture_list_all );
  2070. m_pAllTextures->AddActionSignalTarget( this );
  2071. m_pAllTextures->SetCommand( "AllTextures" );
  2072. m_pViewTextures = vgui::SETUP_PANEL( new CConVarCheckButton( this, "m_pViewTextures", "View textures thumbnails" ) );
  2073. m_pViewTextures->SetVisible( true );
  2074. m_pViewTextures->SetConVar( &mat_texture_list_view );
  2075. m_pViewTextures->AddActionSignalTarget( this );
  2076. m_pViewTextures->SetCommand( "ViewThumbnails" );
  2077. m_pCopyToClipboardButton = vgui::SETUP_PANEL( new vgui::Button( this, "CopyToClipboard", "Copy to Clipboard" ) );
  2078. if ( m_pCopyToClipboardButton )
  2079. {
  2080. m_pCopyToClipboardButton->AddActionSignalTarget( this );
  2081. m_pCopyToClipboardButton->SetCommand( COPYTOCLIPBOARD_CMDNAME );
  2082. }
  2083. m_pCollapse = vgui::SETUP_PANEL( new vgui::ToggleButton( this, "Collapse", " " ) );
  2084. m_pCollapse->AddActionSignalTarget( this );
  2085. m_pCollapse->SetCommand( "Collapse" );
  2086. m_pCollapse->SetSelected( true );
  2087. m_pAlpha = vgui::SETUP_PANEL( new vgui::CheckButton( this, "ShowAlpha", "Alpha" ) );
  2088. m_pAlpha->AddActionSignalTarget( this );
  2089. m_pAlpha->SetCommand( "ShowAlpha" );
  2090. bool bDefaultTxAlphaOn = true;
  2091. m_pAlpha->SetSelected( bDefaultTxAlphaOn );
  2092. m_pThumbWarnings = vgui::SETUP_PANEL( new vgui::CheckButton( this, "ThumbWarnings", "Warns" ) );
  2093. m_pThumbWarnings->AddActionSignalTarget( this );
  2094. m_pThumbWarnings->SetCommand( "ThumbWarnings" );
  2095. m_pThumbWarnings->SetSelected( g_warn_enable );
  2096. // Filtering
  2097. m_pHideMipped = vgui::SETUP_PANEL( new vgui::CheckButton( this, "HideMipped", "Hide Mipped" ) );
  2098. m_pHideMipped->AddActionSignalTarget( this );
  2099. m_pHideMipped->SetCommand( "HideMipped" );
  2100. m_pHideMipped->SetSelected( false );
  2101. // Filtering
  2102. m_pFilteringChk = vgui::SETUP_PANEL( new vgui::CheckButton( this, "FilteringChk", "Filter: " ) );
  2103. m_pFilteringChk->AddActionSignalTarget( this );
  2104. m_pFilteringChk->SetCommand( "FilteringChk" );
  2105. m_pFilteringChk->SetSelected( true );
  2106. m_pFilteringText = vgui::SETUP_PANEL( new vgui::TextEntry( this, "FilteringTxt" ) );
  2107. m_pFilteringText->AddActionSignalTarget( this );
  2108. m_pReloadAllMaterialsButton = vgui::SETUP_PANEL( new vgui::Button( this, "ReloadAllMaterials", "Reload All Materials" ) );
  2109. if ( m_pReloadAllMaterialsButton )
  2110. {
  2111. m_pReloadAllMaterialsButton->AddActionSignalTarget( this );
  2112. m_pReloadAllMaterialsButton->SetCommand( "ReloadAllMaterials" );
  2113. }
  2114. m_pCommitChangesButton = vgui::SETUP_PANEL( new vgui::Button( this, "CommitChanges", "Commit Changes" ) );
  2115. if ( m_pCommitChangesButton )
  2116. {
  2117. m_pCommitChangesButton->AddActionSignalTarget( this );
  2118. m_pCommitChangesButton->SetCommand( "CommitChanges" );
  2119. }
  2120. m_pDiscardChangesButton = vgui::SETUP_PANEL( new vgui::Button( this, "DiscardChanges", "Discard Changes" ) );
  2121. if ( m_pDiscardChangesButton )
  2122. {
  2123. m_pDiscardChangesButton->AddActionSignalTarget( this );
  2124. m_pDiscardChangesButton->SetCommand( "DiscardChanges" );
  2125. }
  2126. // Create the tree control itself.
  2127. m_pListPanel = vgui::SETUP_PANEL( new vgui::ListPanel( this, "List Panel" ) );
  2128. m_pListPanel->SetVisible( !mat_texture_list_view.GetBool() );
  2129. int col = -1;
  2130. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_NAME, "Texture Name", 200, 100, 700, vgui::ListPanel::COLUMN_RESIZEWITHWINDOW );
  2131. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_PATH, "Path", 50, 50, 300, 0 );
  2132. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_SIZE, "Kilobytes", 50, 50, 50, 0 );
  2133. m_pListPanel->SetSortFunc( col, KilobytesSortFunc );
  2134. m_pListPanel->SetSortColumnEx( col, 0, true ); // advanced sorting setup
  2135. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_TEXTURE_GROUP, "Group", 100, 100, 300, 0 );
  2136. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_FORMAT, "Format", 250, 50, 300, 0 );
  2137. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_WIDTH, "Width", 50, 50, 50, 0 );
  2138. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_HEIGHT, "Height", 50, 50, 50, 0 );
  2139. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_BINDS_FRAME, "# Binds", 50, 50, 50, 0 );
  2140. m_pListPanel->AddColumnHeader( ++ col, KEYNAME_BINDS_MAX, "BindsMax", 50, 50, 50, 0 );
  2141. SetBgColor( Color( 0, 0, 0, 100 ) );
  2142. m_pListPanel->SetBgColor( Color( 0, 0, 0, 100 ) );
  2143. // Create the view control itself
  2144. m_pViewPanel = vgui::SETUP_PANEL( new CRenderTexturesListViewPanel( this, "View Panel" ) );
  2145. m_pViewPanel->SetVisible( mat_texture_list_view.GetBool() );
  2146. m_pViewPanel->SetBgColor( Color( 0, 0, 0, 255 ) );
  2147. m_pViewPanel->SetDragEnabled( false );
  2148. m_pViewPanel->SetDropEnabled( false );
  2149. m_pViewPanel->SetPaintAlpha( bDefaultTxAlphaOn );
  2150. m_pViewPanel->SetDataListPanel( m_pListPanel );
  2151. }
  2152. //-----------------------------------------------------------------------------
  2153. // Purpose:
  2154. //-----------------------------------------------------------------------------
  2155. CTextureListPanel::~CTextureListPanel( void )
  2156. {
  2157. g_pTextureListPanel = NULL;
  2158. }
  2159. void CTextureListPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  2160. {
  2161. BaseClass::ApplySchemeSettings( pScheme );
  2162. // If you change this font, be sure to mark it with
  2163. // $use_in_fillrate_mode in its .vmt file
  2164. m_hFont = pScheme->GetFont( "DefaultVerySmall", false );
  2165. Assert( m_hFont );
  2166. }
  2167. //-----------------------------------------------------------------------------
  2168. // Purpose:
  2169. // Output : Returns true on success, false on failure.
  2170. //-----------------------------------------------------------------------------
  2171. bool CTextureListPanel::ShouldDraw( void )
  2172. {
  2173. if ( mat_texture_list.GetInt() )
  2174. return true;
  2175. if ( s_eTxListPanelRequest == TXR_SHOW ||
  2176. s_eTxListPanelRequest == TXR_RUNNING )
  2177. return true;
  2178. return false;
  2179. }
  2180. void CTextureListPanel::PerformLayout()
  2181. {
  2182. BaseClass::PerformLayout();
  2183. // Put the collapse button in the corner
  2184. m_pCollapse->SetPos( 2, 10 );
  2185. m_pCollapse->SetSize( 10, 10 );
  2186. m_pCollapse->SetVisible( true );
  2187. bool bCollapsed = m_pCollapse->IsSelected();
  2188. int x, y, w, t;
  2189. GetClientArea( x, y, w, t );
  2190. int yOffset = y;
  2191. // The cvar reminder goes on the top.
  2192. m_pCVarListLabel->SetPos( x, yOffset );
  2193. m_pCVarListLabel->SetWide( w );
  2194. NULL; // yOffset += m_pCVarListLabel->GetTall();
  2195. m_pCVarListLabel->SetVisible( false ); // m_pCVarListLabel->SetVisible( !bCollapsed );
  2196. m_pTotalUsageLabel->SetPos( x, yOffset );
  2197. m_pTotalUsageLabel->SetWide( w );
  2198. yOffset += m_pTotalUsageLabel->GetTall();
  2199. m_pTotalUsageLabel->SetVisible( !bCollapsed );
  2200. // Align the check boxes.
  2201. vgui::Panel *buttons[] = {
  2202. m_pSpecialTexs,
  2203. m_pShowTextureMemoryUsageOption,
  2204. m_pAllTextures,
  2205. m_pViewTextures,
  2206. m_pFilteringChk,
  2207. m_pHideMipped,
  2208. m_pResolveTexturePath,
  2209. m_pCopyToClipboardButton };
  2210. for ( int i=0; i < ARRAYSIZE( buttons ); i++ )
  2211. {
  2212. buttons[i]->SetPos( x, yOffset );
  2213. buttons[i]->SetWide( w/2 );
  2214. yOffset += buttons[i]->GetTall();
  2215. buttons[i]->SetVisible( !bCollapsed );
  2216. if ( buttons[i] == m_pViewTextures )
  2217. {
  2218. m_pViewTextures->SetWide( 170 );
  2219. int accumw = 170;
  2220. m_pAlpha->SetPos( x + accumw + 5, yOffset - m_pViewTextures->GetTall() );
  2221. m_pAlpha->SetWide( (accumw += 85, 85) );
  2222. m_pThumbWarnings->SetPos( x + accumw + 5, yOffset - m_pViewTextures->GetTall() );
  2223. m_pThumbWarnings->SetWide( (accumw += 85, 85) );
  2224. }
  2225. if ( buttons[i] == m_pFilteringChk )
  2226. {
  2227. m_pFilteringChk->SetWide( 60 );
  2228. int accumw = 60;
  2229. m_pFilteringText->SetPos( x + accumw + 5, yOffset - m_pFilteringChk->GetTall() );
  2230. m_pFilteringText->SetWide( ( accumw += 170, 170 ) );
  2231. m_pFilteringText->SetTall( m_pFilteringChk->GetTall() );
  2232. m_pFilteringText->SetVisible( !bCollapsed );
  2233. }
  2234. }
  2235. if ( bCollapsed )
  2236. {
  2237. int xOffset = 85, iWidth;
  2238. struct LayoutHorz_t
  2239. {
  2240. vgui::Panel *pPanel;
  2241. int iWidth;
  2242. }
  2243. layout[] =
  2244. {
  2245. { m_pTotalUsageLabel, 290 },
  2246. { m_pViewTextures, 170 },
  2247. { m_pAlpha, 60 },
  2248. { m_pAllTextures, 135 },
  2249. { m_pHideMipped, 100 },
  2250. { m_pFilteringChk, 60 },
  2251. { m_pFilteringText, 130 },
  2252. { m_pReloadAllMaterialsButton, 130 },
  2253. { m_pCommitChangesButton, 130 },
  2254. { m_pDiscardChangesButton, 130 },
  2255. };
  2256. for ( int k = 0; k < ARRAYSIZE( layout ); ++ k )
  2257. {
  2258. layout[ k ].pPanel->SetPos( xOffset, 2 );
  2259. iWidth = layout[ k ].iWidth;
  2260. iWidth = min( w - xOffset - 30, iWidth );
  2261. layout[ k ].pPanel->SetWide( iWidth );
  2262. layout[ k ].pPanel->SetVisible( iWidth > 50 );
  2263. if ( iWidth > 50 )
  2264. xOffset += iWidth + 5;
  2265. }
  2266. yOffset = y;
  2267. }
  2268. m_pAlpha->SetVisible( m_pViewTextures->IsSelected() );
  2269. m_pThumbWarnings->SetVisible( !bCollapsed && m_pViewTextures->IsSelected() );
  2270. m_pListPanel->SetBounds( x, yOffset, w, t - (yOffset - y) );
  2271. m_pViewPanel->SetBounds( x, yOffset, w, t - (yOffset - y) );
  2272. m_pListPanel->SetVisible( !mat_texture_list_view.GetBool() );
  2273. m_pViewPanel->SetVisible( mat_texture_list_view.GetBool() );
  2274. }
  2275. bool StripDirName( char *pFilename )
  2276. {
  2277. if ( pFilename[0] == 0 )
  2278. return false;
  2279. char *pLastSlash = pFilename;
  2280. while ( 1 )
  2281. {
  2282. char *pTestSlash = strchr( pLastSlash, '/' );
  2283. if ( !pTestSlash )
  2284. {
  2285. pTestSlash = strchr( pLastSlash, '\\' );
  2286. if ( !pTestSlash )
  2287. break;
  2288. }
  2289. pTestSlash++; // Skip past the slash.
  2290. pLastSlash = pTestSlash;
  2291. }
  2292. if ( pLastSlash == pFilename )
  2293. {
  2294. return false;
  2295. }
  2296. else
  2297. {
  2298. Assert( pLastSlash[-1] == '/' || pLastSlash[-1] == '\\' );
  2299. pLastSlash[-1] = 0;
  2300. return true;
  2301. }
  2302. }
  2303. static inline void ToLowerInplace( char *chBuffer )
  2304. {
  2305. for ( char *pch = chBuffer; *pch; ++ pch )
  2306. {
  2307. if ( V_isupper( *pch ) )
  2308. *pch = tolower( *pch );
  2309. }
  2310. }
  2311. void KeepSpecialKeys( KeyValues *textureList, bool bServiceKeys )
  2312. {
  2313. KeyValues *pNext;
  2314. for ( KeyValues *pCur = textureList->GetFirstSubKey(); pCur; pCur=pNext )
  2315. {
  2316. pNext = pCur->GetNextKey();
  2317. bool bIsServiceKey = false;
  2318. char const *szName = pCur->GetString( KEYNAME_NAME );
  2319. if ( StringHasPrefix( szName, "_" ) ||
  2320. StringHasPrefix( szName, "[" ) ||
  2321. !stricmp( szName, "backbuffer" ) ||
  2322. StringHasPrefix( szName, "colorcorrection" ) ||
  2323. !stricmp( szName, "depthbuffer" ) ||
  2324. !stricmp( szName, "frontbuffer" ) ||
  2325. !stricmp( szName, "normalize" ) ||
  2326. !*szName )
  2327. {
  2328. bIsServiceKey = true;
  2329. }
  2330. if ( bIsServiceKey != bServiceKeys )
  2331. {
  2332. textureList->RemoveSubKey( pCur );
  2333. }
  2334. else if ( bIsServiceKey )
  2335. {
  2336. pCur->SetInt( "SpecialTx", 1 );
  2337. }
  2338. }
  2339. }
  2340. void KeepKeysMatchingFilter( KeyValues *textureList, char const *szFilter )
  2341. {
  2342. if ( !szFilter || !*szFilter )
  2343. return;
  2344. char chFilter[MAX_PATH] = {0}, chName[MAX_PATH] = {0};
  2345. Q_strncpy( chFilter, szFilter, sizeof( chFilter ) - 1 );
  2346. ToLowerInplace( chFilter );
  2347. KeyValues *pNext;
  2348. for ( KeyValues *pCur=textureList->GetFirstSubKey(); pCur; pCur=pNext )
  2349. {
  2350. pNext = pCur->GetNextKey();
  2351. char const *szName = pCur->GetString( KEYNAME_NAME );
  2352. Q_strncpy( chName, szName, sizeof( chName ) - 1 );
  2353. ToLowerInplace( chName );
  2354. if ( !strstr( chName, chFilter ) )
  2355. {
  2356. textureList->RemoveSubKey( pCur );
  2357. }
  2358. }
  2359. }
  2360. void KeepKeysMarkedNoMip( KeyValues *textureList )
  2361. {
  2362. KeyValues *pNext;
  2363. for ( KeyValues *pCur=textureList->GetFirstSubKey(); pCur; pCur=pNext )
  2364. {
  2365. pNext = pCur->GetNextKey();
  2366. char const *szTextureFile = pCur->GetString( KEYNAME_NAME );
  2367. char const *szTextureGroup = pCur->GetString( KEYNAME_TEXTURE_GROUP );
  2368. if ( *szTextureFile )
  2369. {
  2370. ITexture *pMatTexture = materials->FindTexture( szTextureFile, szTextureGroup, false );
  2371. if ( pMatTexture && !(pMatTexture->GetFlags() & TEXTUREFLAGS_NOMIP) )
  2372. {
  2373. textureList->RemoveSubKey( pCur );
  2374. }
  2375. }
  2376. }
  2377. }
  2378. void CTextureListPanel::UpdateTotalUsageLabel()
  2379. {
  2380. char data[1024], kb1[20], kb2[20], kb3[20];
  2381. FmtCommaNumber( kb1, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_BOUND_LAST_FRAME ) + 511) / 1024 );
  2382. FmtCommaNumber( kb2, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_TOTAL_LOADED ) + 511) / 1024 );
  2383. FmtCommaNumber( kb3, m_numDisplayedSizeKB );
  2384. if ( bool bCollapsed = m_pCollapse->IsSelected() )
  2385. {
  2386. char const *szTitle = "";
  2387. Q_snprintf( data, sizeof( data ), "%s[F %s Kb] / [T %s Kb] / [S %s Kb]", szTitle, kb1, kb2, kb3 );
  2388. }
  2389. else
  2390. {
  2391. char const *szTitle = "Texture Memory Usage";
  2392. char kbMip1[ 20 ], kbMip2[ 20 ];
  2393. FmtCommaNumber( kbMip1, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_ESTIMATE_PICMIP_1 ) + 511) / 1024 );
  2394. FmtCommaNumber( kbMip2, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_ESTIMATE_PICMIP_2 ) + 511) / 1024 );
  2395. Q_snprintf( data, sizeof( data ), "%s: frame %s Kb / total %s Kb ( picmip1 = %s Kb, picmip2 = %s Kb ) / shown %s Kb", szTitle, kb1, kb2, kbMip1, kbMip2, kb3 );
  2396. }
  2397. wchar_t unicodeString[1024];
  2398. g_pVGuiLocalize->ConvertANSIToUnicode( data, unicodeString, sizeof( unicodeString ) );
  2399. m_pTotalUsageLabel->SetText( unicodeString );
  2400. }
  2401. void CTextureListPanel::OnTextChanged( void )
  2402. {
  2403. OnCommand( "FilteringTxt" );
  2404. }
  2405. void CTextureListPanel::OnCommand( const char *command )
  2406. {
  2407. if ( !Q_stricmp( command, "Close" ) )
  2408. {
  2409. vgui::Frame::OnCommand( command );
  2410. return;
  2411. }
  2412. if ( !Q_stricmp( command, "Collapse" ) )
  2413. {
  2414. InvalidateLayout();
  2415. return;
  2416. }
  2417. if ( !Q_stricmp( command, "ShowAlpha" ) )
  2418. {
  2419. m_pViewPanel->SetPaintAlpha( m_pAlpha->IsSelected() );
  2420. return;
  2421. }
  2422. if ( !Q_stricmp( command, "ThumbWarnings" ) )
  2423. {
  2424. g_warn_enable = m_pThumbWarnings->IsSelected();
  2425. return;
  2426. }
  2427. if ( !Q_stricmp( command, "ViewThumbnails" ) )
  2428. {
  2429. InvalidateLayout();
  2430. return;
  2431. }
  2432. if ( !Q_stricmp( command, COPYTOCLIPBOARD_CMDNAME ) )
  2433. {
  2434. CopyListPanelToClipboard( m_pListPanel );
  2435. return;
  2436. }
  2437. if ( !Q_stricmp( command, "ReloadAllMaterials" ) )
  2438. {
  2439. Cbuf_AddText( "mat_reloadallmaterials" );
  2440. Cbuf_Execute();
  2441. return;
  2442. }
  2443. if ( !Q_stricmp( command, "CommitChanges" ) )
  2444. {
  2445. Cbuf_AddText( "mat_texture_list_txlod_sync save" );
  2446. Cbuf_Execute();
  2447. return;
  2448. }
  2449. if ( !Q_stricmp( command, "DiscardChanges" ) )
  2450. {
  2451. Cbuf_AddText( "mat_texture_list_txlod_sync reset" );
  2452. Cbuf_Execute();
  2453. return;
  2454. }
  2455. mat_texture_list_on_f();
  2456. InvalidateLayout();
  2457. }
  2458. bool CTextureListPanel::UpdateDisplayedItem( KeyValues *pDispData, KeyValues *kv )
  2459. {
  2460. // Update the item?
  2461. bool bUpdate = false;
  2462. // do the stuff that changes often separately.
  2463. if ( pDispData->GetInt( KEYNAME_BINDS_FRAME ) != kv->GetInt( KEYNAME_BINDS_FRAME ) )
  2464. {
  2465. pDispData->SetInt( KEYNAME_BINDS_FRAME, kv->GetInt( KEYNAME_BINDS_FRAME ) );
  2466. bUpdate = true;
  2467. }
  2468. if ( pDispData->GetInt( KEYNAME_BINDS_MAX ) != kv->GetInt( KEYNAME_BINDS_MAX ) )
  2469. {
  2470. pDispData->SetInt( KEYNAME_BINDS_MAX, kv->GetInt( KEYNAME_BINDS_MAX ) );
  2471. bUpdate = true;
  2472. }
  2473. // stuff that changes less frequently
  2474. if( pDispData->GetInt( KEYNAME_SIZE ) != kv->GetInt( KEYNAME_SIZE ) ||
  2475. pDispData->GetInt( KEYNAME_WIDTH ) != kv->GetInt( KEYNAME_WIDTH ) ||
  2476. pDispData->GetInt( KEYNAME_HEIGHT ) != kv->GetInt( KEYNAME_HEIGHT ) ||
  2477. Q_stricmp( pDispData->GetString( KEYNAME_FORMAT ), kv->GetString( KEYNAME_FORMAT ) ) != 0 ||
  2478. Q_stricmp( pDispData->GetString( KEYNAME_PATH ), kv->GetString( KEYNAME_PATH ) ) != 0 ||
  2479. Q_stricmp( pDispData->GetString( KEYNAME_TEXTURE_GROUP ), kv->GetString( KEYNAME_TEXTURE_GROUP ) ) != 0 )
  2480. {
  2481. pDispData->SetInt( KEYNAME_SIZE, kv->GetInt( KEYNAME_SIZE ) );
  2482. pDispData->SetInt( KEYNAME_WIDTH, kv->GetInt( KEYNAME_WIDTH ) );
  2483. pDispData->SetInt( KEYNAME_HEIGHT, kv->GetInt( KEYNAME_HEIGHT ) );
  2484. pDispData->SetString( KEYNAME_FORMAT, kv->GetString( KEYNAME_FORMAT ) );
  2485. pDispData->SetString( KEYNAME_PATH, kv->GetString( KEYNAME_PATH ) );
  2486. pDispData->SetString( KEYNAME_TEXTURE_GROUP, kv->GetString( KEYNAME_TEXTURE_GROUP ) );
  2487. bUpdate = true;
  2488. }
  2489. return bUpdate;
  2490. }
  2491. int CTextureListPanel::AddListItem( KeyValues *kv )
  2492. {
  2493. int iItem = m_pListPanel->GetItem( kv->GetString( KEYNAME_NAME ) );
  2494. if ( iItem == -1 )
  2495. {
  2496. // Set this so the GetItem() call above can use the key's name (as opposed to the value of its
  2497. // "Name" subkey) to find this texture again.
  2498. kv->SetName( kv->GetString( KEYNAME_NAME ) );
  2499. // Add this one.
  2500. iItem = m_pListPanel->AddItem( kv, 0, false, false );
  2501. m_pViewPanel->InvalidateLayout();
  2502. }
  2503. else
  2504. {
  2505. KeyValues *pValues = m_pListPanel->GetItem( iItem );
  2506. bool bNeedUpdate = UpdateDisplayedItem( pValues, kv );
  2507. if( bNeedUpdate )
  2508. {
  2509. m_pListPanel->ApplyItemChanges( iItem );
  2510. m_pViewPanel->Repaint();
  2511. }
  2512. }
  2513. return iItem;
  2514. }
  2515. //-----------------------------------------------------------------------------
  2516. // Purpose:
  2517. //-----------------------------------------------------------------------------
  2518. void CTextureListPanel::OnTurnedOn()
  2519. {
  2520. if ( g_bRecursiveRequestToShowTextureList )
  2521. return;
  2522. if ( m_pListPanel )
  2523. m_pListPanel->DeleteAllItems();
  2524. if ( CRenderTextureEditor *pRe = m_pViewPanel->GetRenderTxEditor() )
  2525. pRe->Close();
  2526. MakePopup( false, false );
  2527. MoveToFront();
  2528. }
  2529. void CTextureListPanel::Close()
  2530. {
  2531. mat_texture_list_off_f();
  2532. }
  2533. void CTextureListPanel::EndPaint()
  2534. {
  2535. UpdateTotalUsageLabel();
  2536. }
  2537. void CTextureListPanel::Paint()
  2538. {
  2539. VPROF( "CTextureListPanel::Paint" );
  2540. if ( !m_hFont )
  2541. return;
  2542. struct EndPaint_t
  2543. {
  2544. CTextureListPanel *m_p;
  2545. EndPaint_t( CTextureListPanel *p ) : m_p( p ) {}
  2546. ~EndPaint_t()
  2547. {
  2548. m_p->EndPaint();
  2549. }
  2550. } endpaint( this );
  2551. if ( !mat_texture_list.GetBool() )
  2552. return;
  2553. if ( !g_pMaterialSystemDebugTextureInfo->IsDebugTextureListFresh( 1 ) )
  2554. return;
  2555. CSmartTextureKeyValues textureList;
  2556. if ( !textureList.Get() )
  2557. return;
  2558. CRenderTextureEditor *pRte = m_pViewPanel->GetRenderTxEditor();
  2559. if ( ( s_eTxListPanelRequest == TXR_RUNNING ) &&
  2560. pRte->IsVisible() )
  2561. {
  2562. KeyValues *kv = NULL;
  2563. int iHint = 0;
  2564. pRte->GetDispInfo( kv, iHint );
  2565. if ( kv && iHint )
  2566. {
  2567. KeyValues *plv = ( m_pListPanel->IsValidItemID( iHint ) ? m_pListPanel->GetItem( iHint ) : NULL );
  2568. if ( plv && !strcmp( plv->GetString( KEYNAME_NAME ), kv->GetString( KEYNAME_NAME ) ) )
  2569. {
  2570. KeyValues *pValData = plv->GetFirstValue(), *pValRendered = kv->GetFirstValue();
  2571. for ( ; pValData && pValRendered; pValData = pValData->GetNextValue(), pValRendered = pValRendered->GetNextValue() )
  2572. {
  2573. if ( strcmp( pValData->GetString(), pValRendered->GetString() ) )
  2574. break;
  2575. }
  2576. if ( pValData || pValRendered ) // Difference found
  2577. pRte->SetDispInfo( plv, iHint );
  2578. }
  2579. else
  2580. kv = NULL;
  2581. }
  2582. if ( 0 ) // if ( !kv )
  2583. {
  2584. pRte->Close();
  2585. pRte->SetDispInfo( NULL, 0 );
  2586. }
  2587. }
  2588. // If we are fetching all textures, then stop loading material system:
  2589. if ( mat_texture_list_all.GetBool() )
  2590. {
  2591. if ( s_eTxListPanelRequest == TXR_RUNNING )
  2592. {
  2593. mat_texture_list.SetValue( 0 );
  2594. s_eTxListPanelRequest = TXR_SHOW; // Keep displaying our panel
  2595. }
  2596. else
  2597. {
  2598. s_eTxListPanelRequest = TXR_RUNNING;
  2599. }
  2600. }
  2601. else
  2602. {
  2603. if ( s_eTxListPanelRequest == TXR_SHOW )
  2604. {
  2605. // Either first show or turned off "all textures"
  2606. m_pListPanel->RemoveAll();
  2607. m_pViewPanel->InvalidateLayout();
  2608. s_eTxListPanelRequest = TXR_RUNNING;
  2609. return;
  2610. }
  2611. }
  2612. CBitVec<4096 * 8> itemsTouched;
  2613. // Remove the textures we don't care for
  2614. KeepSpecialKeys( textureList.Get(), m_pSpecialTexs->IsSelected() );
  2615. // If filtering is enabled, then do filtering
  2616. if ( m_pFilteringChk->IsSelected() && m_pFilteringText->GetTextLength() )
  2617. {
  2618. char chFilterString[ MAX_PATH ];
  2619. m_pFilteringText->GetText( chFilterString, sizeof( chFilterString ) - 1 );
  2620. chFilterString[ sizeof( chFilterString ) - 1 ] = 0;
  2621. KeepKeysMatchingFilter( textureList.Get(), chFilterString );
  2622. }
  2623. // If we're to hide mipped, remove anything that isn't marked nomip
  2624. if ( m_pHideMipped->IsSelected() )
  2625. {
  2626. KeepKeysMarkedNoMip( textureList.Get() );
  2627. }
  2628. // Compute the total size of the displayed textures
  2629. int cbTotalDisplayedSizeInBytes = 0;
  2630. for ( KeyValues *pCur = textureList.Get()->GetFirstSubKey(); pCur; pCur=pCur->GetNextKey() )
  2631. {
  2632. int sizeInBytes = pCur->GetInt( KEYNAME_SIZE );
  2633. // Accumulate
  2634. cbTotalDisplayedSizeInBytes += sizeInBytes;
  2635. // Factor in frames
  2636. int numCount = pCur->GetInt( "Count" );
  2637. if ( numCount > 1 )
  2638. sizeInBytes *= numCount;
  2639. // Size is in kilobytes.
  2640. int sizeInKilo = ( sizeInBytes + 511 ) / 1024;
  2641. pCur->SetInt( KEYNAME_SIZE, sizeInKilo );
  2642. if ( m_pResolveTexturePath->IsSelected() )
  2643. {
  2644. char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
  2645. Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vtf", pCur->GetString( KEYNAME_NAME ) );
  2646. char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
  2647. if ( szResolvedName )
  2648. {
  2649. pCur->SetString( KEYNAME_PATH, szResolvedName );
  2650. }
  2651. }
  2652. int iItem = AddListItem( pCur );
  2653. if ( iItem < itemsTouched.GetNumBits() )
  2654. itemsTouched.Set( iItem );
  2655. }
  2656. // Set the displayed size
  2657. m_numDisplayedSizeKB = ( cbTotalDisplayedSizeInBytes + 511 ) / 1024;
  2658. // Now remove from view items that weren't used.
  2659. int iNext, numRemoved = 0;
  2660. for ( int iCur=m_pListPanel->FirstItem(); iCur != m_pListPanel->InvalidItemID(); iCur=iNext )
  2661. {
  2662. iNext = m_pListPanel->NextItem( iCur );
  2663. if ( iCur >= itemsTouched.GetNumBits() || !itemsTouched.Get( iCur ) )
  2664. {
  2665. m_pListPanel->RemoveItem( iCur );
  2666. ++ numRemoved;
  2667. }
  2668. }
  2669. // Sorting in list panel
  2670. {
  2671. int iPri, iSec;
  2672. bool bAsc;
  2673. m_pListPanel->GetSortColumnEx( iPri, iSec, bAsc );
  2674. iSec = 0; // always secondary sort by name
  2675. m_pListPanel->SetSortColumnEx( iPri, iSec, bAsc );
  2676. m_pListPanel->SortList();
  2677. }
  2678. if ( numRemoved )
  2679. {
  2680. m_pViewPanel->InvalidateLayout();
  2681. }
  2682. }
  2683. // ------------------------------------------------------------------------------ //
  2684. // Global functions.
  2685. // ------------------------------------------------------------------------------ //
  2686. void VGui_UpdateTextureListPanel()
  2687. {
  2688. if ( mat_show_texture_memory_usage.GetInt() )
  2689. {
  2690. con_nprint_t info;
  2691. info.index = 4;
  2692. info.time_to_live = 0.2;
  2693. info.color[0] = 1;
  2694. info.color[1] = 0.5;
  2695. info.color[2] = 0;
  2696. info.fixed_width_font = true;
  2697. char kb1[20], kb2[20];
  2698. FmtCommaNumber( kb1, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_BOUND_LAST_FRAME ) + 511) / 1024 );
  2699. FmtCommaNumber( kb2, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_TOTAL_LOADED ) + 511) / 1024 );
  2700. Con_NXPrintf( &info, "Texture Memory Usage: %s Kb / %s Kb", kb1, kb2 );
  2701. }
  2702. MatViewOverride::DisplaySelectedTextures();
  2703. if ( IsX360() )
  2704. return;
  2705. g_pMaterialSystemDebugTextureInfo->EnableGetAllTextures( mat_texture_list_all.GetBool() );
  2706. g_pMaterialSystemDebugTextureInfo->EnableDebugTextureList( ( mat_texture_list.GetInt() <= 0 ) ? false : true );
  2707. bool bShouldDrawTxListPanel = g_pTextureListPanel->ShouldDraw();
  2708. if ( g_pTextureListPanel->IsVisible() != bShouldDrawTxListPanel )
  2709. {
  2710. g_pTextureListPanel->SetVisible( bShouldDrawTxListPanel );
  2711. bShouldDrawTxListPanel ? mat_texture_list_on_f() : mat_texture_list_off_f();
  2712. }
  2713. }
  2714. void CL_CreateTextureListPanel( vgui::Panel *parent )
  2715. {
  2716. g_pTextureListPanel = new CTextureListPanel( parent );
  2717. }
  2718. CON_COMMAND( mat_texture_save_fonts, "Save all font textures" )
  2719. {
  2720. for( int i = 0; i < 8192; i++ )
  2721. {
  2722. char szTextureName[ MAX_PATH ];
  2723. Q_snprintf( szTextureName, ARRAYSIZE( szTextureName ), "__font_page_%d.tga", i );
  2724. if( !materials->IsTextureLoaded( szTextureName ) )
  2725. break;
  2726. ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
  2727. if( pMatTexture && !pMatTexture->IsError() )
  2728. {
  2729. bool bRet = SaveTextureImage( szTextureName );
  2730. Msg( "SaveTextureImage( '%s' ): %s\n", szTextureName, bRet ? "succeeded" : "failed" );
  2731. }
  2732. }
  2733. }
  2734. void mat_texture_list_on_f()
  2735. {
  2736. ConVarRef sv_cheats( "sv_cheats" );
  2737. if ( sv_cheats.IsValid() && !sv_cheats.GetBool() )
  2738. return;
  2739. ConVarRef mat_queue_mode( "mat_queue_mode" );
  2740. if( mat_queue_mode.IsValid() && ( g_nSaveQueueState == INT_MIN ) )
  2741. {
  2742. g_nSaveQueueState = mat_queue_mode.GetInt();
  2743. mat_queue_mode.SetValue( 0 );
  2744. }
  2745. mat_texture_list.SetValue( 1 );
  2746. s_eTxListPanelRequest = TXR_SHOW;
  2747. g_pTextureListPanel->OnTurnedOn();
  2748. MatViewOverride::RequestSelectNone();
  2749. // On Linux, the mouse gets recentered when it's hidden. So if you bring up the texture list
  2750. // dialog while the game is running, we need to make sure the mouse is shown. Otherwise it's
  2751. // very tough to use when your mouse keeps getting recentered.
  2752. if( !g_cursorset && g_pVGuiSurface )
  2753. {
  2754. g_pVGuiSurface->SetCursorAlwaysVisible( true );
  2755. g_cursorset = true;
  2756. }
  2757. }
  2758. void mat_texture_list_off_f()
  2759. {
  2760. mat_texture_list.SetValue( 0 );
  2761. s_eTxListPanelRequest = TXR_HIDE;
  2762. if( g_cursorset )
  2763. {
  2764. g_pVGuiSurface->SetCursorAlwaysVisible( false );
  2765. g_cursorset = false;
  2766. }
  2767. if( g_nSaveQueueState != INT_MIN )
  2768. {
  2769. ConVarRef mat_queue_mode( "mat_queue_mode" );
  2770. mat_queue_mode.SetValue( g_nSaveQueueState );
  2771. g_nSaveQueueState = INT_MIN;
  2772. }
  2773. }