3055 lines
85 KiB
C++
3055 lines
85 KiB
C++
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||
//
|
||
// Purpose:
|
||
//
|
||
//=============================================================================//
|
||
|
||
#include "client_pch.h"
|
||
#ifdef _PS3
|
||
void CL_CreateTextureListPanel( vgui::Panel * ) {}
|
||
void CL_TextureListPanel_ClearState() {}
|
||
void VGui_UpdateTextureListPanel() {}
|
||
#else
|
||
#include "ivideomode.h"
|
||
#include "client_class.h"
|
||
#include "icliententitylist.h"
|
||
#include "vgui_basepanel.h"
|
||
#include <vgui_controls/Controls.h>
|
||
#include <vgui/ISurface.h>
|
||
#include <vgui/IScheme.h>
|
||
#include <vgui/IVGui.h>
|
||
#include <vgui_controls/Frame.h>
|
||
#include <vgui_controls/TreeView.h>
|
||
#include <vgui_controls/ListPanel.h>
|
||
#include <vgui_controls/ListViewPanel.h>
|
||
#include <vgui_controls/TreeViewListControl.h>
|
||
#include <vgui/ISystem.h>
|
||
#include "tier0/vprof.h"
|
||
#include "keyvalues.h"
|
||
#include "vgui_helpers.h"
|
||
#include "utlsymbol.h"
|
||
#include "tier1/UtlStringMap.h"
|
||
#include "bitvec.h"
|
||
#include "utldict.h"
|
||
#include "vgui/ILocalize.h"
|
||
#include "con_nprint.h"
|
||
#include "gl_matsysiface.h"
|
||
|
||
#include "VGuiMatSurface/IMatSystemSurface.h"
|
||
#include "materialsystem/imaterial.h"
|
||
#include "materialsystem/imaterialvar.h"
|
||
#include "materialsystem/imesh.h"
|
||
#include "materialsystem/idebugtextureinfo.h"
|
||
#include "materialsystem/itexture.h"
|
||
#include "vtf/vtf.h"
|
||
#include "tier2/tier2.h"
|
||
#include "smartptr.h"
|
||
|
||
#include "igame.h"
|
||
|
||
#include "client.h"
|
||
|
||
// For character manipulations isupper/tolower
|
||
#include <ctype.h>
|
||
|
||
// memdbgon must be the last include file in a .cpp file!!!
|
||
#include "tier0/memdbgon.h"
|
||
|
||
#define KEYNAME_NAME "Name"
|
||
#define KEYNAME_PATH "Path"
|
||
#define KEYNAME_BINDS_MAX "BindsMax"
|
||
#define KEYNAME_BINDS_FRAME "BindsFrame"
|
||
#define KEYNAME_SIZE "Size"
|
||
#define KEYNAME_FORMAT "Format"
|
||
#define KEYNAME_WIDTH "Width"
|
||
#define KEYNAME_HEIGHT "Height"
|
||
#define KEYNAME_TEXTURE_GROUP "TexGroup"
|
||
|
||
#define COPYTOCLIPBOARD_CMDNAME "CopyToClipboard"
|
||
|
||
#if defined( _X360 )
|
||
CON_COMMAND( mat_get_textures, "VXConsole command" )
|
||
{
|
||
g_pMaterialSystemDebugTextureInfo->EnableDebugTextureList( true );
|
||
g_pMaterialSystemDebugTextureInfo->EnableGetAllTextures( args.ArgC() >= 2 && ( Q_stricmp( args[1], "all" ) == 0 ) );
|
||
}
|
||
#endif
|
||
|
||
static ConVar mat_texture_list( "mat_texture_list", "0", FCVAR_CHEAT, "For debugging, show a list of used textures per frame" );
|
||
|
||
static inline void MatTextureModificationRecorded()
|
||
{
|
||
extern void Host_DisallowSecureServers();
|
||
Host_DisallowSecureServers();
|
||
}
|
||
|
||
static enum TxListPanelRequest
|
||
{
|
||
TXR_NONE,
|
||
TXR_SHOW,
|
||
TXR_RUNNING,
|
||
TXR_HIDE
|
||
} s_eTxListPanelRequest = TXR_NONE;
|
||
|
||
// These are here so you can bind a key to +mat_texture_list and toggle it on and off.
|
||
void mat_texture_list_on_f();
|
||
void mat_texture_list_off_f();
|
||
|
||
ConCommand mat_texture_list_on( "+mat_texture_list", mat_texture_list_on_f );
|
||
ConCommand mat_texture_list_off( "-mat_texture_list", mat_texture_list_off_f );
|
||
|
||
ConVar mat_texture_list_all( "mat_texture_list_all", "0", FCVAR_NEVER_AS_STRING, "If this is nonzero, then the texture list panel will show all currently-loaded textures." );
|
||
ConVar mat_texture_list_all_frames( "mat_texture_list_all_frames", "2", 0, "How many frames to sample texture memory for all textures." );
|
||
|
||
ConVar mat_texture_list_view( "mat_texture_list_view", "1", FCVAR_NEVER_AS_STRING, "If this is nonzero, then the texture list panel will render thumbnails of currently-loaded textures." );
|
||
|
||
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." );
|
||
|
||
|
||
static int g_warn_texkbytes = 1499;
|
||
static int g_warn_texdimensions = 1024;
|
||
static bool g_warn_enable = true;
|
||
|
||
class CTextureListPanel;
|
||
static CTextureListPanel *g_pTextureListPanel = NULL;
|
||
static bool g_bRecursiveRequestToShowTextureList = false;
|
||
|
||
|
||
//
|
||
// A class to mimic a list view
|
||
//
|
||
|
||
namespace vgui
|
||
{
|
||
|
||
|
||
class TileViewPanelEx : public Panel
|
||
{
|
||
DECLARE_CLASS_SIMPLE( TileViewPanelEx, Panel );
|
||
|
||
public:
|
||
TileViewPanelEx( Panel *parent, const char *panelName );
|
||
~TileViewPanelEx();
|
||
|
||
public:
|
||
virtual void SetFont( HFont hFont );
|
||
virtual HFont GetFont();
|
||
|
||
public:
|
||
enum HitTest_t
|
||
{
|
||
HT_NOTHING = 0,
|
||
HT_TILE
|
||
};
|
||
virtual int HitTest( int x, int y, int &iTile );
|
||
virtual bool GetTileOrg( int iTile, int &x, int &y );
|
||
|
||
protected: // Overrides for contents
|
||
virtual int GetNumTiles() = 0;
|
||
virtual void GetTileSize( int &wide, int &tall ) = 0;
|
||
virtual void RenderTile( int iTile, int x, int y ) = 0;
|
||
|
||
protected:
|
||
// Handlers
|
||
virtual void OnMouseWheeled( int delta );
|
||
virtual void OnSizeChanged( int wide, int tall );
|
||
virtual void PerformLayout();
|
||
virtual void Paint();
|
||
virtual void ApplySchemeSettings( IScheme *pScheme );
|
||
MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" );
|
||
|
||
protected:
|
||
virtual bool ComputeLayoutInfo();
|
||
int m_li_numTiles; //!< Total number of tiles
|
||
int m_li_numVisibleTiles; //!< Number of tiles fitting in the client area
|
||
int m_li_wide, m_li_tall; //!< Tile area width/height
|
||
int m_li_wideItem, m_li_tallItem; //!< Every item width/height
|
||
int m_li_colVisible, m_li_rowVisible; //!< Num columns/rows fitting in the client area
|
||
int m_li_rowNeeded; //!< Num rows required to fit all numTiles
|
||
int m_li_startTile, m_li_endTile; //!< Start/end tile that are rendered in the client area
|
||
|
||
private:
|
||
ScrollBar *m_hbar;
|
||
HFont m_hFont;
|
||
};
|
||
|
||
|
||
|
||
//
|
||
// Implementation details
|
||
//
|
||
|
||
TileViewPanelEx::TileViewPanelEx( Panel *parent, const char *panelName ) :
|
||
Panel( parent, panelName ),
|
||
m_hbar( NULL ),
|
||
m_hFont( INVALID_FONT )
|
||
{
|
||
m_hbar = new ScrollBar( this, "VerticalScrollBar", true );
|
||
m_hbar->AddActionSignalTarget( this );
|
||
m_hbar->SetVisible( true );
|
||
}
|
||
|
||
TileViewPanelEx::~TileViewPanelEx()
|
||
{
|
||
delete m_hbar;
|
||
}
|
||
|
||
void TileViewPanelEx::SetFont( HFont hFont )
|
||
{
|
||
m_hFont = hFont;
|
||
Repaint();
|
||
}
|
||
|
||
HFont TileViewPanelEx::GetFont()
|
||
{
|
||
return m_hFont;
|
||
}
|
||
|
||
int TileViewPanelEx::HitTest( int x, int y, int &iTile )
|
||
{
|
||
iTile = -1;
|
||
|
||
if ( !ComputeLayoutInfo() )
|
||
return HT_NOTHING;
|
||
|
||
int hitCol = ( x / m_li_wideItem );
|
||
int hitRow = ( y / m_li_tallItem );
|
||
|
||
if ( hitCol >= m_li_colVisible )
|
||
return HT_NOTHING;
|
||
if ( hitRow > m_li_rowVisible )
|
||
return HT_NOTHING;
|
||
|
||
int hitTile = m_li_startTile + hitCol + hitRow * m_li_colVisible;
|
||
if ( hitTile >= m_li_endTile )
|
||
return HT_NOTHING;
|
||
|
||
// Hit tile
|
||
iTile = hitTile;
|
||
return HT_TILE;
|
||
}
|
||
|
||
bool TileViewPanelEx::GetTileOrg( int iTile, int &x, int &y )
|
||
{
|
||
if ( m_li_colVisible <= 0 )
|
||
return false;
|
||
if ( iTile < m_li_startTile || iTile >= m_li_endTile )
|
||
return false;
|
||
|
||
x = 0 + ( ( iTile - m_li_startTile ) % m_li_colVisible ) * m_li_wideItem;
|
||
y = 0 + ( ( iTile - m_li_startTile ) / m_li_colVisible ) * m_li_tallItem;
|
||
|
||
return true;
|
||
}
|
||
|
||
void TileViewPanelEx::OnMouseWheeled( int delta )
|
||
{
|
||
if ( m_hbar->IsVisible() )
|
||
{
|
||
int val = m_hbar->GetValue();
|
||
val -= delta;
|
||
m_hbar->SetValue( val );
|
||
}
|
||
}
|
||
|
||
void TileViewPanelEx::OnSizeChanged( int wide, int tall )
|
||
{
|
||
BaseClass::OnSizeChanged( wide, tall );
|
||
InvalidateLayout();
|
||
Repaint();
|
||
}
|
||
|
||
void TileViewPanelEx::PerformLayout()
|
||
{
|
||
int numTiles = GetNumTiles();
|
||
m_hbar->SetVisible( false );
|
||
|
||
int wide, tall;
|
||
GetSize( wide, tall );
|
||
wide -= m_hbar->GetWide();
|
||
|
||
m_hbar->SetPos( wide - 2, 0 );
|
||
m_hbar->SetTall( tall );
|
||
|
||
if ( !numTiles )
|
||
return;
|
||
|
||
int wideItem = 1, tallItem = 1;
|
||
GetTileSize( wideItem, tallItem );
|
||
if ( !wideItem || !tallItem )
|
||
return;
|
||
|
||
int colVisible = wide / wideItem;
|
||
int rowVisible = tall / tallItem;
|
||
if ( rowVisible <= 0 || colVisible <= 0 )
|
||
return;
|
||
|
||
int rowNeeded = ( numTiles + colVisible - 1 ) / colVisible;
|
||
|
||
int startTile = 0;
|
||
if ( rowNeeded > rowVisible )
|
||
{
|
||
m_hbar->SetRange( 0, rowNeeded );
|
||
m_hbar->SetRangeWindow( rowVisible );
|
||
m_hbar->SetButtonPressedScrollValue( 1 );
|
||
|
||
m_hbar->SetVisible( true );
|
||
m_hbar->InvalidateLayout();
|
||
|
||
int val = m_hbar->GetValue();
|
||
startTile = val * colVisible;
|
||
}
|
||
}
|
||
|
||
bool TileViewPanelEx::ComputeLayoutInfo()
|
||
{
|
||
m_li_numTiles = GetNumTiles();
|
||
if ( !m_li_numTiles )
|
||
return false;
|
||
|
||
GetSize( m_li_wide, m_li_tall );
|
||
m_li_wide -= m_hbar->GetWide();
|
||
|
||
m_li_wideItem = 1, m_li_tallItem = 1;
|
||
GetTileSize( m_li_wideItem, m_li_tallItem );
|
||
if ( !m_li_wideItem || !m_li_tallItem )
|
||
return false;
|
||
|
||
m_li_colVisible = m_li_wide / m_li_wideItem;
|
||
m_li_rowVisible = m_li_tall / m_li_tallItem;
|
||
if ( m_li_rowVisible <= 0 || m_li_colVisible <= 0 )
|
||
return false;
|
||
|
||
m_li_rowNeeded = ( m_li_numTiles + m_li_colVisible - 1 ) / m_li_colVisible;
|
||
m_li_numVisibleTiles = m_li_colVisible * m_li_rowVisible;
|
||
|
||
m_li_startTile = 0;
|
||
if ( m_li_rowNeeded > m_li_rowVisible )
|
||
{
|
||
int val = m_hbar->GetValue();
|
||
m_li_startTile = val * m_li_colVisible;
|
||
}
|
||
|
||
if ( m_li_startTile >= m_li_numTiles )
|
||
m_li_startTile = m_li_numTiles - m_li_numVisibleTiles;
|
||
if ( m_li_startTile < 0 )
|
||
m_li_startTile = 0;
|
||
|
||
m_li_endTile = m_li_startTile + m_li_numVisibleTiles + m_li_colVisible; // draw the partly visible items
|
||
if ( m_li_endTile > m_li_numTiles )
|
||
m_li_endTile = m_li_numTiles;
|
||
|
||
return true;
|
||
}
|
||
|
||
void TileViewPanelEx::Paint()
|
||
{
|
||
BaseClass::Paint();
|
||
|
||
// Now render all our tiles
|
||
if ( !ComputeLayoutInfo() )
|
||
return;
|
||
|
||
for ( int iRenderTile = m_li_startTile; iRenderTile < m_li_endTile; ++ iRenderTile )
|
||
{
|
||
int x = 0 + ( ( iRenderTile - m_li_startTile ) % m_li_colVisible ) * m_li_wideItem;
|
||
int y = 0 + ( ( iRenderTile - m_li_startTile ) / m_li_colVisible ) * m_li_tallItem;
|
||
RenderTile( iRenderTile, x, y );
|
||
}
|
||
}
|
||
|
||
void TileViewPanelEx::ApplySchemeSettings( IScheme *pScheme )
|
||
{
|
||
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
||
SetBgColor( GetSchemeColor( "ListPanel.BgColor", pScheme ) );
|
||
SetBorder( pScheme->GetBorder("ButtonDepressedBorder" ) );
|
||
|
||
SetFont( pScheme->GetFont( "Default", IsProportional() ) );
|
||
}
|
||
|
||
void TileViewPanelEx::OnSliderMoved()
|
||
{
|
||
InvalidateLayout();
|
||
Repaint();
|
||
}
|
||
|
||
|
||
|
||
}; // namespace vgui
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// Material access
|
||
//
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
class CAutoMatSysDebugMode
|
||
{
|
||
public:
|
||
CAutoMatSysDebugMode();
|
||
~CAutoMatSysDebugMode();
|
||
|
||
void ScheduleCleanupTextureVar( IMaterialVar *pVar );
|
||
|
||
protected:
|
||
bool bOldDebugMode;
|
||
CUtlRBTree< IMaterialVar * > arrCleanupVars;
|
||
};
|
||
|
||
CAutoMatSysDebugMode::CAutoMatSysDebugMode() :
|
||
arrCleanupVars( DefLessFunc(IMaterialVar *) )
|
||
{
|
||
g_pMaterialSystem->Flush();
|
||
bOldDebugMode = g_pMaterialSystemDebugTextureInfo->SetDebugTextureRendering( true );
|
||
}
|
||
|
||
CAutoMatSysDebugMode::~CAutoMatSysDebugMode()
|
||
{
|
||
g_pMaterialSystem->Flush();
|
||
g_pMaterialSystemDebugTextureInfo->SetDebugTextureRendering( bOldDebugMode );
|
||
|
||
for ( uint32 k = 0; k < arrCleanupVars.Count(); ++ k )
|
||
{
|
||
IMaterialVar *pVar = arrCleanupVars.Element( k );
|
||
pVar->SetUndefined();
|
||
}
|
||
}
|
||
|
||
void CAutoMatSysDebugMode::ScheduleCleanupTextureVar( IMaterialVar *pVar )
|
||
{
|
||
if ( !pVar )
|
||
return;
|
||
|
||
arrCleanupVars.InsertIfNotFound( pVar );
|
||
}
|
||
|
||
static IMaterial * UseDebugMaterial( char const *szMaterial, ITexture *pMatTexture, CAutoMatSysDebugMode *pRestoreVars )
|
||
{
|
||
if ( !szMaterial || !pMatTexture )
|
||
return NULL;
|
||
|
||
bool foundVar;
|
||
|
||
IMaterial *pMaterial = materials->FindMaterial( szMaterial, TEXTURE_GROUP_OTHER, false );
|
||
// IMaterial *pMaterial = materials->FindMaterial( "debug/debugempty", TEXTURE_GROUP_OTHER, false );
|
||
if ( !pMaterial )
|
||
return NULL;
|
||
|
||
IMaterialVar *BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false );
|
||
// IMaterialVar *BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false );
|
||
if ( !foundVar || !BaseTextureVar )
|
||
return NULL;
|
||
|
||
IMaterialVar *FrameVar = pMaterial->FindVar( "$frame", &foundVar, false );
|
||
if ( foundVar && FrameVar )
|
||
{
|
||
int numAnimFrames = pMatTexture->GetNumAnimationFrames();
|
||
|
||
if ( pMatTexture->IsRenderTarget() || pMatTexture->IsProcedural() )
|
||
numAnimFrames = 0; // Cannot use the stencil parts of the render targets and shouldn't use the other frames of procedural textures
|
||
|
||
FrameVar->SetIntValue( ( numAnimFrames > 0 ) ? ( g_ClientGlobalVariables.tickcount % numAnimFrames ) : 0 );
|
||
}
|
||
|
||
BaseTextureVar->SetTextureValue( pMatTexture );
|
||
|
||
if ( pRestoreVars )
|
||
{
|
||
pRestoreVars->ScheduleCleanupTextureVar( BaseTextureVar );
|
||
}
|
||
|
||
return pMaterial;
|
||
}
|
||
|
||
static void RenderTexturedRect( vgui::Panel *pPanel, IMaterial *pMaterial, int x, int y, int x1, int y1, int xoff = 0, int yoff = 0 )
|
||
{
|
||
CAutoMatSysDebugMode auto_matsysdebugmode;
|
||
|
||
int tall = pPanel->GetTall();
|
||
float fHeightUV = 1.0f;
|
||
if ( y1 > tall )
|
||
{
|
||
fHeightUV = float( tall - y ) / float( y1 - y );
|
||
y1 = tall;
|
||
}
|
||
if ( y1 <= y )
|
||
return;
|
||
|
||
pPanel->LocalToScreen( x, y );
|
||
pPanel->LocalToScreen( x1, y1 );
|
||
|
||
x += xoff; x1 += xoff; y += yoff; y1 += yoff;
|
||
|
||
CMatRenderContextPtr pRenderContext( materials );
|
||
pRenderContext->Bind( pMaterial );
|
||
IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
|
||
|
||
CMeshBuilder meshBuilder;
|
||
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
|
||
|
||
meshBuilder.Position3f( x, y, 0.0f );
|
||
meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
|
||
meshBuilder.AdvanceVertex();
|
||
|
||
meshBuilder.Position3f( x1, y, 0.0f );
|
||
meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
|
||
meshBuilder.AdvanceVertex();
|
||
|
||
meshBuilder.Position3f( x1, y1, 0.0f );
|
||
meshBuilder.TexCoord2f( 0, 1.0f, fHeightUV );
|
||
meshBuilder.AdvanceVertex();
|
||
|
||
meshBuilder.Position3f( x, y1, 0.0f );
|
||
meshBuilder.TexCoord2f( 0, 0.0f, fHeightUV );
|
||
meshBuilder.AdvanceVertex();
|
||
|
||
meshBuilder.End();
|
||
pMesh->Draw();
|
||
}
|
||
|
||
static bool ShallWarnTx( KeyValues *kv, ITexture *tx )
|
||
{
|
||
if ( !tx )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if ( tx->GetFlags() & ( TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_ONEBITALPHA ) )
|
||
return true;
|
||
|
||
if ( stricmp( "DXT1", kv->GetString( KEYNAME_FORMAT ) ) && stricmp( "DXT5", kv->GetString( KEYNAME_FORMAT ) ) &&
|
||
stricmp( "ATI1N", kv->GetString( KEYNAME_FORMAT ) ) && stricmp( "ATI2N", kv->GetString( KEYNAME_FORMAT ) ) )
|
||
return true;
|
||
|
||
if ( kv->GetInt( KEYNAME_SIZE ) > g_warn_texkbytes )
|
||
return true;
|
||
|
||
if ( kv->GetInt( KEYNAME_WIDTH ) > g_warn_texdimensions )
|
||
return true;
|
||
|
||
if ( kv->GetInt( KEYNAME_HEIGHT ) > g_warn_texdimensions )
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
static void FmtCommaNumber( char *pchBuffer, unsigned int uiNumber )
|
||
{
|
||
pchBuffer[0] = 0;
|
||
for ( unsigned int uiDivisor = 1000 * 1000 * 1000; uiDivisor > 0; uiDivisor /= 1000 )
|
||
{
|
||
if ( uiNumber > uiDivisor )
|
||
{
|
||
unsigned int uiPrint = ( uiNumber / uiDivisor ) % 1000;
|
||
sprintf( pchBuffer + strlen( pchBuffer ), ( uiNumber / uiDivisor < 1000 ) ? "%d," : "%03d,", uiPrint );
|
||
}
|
||
}
|
||
|
||
int len = strlen( pchBuffer );
|
||
if ( !len )
|
||
sprintf( pchBuffer, "0" );
|
||
else if ( pchBuffer[ len - 1 ] == ',' )
|
||
pchBuffer[ len - 1 ] = 0;
|
||
}
|
||
|
||
namespace
|
||
{
|
||
|
||
char s_chLastViewedTextureBuffer[ 0x200 ] = {0};
|
||
|
||
}; // end `anonymous` namespace
|
||
|
||
ConVar mat_texture_list_exclude_editing( "mat_texture_list_exclude_editing", "0" );
|
||
|
||
bool CanAdjustTextureSize( char const *szTextureName, bool bMoveSizeUp )
|
||
{
|
||
ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
|
||
if ( !pMatTexture )
|
||
return false;
|
||
|
||
if ( mat_texture_list_exclude_editing.GetInt() > 0 )
|
||
{
|
||
MaterialTextureInfo_t txInfo;
|
||
if ( !materials->GetTextureInformation( szTextureName, txInfo ) )
|
||
return false;
|
||
if ( txInfo.iExcludeInformation == 0 )
|
||
return false;
|
||
}
|
||
|
||
// Determine the texture current size
|
||
if ( !bMoveSizeUp )
|
||
{
|
||
return ( pMatTexture->GetActualWidth() > 4 || pMatTexture->GetActualHeight() > 4 );
|
||
}
|
||
else
|
||
{
|
||
return ( pMatTexture->GetActualWidth() < pMatTexture->GetMappingWidth() ||
|
||
pMatTexture->GetActualHeight() < pMatTexture->GetMappingHeight() );
|
||
}
|
||
}
|
||
|
||
bool AdjustTextureSize( char const *szTextureName, bool bMoveSizeUp )
|
||
{
|
||
MatTextureModificationRecorded();
|
||
|
||
ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
|
||
|
||
if ( !pMatTexture )
|
||
return false;
|
||
|
||
if ( mat_texture_list_exclude_editing.GetInt() > 0 )
|
||
{
|
||
int iOverride = MAX( pMatTexture->GetActualWidth(), pMatTexture->GetActualHeight() );
|
||
if ( bMoveSizeUp )
|
||
iOverride <<= 1;
|
||
else
|
||
iOverride >>= 1;
|
||
pMatTexture->ForceExcludeOverride( iOverride );
|
||
}
|
||
else
|
||
{
|
||
pMatTexture->ForceLODOverride( bMoveSizeUp ? +1 : -1 );
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool AdjustTextureExclude( char const *szTextureName, bool bExclude )
|
||
{
|
||
MatTextureModificationRecorded();
|
||
|
||
ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
|
||
|
||
if ( !pMatTexture )
|
||
return false;
|
||
|
||
if ( mat_texture_list_exclude_editing.GetInt() > 0 )
|
||
{
|
||
int iOverride = bExclude ? 0 : -1;
|
||
pMatTexture->ForceExcludeOverride( iOverride );
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
bool CanAdjustTextureExclude( char const *szTextureName )
|
||
{
|
||
if ( mat_texture_list_exclude_editing.GetInt() <= 0 )
|
||
return false;
|
||
|
||
ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
|
||
|
||
if ( !pMatTexture )
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
bool IsTextureExcluded( char const *szTextureName )
|
||
{
|
||
if ( mat_texture_list_exclude_editing.GetInt() <= 0 )
|
||
return false;
|
||
|
||
ITexture *pMatTexture = materials->FindTexture( szTextureName, "", false );
|
||
|
||
if ( !pMatTexture )
|
||
return false;
|
||
|
||
MaterialTextureInfo_t txInfo;
|
||
if ( !materials->GetTextureInformation( szTextureName, txInfo ) )
|
||
return false;
|
||
|
||
if ( txInfo.iExcludeInformation == 0 )
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
|
||
CON_COMMAND_F( mat_texture_list_txlod, "Adjust LOD of the last viewed texture +1 to inc resolution, -1 to dec resolution", FCVAR_DONTRECORD )
|
||
{
|
||
if ( args.ArgC() == 2 )
|
||
{
|
||
char const *szArg = args.Arg( 1 );
|
||
|
||
if ( !stricmp( szArg, "exclude" ) || !stricmp( szArg, "noexclude" ) )
|
||
{
|
||
bool bExclude = !stricmp( szArg, "exclude" );
|
||
if ( !CanAdjustTextureExclude( s_chLastViewedTextureBuffer ) )
|
||
Warning( "mat_texture_list_txlod cannot adjust exclude for '%s'\n", s_chLastViewedTextureBuffer );
|
||
else if ( !AdjustTextureExclude( s_chLastViewedTextureBuffer, bExclude ) )
|
||
Warning( "mat_texture_list_txlod failed %sexcluding '%s'\n", bExclude ? "" : "no", s_chLastViewedTextureBuffer );
|
||
else
|
||
Msg( "mat_texture_list_txlod %sexcluded '%s'\n", bExclude ? "" : "no", s_chLastViewedTextureBuffer );
|
||
return;
|
||
}
|
||
|
||
int iAdjustment = atoi( szArg );
|
||
switch ( iAdjustment )
|
||
{
|
||
case 1:
|
||
case -1:
|
||
if ( !CanAdjustTextureSize( s_chLastViewedTextureBuffer, iAdjustment > 0 ) )
|
||
Warning( "mat_texture_list_txlod cannot adjust lod for '%s'\n", s_chLastViewedTextureBuffer );
|
||
else if ( !AdjustTextureSize( s_chLastViewedTextureBuffer, iAdjustment > 0 ) )
|
||
Warning( "mat_texture_list_txlod failed adjusting lod for '%s'\n", s_chLastViewedTextureBuffer );
|
||
else
|
||
Msg( "mat_texture_list_txlod adjusted lod %c1 for '%s'\n", ( iAdjustment > 0 ) ? '+' : '-' , s_chLastViewedTextureBuffer );
|
||
return;
|
||
default:
|
||
break;
|
||
|
||
}
|
||
}
|
||
Warning( "Usage: 'mat_texture_list_txlod +1' to inc lod | 'mat_texture_list_txlod -1' to dec lod\n" );
|
||
}
|
||
|
||
|
||
namespace MatViewOverride
|
||
{
|
||
|
||
|
||
//
|
||
// View override parameters request
|
||
//
|
||
struct ViewParamsReq
|
||
{
|
||
CUtlVector< UtlSymId_t > lstMaterials;
|
||
}
|
||
s_viewParamsReq;
|
||
|
||
void RequestSelectNone( void )
|
||
{
|
||
s_viewParamsReq.lstMaterials.RemoveAll();
|
||
}
|
||
void RequestSelected( int nCount, UtlSymId_t const *pNameIds )
|
||
{
|
||
s_viewParamsReq.lstMaterials.AddMultipleToTail( nCount, pNameIds );
|
||
}
|
||
|
||
//
|
||
// View override last parameters
|
||
//
|
||
struct ViewParamsLast
|
||
{
|
||
ViewParamsLast() : lstMaterials( DefLessFunc( UtlSymId_t ) ), flTime( 0.f ), bHighlighted( false ) {}
|
||
|
||
float flTime;
|
||
bool bHighlighted;
|
||
|
||
struct TxInfo
|
||
{
|
||
ITexture *pTx;
|
||
CUtlSymbol name;
|
||
};
|
||
|
||
struct VarMap : public CUtlMap< UtlSymId_t, TxInfo >
|
||
{
|
||
VarMap() : CUtlMap< UtlSymId_t, TxInfo >( DefLessFunc( UtlSymId_t ) ) {}
|
||
VarMap( VarMap const &x ) { const_cast< VarMap & >( x ).Swap( *this ); m_matInfo = x.m_matInfo; } // Fast-swap data
|
||
|
||
struct MatInfo
|
||
{
|
||
// MatInfo() : ignorez( false ) {}
|
||
// bool ignorez;
|
||
MatInfo() {}
|
||
} m_matInfo;
|
||
};
|
||
|
||
CUtlMap< UtlSymId_t, VarMap > lstMaterials;
|
||
}
|
||
s_viewParamsLast;
|
||
|
||
//
|
||
// DisplaySelectedTextures
|
||
// Executed every frame to toggle the selected/unselected
|
||
// textures for a list of materials.
|
||
//
|
||
void DisplaySelectedTextures()
|
||
{
|
||
// Nothing selected
|
||
if ( !s_viewParamsLast.lstMaterials.Count() &&
|
||
!s_viewParamsReq.lstMaterials.Count() )
|
||
return;
|
||
|
||
if ( !s_viewParamsLast.lstMaterials.Count() &&
|
||
s_viewParamsReq.lstMaterials.Count() )
|
||
{
|
||
// First time selection
|
||
s_viewParamsLast.flTime = Plat_FloatTime();
|
||
s_viewParamsLast.bHighlighted = false;
|
||
}
|
||
else
|
||
{
|
||
// Wait for the flash-time
|
||
float fCurTime = Plat_FloatTime();
|
||
if ( fCurTime >= s_viewParamsLast.flTime &&
|
||
fCurTime < s_viewParamsLast.flTime + 0.4 &&
|
||
s_viewParamsReq.lstMaterials.Count() )
|
||
return;
|
||
|
||
s_viewParamsLast.flTime = fCurTime;
|
||
s_viewParamsLast.bHighlighted = !s_viewParamsLast.bHighlighted;
|
||
}
|
||
|
||
// Find the empty texture
|
||
ITexture *txEmpty = materials->FindTexture( "debugempty", "", false );
|
||
|
||
typedef unsigned short MapIdx;
|
||
|
||
// Now walk over all the materials in the req list and push them to the params
|
||
for ( int k = 0, kEnd = s_viewParamsReq.lstMaterials.Count(); k < kEnd; ++ k )
|
||
{
|
||
UtlSymId_t idMat = s_viewParamsReq.lstMaterials[ k ];
|
||
MapIdx idx = s_viewParamsLast.lstMaterials.Find( idMat );
|
||
if ( idx == s_viewParamsLast.lstMaterials.InvalidIndex() )
|
||
{
|
||
// Insert the new material
|
||
idx = s_viewParamsLast.lstMaterials.Insert( idMat );
|
||
ViewParamsLast::VarMap &vars = s_viewParamsLast.lstMaterials.Element( idx );
|
||
|
||
// Locate the material
|
||
char const *szMaterialName = CUtlSymbol( idMat ).String();
|
||
IMaterial *pMat = materials->FindMaterial( szMaterialName, TEXTURE_GROUP_OTHER, false );
|
||
if ( pMat )
|
||
{
|
||
int numParams = pMat->ShaderParamCount();
|
||
IMaterialVar **arrVars = pMat->GetShaderParams();
|
||
for ( int idxParam = 0; idxParam < numParams; ++ idxParam )
|
||
{
|
||
// if ( !stricmp( arrVars[ idxParam ]->GetName(), "$ignorez" ) )
|
||
// {
|
||
// vars.m_matInfo.ignorez = arrVars[ idxParam ]->GetIntValue() ? true : false;
|
||
// arrVars[ idxParam ]->SetIntValue( 1 );
|
||
// continue;
|
||
// }
|
||
|
||
if ( !arrVars[ idxParam ]->IsTexture() )
|
||
continue;
|
||
|
||
ITexture *pTex = arrVars[ idxParam ]->GetTextureValue();
|
||
if ( !pTex || pTex->IsError() )
|
||
continue;
|
||
|
||
ViewParamsLast::TxInfo txinfo;
|
||
txinfo.name = CUtlSymbol( pTex->GetName() );
|
||
txinfo.pTx = pTex;
|
||
vars.Insert( CUtlSymbol( arrVars[ idxParam ]->GetName() ), txinfo );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Now walk over all the materials that we have to highlight or unhighlight
|
||
for ( MapIdx idx = s_viewParamsLast.lstMaterials.FirstInorder();
|
||
idx != s_viewParamsLast.lstMaterials.InvalidIndex();
|
||
/* advance inside */ )
|
||
{
|
||
UtlSymId_t idMat = s_viewParamsLast.lstMaterials.Key( idx );
|
||
ViewParamsLast::VarMap &vars = s_viewParamsLast.lstMaterials.Element( idx );
|
||
|
||
bool bRemovedSelection = ( s_viewParamsReq.lstMaterials.Find( idMat ) < 0 );
|
||
|
||
char const *szMaterialName = CUtlSymbol( idMat ).String();
|
||
IMaterial *pMat = materials->FindMaterial( szMaterialName, TEXTURE_GROUP_OTHER, false );
|
||
if ( pMat )
|
||
{
|
||
int numParams = pMat->ShaderParamCount();
|
||
IMaterialVar **arrVars = pMat->GetShaderParams();
|
||
for ( int idxParam = 0; idxParam < numParams; ++ idxParam )
|
||
{
|
||
// if ( bRemovedSelection && !stricmp( arrVars[ idxParam ]->GetName(), "$ignorez" ) )
|
||
// {
|
||
// arrVars[ idxParam ]->SetIntValue( vars.m_matInfo.ignorez ? 1 : 0 );
|
||
// continue;
|
||
// }
|
||
|
||
char const *szVarName = arrVars[ idxParam ]->GetName();
|
||
CUtlSymbol symVarName( szVarName );
|
||
MapIdx idxVarsTxInfo = vars.Find( symVarName );
|
||
if ( idxVarsTxInfo != vars.InvalidIndex() )
|
||
{
|
||
ViewParamsLast::TxInfo &ti = vars.Element( idxVarsTxInfo );
|
||
|
||
ITexture *pTx = ( s_viewParamsLast.bHighlighted && !bRemovedSelection ) ? txEmpty : ti.pTx;
|
||
Assert( ti.pTx && !ti.pTx->IsError() );
|
||
|
||
arrVars[ idxParam ]->SetTextureValue( pTx );
|
||
}
|
||
}
|
||
}
|
||
|
||
// Index advance
|
||
if ( bRemovedSelection )
|
||
{
|
||
MapIdx idxRemove = idx;
|
||
idx = s_viewParamsLast.lstMaterials.NextInorder( idx );
|
||
s_viewParamsLast.lstMaterials.RemoveAt( idxRemove );
|
||
}
|
||
else
|
||
{
|
||
idx = s_viewParamsLast.lstMaterials.NextInorder( idx );
|
||
}
|
||
}
|
||
}
|
||
|
||
}; // end namespace MatViewOverride
|
||
|
||
|
||
void CL_TextureListPanel_ClearState()
|
||
{
|
||
MatViewOverride::RequestSelectNone();
|
||
MatViewOverride::DisplaySelectedTextures();
|
||
}
|
||
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// Custom text entry with "Open" for vmt's
|
||
//
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
class CVmtTextEntry : public vgui::TextEntry
|
||
{
|
||
DECLARE_CLASS_SIMPLE( CVmtTextEntry, vgui::TextEntry );
|
||
|
||
public:
|
||
CVmtTextEntry( vgui::Panel *parent, char const *szName ) : BaseClass( parent, szName ) {}
|
||
|
||
public:
|
||
MESSAGE_FUNC( OpenVmtSelected, "DoOpenVmtSelected" );
|
||
|
||
virtual void OpenEditMenu();
|
||
};
|
||
|
||
void CVmtTextEntry::OpenEditMenu()
|
||
{
|
||
vgui::Menu *pEditMenu = BaseClass::GetEditMenu();
|
||
|
||
int pos = pEditMenu->AddMenuItem( "Open VMT", new KeyValues("DoOpenVmtSelected"), this );
|
||
pEditMenu->MoveMenuItem( pos, 0 );
|
||
|
||
int x0, x1;
|
||
pEditMenu->SetItemEnabled( "Open VMT", GetSelectedRange(x0, x1) );
|
||
|
||
BaseClass::OpenEditMenu();
|
||
}
|
||
|
||
void CVmtTextEntry::OpenVmtSelected()
|
||
{
|
||
int x0, x1;
|
||
if ( !GetSelectedRange(x0, x1) )
|
||
return;
|
||
|
||
CUtlVector<char> buf;
|
||
buf.SetCount( x1 - x0 + 1 );
|
||
GetTextRange( buf.Base(), x0, x1 - x0 );
|
||
|
||
for ( char *pchName = buf.Base(), *pchNext = NULL; pchName; pchName = pchNext )
|
||
{
|
||
if ( ( pchNext = strchr( pchName, '\n' ) ) != NULL )
|
||
*( pchNext ++ ) = 0;
|
||
|
||
char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
|
||
Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vmt", pchName );
|
||
char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
|
||
|
||
if ( szResolvedName )
|
||
vgui::system()->ShellExecuteEx( "open", szResolvedName, "" );
|
||
}
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// Render textures edit panel
|
||
//
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
class CRenderTextureEditor : public vgui::Frame
|
||
{
|
||
DECLARE_CLASS_SIMPLE( CRenderTextureEditor, vgui::Frame );
|
||
|
||
public:
|
||
CRenderTextureEditor( vgui::Panel *parent, char const *szName );
|
||
~CRenderTextureEditor();
|
||
|
||
public:
|
||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||
virtual void PerformLayout();
|
||
virtual void OnCommand( const char *command );
|
||
virtual void SetFont( vgui::HFont hFont ) { m_hFont = hFont; Repaint(); }
|
||
virtual vgui::HFont GetFont() { return m_hFont; }
|
||
|
||
public:
|
||
virtual void OnMousePressed( vgui::MouseCode code );
|
||
virtual void OnMouseDoublePressed( vgui::MouseCode code ) { OnMousePressed( code ); }
|
||
virtual void Activate();
|
||
virtual void Close();
|
||
|
||
public:
|
||
void SetDispInfo( KeyValues *kv, int iHint );
|
||
void GetDispInfo( KeyValues *&kv, int &iHint );
|
||
|
||
public:
|
||
virtual void Paint();
|
||
|
||
enum
|
||
{
|
||
TILE_BORDER = 10,
|
||
TILE_SIZE = 550,
|
||
TILE_TEXTURE_SIZE = 256,
|
||
TILE_TEXT = 70
|
||
};
|
||
|
||
protected:
|
||
vgui::HFont m_hFont;
|
||
CVmtTextEntry *m_pMaterials;
|
||
vgui::Button *m_pExplore;
|
||
vgui::Button *m_pReload;
|
||
vgui::Button *m_pCopyTxt, *m_pCopyImg;
|
||
vgui::Button *m_pSizeControls[3];
|
||
vgui::Button *m_pFlashBtn;
|
||
KeyValues *m_pInfo;
|
||
CUtlBuffer m_bufInfoText;
|
||
CUtlVector< UtlSymId_t > m_lstMaterials;
|
||
int m_iInfoHint;
|
||
};
|
||
|
||
CRenderTextureEditor::CRenderTextureEditor( vgui::Panel *parent, char const *szName ) :
|
||
BaseClass( parent, szName ),
|
||
m_pInfo( NULL ),
|
||
m_iInfoHint( 0 ),
|
||
m_hFont( vgui::INVALID_FONT ),
|
||
m_bufInfoText( 0, 0, CUtlBuffer::TEXT_BUFFER )
|
||
{
|
||
m_pMaterials = vgui::SETUP_PANEL( new CVmtTextEntry( this, "Materials" ) );
|
||
m_pMaterials->SetMultiline( true );
|
||
m_pMaterials->SetEditable( false );
|
||
m_pMaterials->SetEnabled( false );
|
||
m_pMaterials->SetVerticalScrollbar( true );
|
||
m_pMaterials->SetVisible( true );
|
||
|
||
m_pExplore = vgui::SETUP_PANEL( new vgui::Button( this, "Explore", "Open", this, "Explore" ) );
|
||
m_pExplore->SetVisible( true );
|
||
|
||
m_pReload = vgui::SETUP_PANEL( new vgui::Button( this, "Reload", "Reload", this, "Reload" ) );
|
||
m_pReload->SetVisible( true );
|
||
|
||
m_pCopyTxt = vgui::SETUP_PANEL( new vgui::Button( this, "CopyTxt", "Copy Text", this, "CopyTxt" ) );
|
||
m_pCopyTxt->SetVisible( true );
|
||
|
||
m_pCopyImg = vgui::SETUP_PANEL( new vgui::Button( this, "CopyImg", "Copy Image", this, "CopyImg" ) );
|
||
m_pCopyImg->SetVisible( true );
|
||
|
||
m_pFlashBtn = vgui::SETUP_PANEL( new vgui::Button( this, "FlashBtn", "Flash in Game", this, "FlashBtn" ) );
|
||
m_pFlashBtn->SetVisible( true );
|
||
|
||
m_pSizeControls[0] = vgui::SETUP_PANEL( new vgui::Button( this, "--", "--", this, "size-" ) );
|
||
m_pSizeControls[1] = vgui::SETUP_PANEL( new vgui::Button( this, "+", "+", this, "size+" ) );
|
||
|
||
m_pSizeControls[2] = vgui::SETUP_PANEL( new vgui::CheckButton( this, "Exclude", "Exclude" ) );
|
||
m_pSizeControls[2]->AddActionSignalTarget( this );
|
||
m_pSizeControls[2]->SetCommand( "Exclude" );
|
||
|
||
}
|
||
|
||
CRenderTextureEditor::~CRenderTextureEditor()
|
||
{
|
||
SetDispInfo( NULL, 0 );
|
||
}
|
||
|
||
void CRenderTextureEditor::GetDispInfo( KeyValues *&kv, int &iHint )
|
||
{
|
||
iHint = m_iInfoHint;
|
||
kv = m_pInfo;
|
||
}
|
||
|
||
void CRenderTextureEditor::SetDispInfo( KeyValues *kv, int iHint )
|
||
{
|
||
m_iInfoHint = iHint;
|
||
|
||
if ( m_pInfo )
|
||
m_pInfo->deleteThis();
|
||
|
||
m_pInfo = kv ? kv->MakeCopy() : NULL;
|
||
|
||
|
||
CUtlStringMap< bool > arrMaterials, arrMaterialsFullNames;
|
||
|
||
if ( kv )
|
||
{
|
||
char const *szTextureName = kv->GetString( KEYNAME_NAME );
|
||
for ( MaterialHandle_t hm = materials->FirstMaterial();
|
||
hm != materials->InvalidMaterial(); hm = materials->NextMaterial( hm ) )
|
||
{
|
||
IMaterial *pMat = materials->GetMaterial( hm );
|
||
if ( !pMat )
|
||
continue;
|
||
|
||
int numParams = pMat->ShaderParamCount();
|
||
IMaterialVar **arrVars = pMat->GetShaderParams();
|
||
for ( int idxParam = 0; idxParam < numParams; ++ idxParam )
|
||
{
|
||
if ( !arrVars[ idxParam ]->IsTexture() )
|
||
continue;
|
||
|
||
ITexture *pTex = arrVars[ idxParam ]->GetTextureValue();
|
||
if ( !pTex || pTex->IsError() )
|
||
continue;
|
||
|
||
if ( !stricmp( pTex->GetName(), szTextureName ) )
|
||
{
|
||
bool bRealMaterial = true;
|
||
|
||
if ( StringHasPrefix( pMat->GetName(), "debug/debugtexture" ) )
|
||
bRealMaterial = false;
|
||
|
||
if ( StringHasPrefix( pMat->GetName(), "maps/" ) )
|
||
{
|
||
// Format: maps/mapname/[matname]_x_y_z
|
||
bRealMaterial = false;
|
||
|
||
char chName[ MAX_PATH ];
|
||
Q_strncpy( chName, pMat->GetName() + 5, sizeof( chName ) - 1 );
|
||
|
||
if ( char *szMatName = strchr( chName, '/' ) )
|
||
{
|
||
++ szMatName;
|
||
for ( int k = 0; k < 3; ++ k )
|
||
{
|
||
if ( char *rUnderscore = strrchr( szMatName, '_' ) )
|
||
*rUnderscore = 0;
|
||
}
|
||
|
||
sprintf( szMatName + strlen( szMatName ), " (cubemap)" );
|
||
arrMaterials[ szMatName ] = true;
|
||
}
|
||
arrMaterialsFullNames[ pMat->GetName() ] = true;
|
||
}
|
||
|
||
if ( bRealMaterial )
|
||
{
|
||
arrMaterials[ pMat->GetName() ] = true;
|
||
arrMaterialsFullNames[ pMat->GetName() ] = true;
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Now that we have a list of materials make a printable version
|
||
CUtlBuffer bufText( 0, 0, CUtlBuffer::TEXT_BUFFER );
|
||
|
||
if ( !arrMaterials.GetNumStrings() )
|
||
{
|
||
bufText.Printf( "-- no materials --" );
|
||
}
|
||
else
|
||
{
|
||
int c = arrMaterials.GetNumStrings();
|
||
bufText.Printf( " %d material%s:", c, ( c%10 == 1 && c != 11 ) ? "" : "s" );
|
||
}
|
||
|
||
for ( int k = 0; k < arrMaterials.GetNumStrings(); ++ k )
|
||
{
|
||
bufText.Printf( "\n%s", arrMaterials.String( k ) );
|
||
}
|
||
|
||
// Set text except for the cases when m_pInfo and no materials found
|
||
if ( !( m_pInfo && !arrMaterials.GetNumStrings() ) )
|
||
{
|
||
m_pMaterials->SetText( ( char const * ) bufText.Base() );
|
||
|
||
m_lstMaterials.RemoveAll();
|
||
m_lstMaterials.EnsureCapacity( arrMaterialsFullNames.GetNumStrings() );
|
||
for ( int k = 0; k < arrMaterialsFullNames.GetNumStrings(); ++ k )
|
||
{
|
||
m_lstMaterials.AddToTail( CUtlSymbol( arrMaterialsFullNames.String( k ) ) );
|
||
}
|
||
}
|
||
|
||
m_bufInfoText.Clear();
|
||
|
||
InvalidateLayout();
|
||
}
|
||
|
||
void CRenderTextureEditor::Close()
|
||
{
|
||
BaseClass::Close();
|
||
|
||
SetDispInfo( NULL, 0 );
|
||
}
|
||
|
||
void CRenderTextureEditor::Activate()
|
||
{
|
||
BaseClass::Activate();
|
||
}
|
||
|
||
void CRenderTextureEditor::PerformLayout()
|
||
{
|
||
BaseClass::PerformLayout();
|
||
|
||
int iRenderedHeight = 4 * TILE_BORDER + TILE_TEXT + TILE_SIZE;
|
||
|
||
SetSize( 4 * TILE_BORDER + TILE_SIZE,
|
||
iRenderedHeight + 90 + TILE_BORDER );
|
||
|
||
m_pMaterials->SetPos( TILE_BORDER, iRenderedHeight + 2 );
|
||
m_pMaterials->SetSize( 2 * TILE_BORDER + TILE_SIZE, 90 );
|
||
|
||
m_pExplore->SetPos( 2 * TILE_BORDER + TILE_SIZE - 50, 2 * TILE_BORDER );
|
||
m_pExplore->SetWide( 50 );
|
||
|
||
m_pReload->SetPos( 2 * TILE_BORDER + TILE_SIZE - 50 - 65, 2 * TILE_BORDER );
|
||
m_pReload->SetWide( 60 );
|
||
m_pReload->SetVisible( m_lstMaterials.Count() > 0 );
|
||
|
||
m_pExplore->SetVisible( false );
|
||
m_pSizeControls[0]->SetVisible( false );
|
||
m_pSizeControls[1]->SetVisible( false );
|
||
m_pSizeControls[2]->SetVisible( false );
|
||
|
||
if ( m_pInfo )
|
||
{
|
||
char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
|
||
Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vtf", m_pInfo->GetString( KEYNAME_NAME ) );
|
||
char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
|
||
if ( szResolvedName )
|
||
{
|
||
m_pExplore->SetVisible( true );
|
||
}
|
||
|
||
char const *szKeyName = m_pInfo->GetString( KEYNAME_NAME );
|
||
|
||
if ( !m_pInfo->GetInt( "SpecialTx" ) )
|
||
{
|
||
m_pSizeControls[0]->SetVisible( true );
|
||
m_pSizeControls[1]->SetVisible( true );
|
||
|
||
if ( CanAdjustTextureExclude( szKeyName ) )
|
||
{
|
||
m_pSizeControls[2]->SetVisible( true );
|
||
m_pSizeControls[2]->SetSelected( IsTextureExcluded( szKeyName ) );
|
||
}
|
||
|
||
m_pSizeControls[0]->SetEnabled( CanAdjustTextureSize( szKeyName, false ) );
|
||
m_pSizeControls[1]->SetEnabled( CanAdjustTextureSize( szKeyName, true ) );
|
||
|
||
int posX, posY;
|
||
m_pExplore->GetPos( posX, posY );
|
||
m_pSizeControls[0]->SetPos( posX, posY + m_pExplore->GetTall() + 1 );
|
||
m_pSizeControls[0]->SetWide( m_pExplore->GetWide() / 2 );
|
||
m_pSizeControls[1]->SetPos( posX + m_pSizeControls[0]->GetWide() + 1, posY + m_pExplore->GetTall() + 1 );
|
||
m_pSizeControls[1]->SetWide( m_pExplore->GetWide() - ( m_pSizeControls[0]->GetWide() + 1 ) );
|
||
|
||
int iExcludeWidth = 80;
|
||
m_pSizeControls[2]->SetPos( posX - iExcludeWidth - 1, posY + m_pExplore->GetTall() + 1 );
|
||
m_pSizeControls[2]->SetWide( iExcludeWidth );
|
||
}
|
||
}
|
||
|
||
{
|
||
int posX, posY;
|
||
m_pExplore->GetPos( posX, posY );
|
||
posY += m_pExplore->GetTall() * 2 + 2;
|
||
posX += m_pExplore->GetWide();
|
||
|
||
posX -= 80;
|
||
m_pCopyImg->SetPos( posX, posY );
|
||
m_pCopyImg->SetWide( 80 );
|
||
|
||
posX -= 80 + 5;
|
||
m_pCopyTxt->SetPos( posX, posY );
|
||
m_pCopyTxt->SetWide( 80 );
|
||
|
||
posX -= 95 + 5;
|
||
m_pFlashBtn->SetPos( posX, posY );
|
||
m_pFlashBtn->SetWide( 95 );
|
||
}
|
||
}
|
||
|
||
void CRenderTextureEditor::OnCommand( const char *command )
|
||
{
|
||
BaseClass::OnCommand( command );
|
||
|
||
MatTextureModificationRecorded();
|
||
|
||
if ( !stricmp( command, "Explore" ) && m_pInfo )
|
||
{
|
||
char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
|
||
Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vtf", m_pInfo->GetString( KEYNAME_NAME ) );
|
||
char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
|
||
|
||
char params[256];
|
||
Q_snprintf( params, sizeof( params ) - 1, "/E,/SELECT,%s", szResolvedName );
|
||
vgui::system()->ShellExecuteEx( "open", "explorer.exe", params );
|
||
}
|
||
|
||
if ( !stricmp( command, "Reload" ) && m_lstMaterials.Count() )
|
||
{
|
||
CUtlBuffer bufCommand( 0, 0, CUtlBuffer::TEXT_BUFFER );
|
||
int idxMaterial = 0;
|
||
|
||
//
|
||
// Issue the console command several times in case we overflow the
|
||
// console command buffer size.
|
||
//
|
||
Cbuf_Execute();
|
||
for ( ; idxMaterial < m_lstMaterials.Count(); )
|
||
{
|
||
int iOldIdx = idxMaterial;
|
||
bufCommand.Printf( "mat_reloadmaterial \"" );
|
||
|
||
for ( ; idxMaterial < m_lstMaterials.Count(); ++ idxMaterial )
|
||
{
|
||
int iOldSize = bufCommand.TellPut();
|
||
int const iSizeLimit = CCommand::MaxCommandLength() - 3;
|
||
|
||
char const *szString = CUtlSymbol( m_lstMaterials[idxMaterial] ).String();
|
||
bufCommand.Printf( "%s%s", ( idxMaterial > iOldIdx ) ? "*" : "", szString );
|
||
|
||
if ( bufCommand.TellPut() > iSizeLimit &&
|
||
idxMaterial > iOldIdx )
|
||
{
|
||
bufCommand.SeekPut( CUtlBuffer::SEEK_HEAD, iOldSize );
|
||
break;
|
||
}
|
||
}
|
||
|
||
bufCommand.Printf( "\"\n" );
|
||
bufCommand.PutChar( 0 );
|
||
|
||
Cbuf_AddText( Cbuf_GetCurrentPlayer(), ( char const * ) bufCommand.Base() );
|
||
bufCommand.Clear();
|
||
Cbuf_Execute();
|
||
}
|
||
}
|
||
|
||
if ( !stricmp( command, "CopyTxt" ) )
|
||
{
|
||
char const *szName = ( char const * ) m_bufInfoText.Base();
|
||
if ( !m_bufInfoText.TellPut() || !szName )
|
||
szName = "";
|
||
vgui::system()->SetClipboardText( szName, strlen( szName ) + 1 );
|
||
}
|
||
|
||
if ( !stricmp( command, "CopyImg" ) )
|
||
{
|
||
int x = 0, y = 0;
|
||
this->LocalToScreen( x, y );
|
||
|
||
void *pMainWnd = game->GetMainWindow();
|
||
vgui::system()->SetClipboardImage( pMainWnd, x, y, x + GetWide(), y + GetTall() );
|
||
}
|
||
|
||
if ( !stricmp( command, "FlashBtn" ) )
|
||
{
|
||
MatViewOverride::RequestSelectNone();
|
||
MatViewOverride::RequestSelected( m_lstMaterials.Count(), m_lstMaterials.Base() );
|
||
mat_texture_list_off_f();
|
||
}
|
||
|
||
if ( ( !stricmp( command, "size-" ) || !stricmp( command, "size+" ) ) && m_pInfo )
|
||
{
|
||
bool bSizeUp = ( command[4] == '+' );
|
||
bool bResult = AdjustTextureSize( m_pInfo->GetString( KEYNAME_NAME ), bSizeUp );
|
||
if ( bResult )
|
||
{
|
||
CAutoPushPop<bool> auto_g_bRecursiveRequestToShowTextureList( g_bRecursiveRequestToShowTextureList, true );
|
||
mat_texture_list_on_f();
|
||
}
|
||
|
||
InvalidateLayout();
|
||
}
|
||
|
||
if ( !stricmp( command, "Exclude" ) )
|
||
{
|
||
bool bExclude = m_pSizeControls[2]->IsSelected();
|
||
bool bResult = AdjustTextureExclude( m_pInfo->GetString( KEYNAME_NAME ), bExclude );
|
||
if ( bResult )
|
||
{
|
||
CAutoPushPop<bool> auto_g_bRecursiveRequestToShowTextureList( g_bRecursiveRequestToShowTextureList, true );
|
||
mat_texture_list_on_f();
|
||
}
|
||
|
||
InvalidateLayout();
|
||
}
|
||
}
|
||
|
||
void CRenderTextureEditor::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
{
|
||
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
||
SetFont( pScheme->GetFont( "Default", IsProportional() ) );
|
||
}
|
||
|
||
void CRenderTextureEditor::OnMousePressed( vgui::MouseCode code )
|
||
{
|
||
Close();
|
||
}
|
||
|
||
void CRenderTextureEditor::Paint()
|
||
{
|
||
CAutoMatSysDebugMode auto_matsysdebugmode;
|
||
|
||
DisableFadeEffect();
|
||
SetBgColor( Color( 10, 50, 10, 255 ) );
|
||
|
||
BaseClass::Paint();
|
||
|
||
KeyValues *kv = m_pInfo;
|
||
if ( !kv )
|
||
return;
|
||
|
||
char const *szTextureFile = kv->GetString( KEYNAME_NAME );
|
||
Q_strncpy( s_chLastViewedTextureBuffer, szTextureFile, sizeof( s_chLastViewedTextureBuffer ) );
|
||
char const *szTextureGroup = kv->GetString( KEYNAME_TEXTURE_GROUP );
|
||
|
||
ITexture *pMatTexture = NULL;
|
||
if ( *szTextureFile )
|
||
pMatTexture = materials->FindTexture( szTextureFile, szTextureGroup, false );
|
||
if ( !pMatTexture )
|
||
pMatTexture = materials->FindTexture( "debugempty", "", false );
|
||
|
||
// Determine the texture size
|
||
int iTxWidth = kv->GetInt( KEYNAME_WIDTH );
|
||
int iTxHeight = kv->GetInt( KEYNAME_HEIGHT );
|
||
int iTxSize = kv->GetInt( KEYNAME_SIZE );
|
||
char const *szTxFormat = kv->GetString( KEYNAME_FORMAT );
|
||
|
||
int x = TILE_BORDER, y = TILE_BORDER;
|
||
|
||
// Dimensions to draw
|
||
int iDrawWidth = iTxWidth;
|
||
int iDrawHeight = iTxHeight;
|
||
|
||
if ( pMatTexture && pMatTexture->IsCubeMap() )
|
||
{
|
||
iDrawWidth = 1024;
|
||
iDrawHeight = 1024;
|
||
}
|
||
|
||
if ( iDrawHeight >= iDrawWidth )
|
||
{
|
||
if ( iDrawHeight > TILE_TEXTURE_SIZE )
|
||
{
|
||
iDrawWidth = iDrawWidth * ( float( TILE_TEXTURE_SIZE ) / iDrawHeight );
|
||
iDrawHeight = TILE_TEXTURE_SIZE;
|
||
}
|
||
|
||
if ( iDrawHeight < 64 )
|
||
{
|
||
iDrawWidth = iDrawWidth * ( float( 64 ) / iDrawHeight );
|
||
iDrawHeight = 64;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( iDrawWidth > TILE_TEXTURE_SIZE )
|
||
{
|
||
iDrawHeight = iDrawHeight * ( float( TILE_TEXTURE_SIZE ) / iDrawWidth );
|
||
iDrawWidth = TILE_TEXTURE_SIZE;
|
||
}
|
||
|
||
if ( iDrawWidth < 64 )
|
||
{
|
||
iDrawHeight = iDrawHeight * ( float( 64 ) / iDrawWidth );
|
||
iDrawWidth = 64;
|
||
}
|
||
}
|
||
|
||
iDrawHeight = iDrawHeight / ( float( TILE_TEXTURE_SIZE ) / float( TILE_SIZE ) );
|
||
iDrawWidth = iDrawWidth / ( float( TILE_TEXTURE_SIZE ) / float( TILE_SIZE ) );
|
||
|
||
iDrawHeight = MAX( iDrawHeight, 4 );
|
||
iDrawWidth = MAX( iDrawWidth, 4 );
|
||
|
||
//
|
||
// Draw frame
|
||
//
|
||
{
|
||
int tileWidth = 2 * TILE_BORDER + TILE_SIZE;
|
||
int tileHeight = 3 * TILE_BORDER + TILE_SIZE + TILE_TEXT;
|
||
|
||
g_pMatSystemSurface->DrawSetColor( 255, 255, 255, 255 );
|
||
g_pMatSystemSurface->DrawOutlinedRect( x + 1, y + 1,
|
||
x + tileWidth - 2 , y + tileHeight - 2 );
|
||
}
|
||
|
||
//
|
||
// Draw all
|
||
//
|
||
|
||
x += TILE_BORDER;
|
||
y += TILE_BORDER;
|
||
|
||
char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
|
||
Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vtf", szTextureFile );
|
||
char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
|
||
|
||
char const *szPrintFilePrefix = szResolvedName ? "" : "[?]/";
|
||
char const *szPrintFileName = szResolvedName ? szResolvedName : szTextureFile;
|
||
|
||
char chSizeBuf[20] = { 0 };
|
||
if ( iTxSize >= 0 )
|
||
FmtCommaNumber( chSizeBuf, iTxSize );
|
||
else
|
||
chSizeBuf[0] = '-';
|
||
|
||
g_pMatSystemSurface->DrawColoredTextRect( GetFont(), x, y, TILE_SIZE, TILE_TEXT / 2,
|
||
255, 255, 255, 255,
|
||
"%s%s\n"
|
||
"%s Kb %dx%d %s",
|
||
szPrintFilePrefix, szPrintFileName,
|
||
chSizeBuf,
|
||
iTxWidth, iTxHeight,
|
||
szTxFormat
|
||
);
|
||
|
||
if ( !m_bufInfoText.TellPut() )
|
||
{
|
||
m_bufInfoText.Printf(
|
||
"%s%s\r\n"
|
||
"%s Kb %dx%d %s",
|
||
szPrintFilePrefix, szPrintFileName,
|
||
chSizeBuf,
|
||
iTxWidth, iTxHeight,
|
||
szTxFormat );
|
||
}
|
||
|
||
if ( !kv->GetInt( "SpecialTx" ) )
|
||
{
|
||
char chLine1[256] = {0};
|
||
char chLine2[256] = {0};
|
||
|
||
//
|
||
// Line 1
|
||
//
|
||
if ( iTxSize > g_warn_texkbytes )
|
||
sprintf( chLine1 + strlen( chLine1 ), " Size(%s Kb)", chSizeBuf );
|
||
if ( ( iTxWidth > g_warn_texdimensions ) ||
|
||
( iTxHeight > g_warn_texdimensions ) )
|
||
sprintf( chLine1 + strlen( chLine1 ), " Dimensions(%dx%d)", iTxWidth, iTxHeight );
|
||
if ( stricmp( szTxFormat, "DXT1" ) &&
|
||
stricmp( szTxFormat, "DXT5" ) )
|
||
sprintf( chLine1 + strlen( chLine1 ), " Format(%s)", szTxFormat );
|
||
if ( pMatTexture->GetFlags() & TEXTUREFLAGS_NOLOD )
|
||
sprintf( chLine1 + strlen( chLine1 ), " NoLod" );
|
||
if ( pMatTexture->GetFlags() & TEXTUREFLAGS_NOMIP )
|
||
sprintf( chLine1 + strlen( chLine1 ), " NoMip" );
|
||
if ( pMatTexture->GetFlags() & TEXTUREFLAGS_ONEBITALPHA )
|
||
sprintf( chLine1 + strlen( chLine1 ), " OneBitAlpha" );
|
||
if ( pMatTexture->IsVolumeTexture() )
|
||
sprintf( chLine1 + strlen( chLine1 ), " Volume" );
|
||
|
||
//
|
||
// Line 2
|
||
//
|
||
// Always show stats for higher/lower mips
|
||
{
|
||
int wmap = pMatTexture->GetMappingWidth(), hmap = pMatTexture->GetMappingHeight(), dmap = pMatTexture->GetMappingDepth();
|
||
int wact = pMatTexture->GetActualWidth(), hact = pMatTexture->GetActualHeight(), dact = pMatTexture->GetActualDepth();
|
||
ImageFormat fmt = pMatTexture->GetImageFormat();
|
||
|
||
if ( wact > 4 || hact > 4 )
|
||
{
|
||
char chbuf[50];
|
||
int mem = ImageLoader::GetMemRequired( MAX( MIN( wact, 4 ), wact / 2 ), MAX( MIN( hact, 4 ), hact / 2 ), MAX( 1, dact / 2 ), fmt, true );
|
||
mem = ( mem + 511 ) / 1024;
|
||
FmtCommaNumber( chbuf, mem );
|
||
|
||
sprintf ( chLine2 + strlen( chLine2 ), " %s Kb @ lower mip", chbuf );
|
||
}
|
||
|
||
if ( wmap > wact || hmap > hact || dmap > dact )
|
||
{
|
||
char chbuf[ 50 ];
|
||
int mem = ImageLoader::GetMemRequired( MIN( wmap, wact * 2 ), MIN( hmap, hact * 2 ), MIN( dmap, dact * 2 ), fmt, true );
|
||
mem = ( mem + 511 ) / 1024;
|
||
FmtCommaNumber( chbuf, mem );
|
||
|
||
sprintf ( chLine2 + strlen( chLine2 ), " %s Kb @ higher mip", chbuf );
|
||
}
|
||
}
|
||
|
||
if ( chLine1[0] )
|
||
{
|
||
g_pMatSystemSurface->DrawSetColor( 200, 0, 0, 255 );
|
||
g_pMatSystemSurface->DrawFilledRect( x - TILE_BORDER/2, y + TILE_TEXT/2, x + TILE_BORDER/2 + TILE_SIZE, y + TILE_TEXT/2 + TILE_TEXT/4 );
|
||
g_pMatSystemSurface->DrawColoredTextRect( GetFont(), x, y + TILE_TEXT/2, TILE_SIZE, TILE_TEXT / 4,
|
||
255, 255, 255, 255,
|
||
"%s", chLine1 );
|
||
}
|
||
if ( chLine2[0] )
|
||
{
|
||
// g_pMatSystemSurface->DrawSetColor( 200, 0, 0, 255 );
|
||
// g_pMatSystemSurface->DrawFilledRect( x - TILE_BORDER/2, y + TILE_TEXT/2 + TILE_TEXT/4, x + TILE_BORDER/2 + TILE_SIZE, y + TILE_TEXT );
|
||
g_pMatSystemSurface->DrawColoredTextRect( GetFont(), x, y + TILE_TEXT/2 + TILE_TEXT/4, TILE_SIZE, TILE_TEXT / 4,
|
||
255, 255, 255, 255,
|
||
"%s", chLine2 );
|
||
}
|
||
}
|
||
|
||
y += TILE_TEXT + TILE_BORDER;
|
||
|
||
// Images placement
|
||
bool bHasAlpha = !!stricmp( szTxFormat, "DXT1" );
|
||
|
||
int extTxWidth = TILE_SIZE;
|
||
int extTxHeight = TILE_SIZE;
|
||
|
||
int orgTxX = 0, orgTxXA = 0;
|
||
int orgTxY = 0, orgTxYA = 0;
|
||
|
||
if ( bHasAlpha )
|
||
{
|
||
if ( iTxWidth >= iTxHeight * 2 )
|
||
{
|
||
extTxHeight /= 2;
|
||
orgTxYA = extTxHeight + TILE_BORDER/2;
|
||
extTxHeight -= 1;
|
||
}
|
||
else if ( iTxHeight >= iTxWidth * 2 )
|
||
{
|
||
extTxWidth /= 2;
|
||
orgTxXA = extTxWidth + TILE_BORDER/2;
|
||
extTxWidth -= 3;
|
||
}
|
||
else
|
||
{
|
||
extTxHeight /= 2;
|
||
orgTxYA = extTxHeight + TILE_BORDER/2;
|
||
orgTxX = extTxWidth / 4;
|
||
extTxWidth /= 2;
|
||
|
||
if ( iDrawWidth > extTxWidth )
|
||
{
|
||
iDrawWidth /= 2;
|
||
iDrawHeight /= 2;
|
||
}
|
||
extTxWidth -= 1;
|
||
extTxHeight -= 1;
|
||
}
|
||
}
|
||
|
||
enum { IMG_FRAME_OFF = 2 };
|
||
if ( IMaterial *pMaterial = UseDebugMaterial( "debug/debugtexturecolor", pMatTexture, &auto_matsysdebugmode ) )
|
||
{
|
||
g_pMatSystemSurface->DrawSetColor( 255, 255, 255, 255 );
|
||
g_pMatSystemSurface->DrawOutlinedRect( x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
|
||
RenderTexturedRect( this, pMaterial,
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 );
|
||
|
||
if ( bHasAlpha )
|
||
{
|
||
orgTxX += orgTxXA;
|
||
orgTxY += orgTxYA;
|
||
if ( IMaterial *pMaterial = UseDebugMaterial( "debug/debugtexturealpha", pMatTexture, &auto_matsysdebugmode ) )
|
||
{
|
||
g_pMatSystemSurface->DrawOutlinedRect( x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
|
||
RenderTexturedRect( this, pMaterial,
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 );
|
||
}
|
||
|
||
orgTxX -= orgTxXA;
|
||
orgTxY -= orgTxYA;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
g_pMatSystemSurface->DrawSetColor( 255, 0, 255, 100 );
|
||
g_pMatSystemSurface->DrawFilledRect(
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxWidth - iDrawHeight ) / 2,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxWidth + iDrawHeight ) / 2 );
|
||
}
|
||
|
||
if ( IsTextureExcluded( szTextureFile ) )
|
||
{
|
||
g_pMatSystemSurface->DrawSetColor( 200, 0, 0, 255 );
|
||
g_pMatSystemSurface->DrawFilledRect(
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF,
|
||
y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF,
|
||
y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
|
||
|
||
g_pMatSystemSurface->DrawColoredTextRect( GetFont(),
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2,
|
||
y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
|
||
iDrawWidth,
|
||
iDrawHeight,
|
||
255, 255, 255, 255,
|
||
"EXCLUDED"
|
||
);
|
||
}
|
||
|
||
y += TILE_SIZE + TILE_BORDER;
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// Render textures view panel
|
||
//
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
class CRenderTexturesListViewPanel : public vgui::TileViewPanelEx
|
||
{
|
||
DECLARE_CLASS_SIMPLE( CRenderTexturesListViewPanel, vgui::TileViewPanelEx );
|
||
|
||
public:
|
||
CRenderTexturesListViewPanel( vgui::Panel *parent, char const *szName );
|
||
~CRenderTexturesListViewPanel();
|
||
|
||
protected:
|
||
virtual int GetNumTiles();
|
||
virtual void GetTileSize( int &wide, int &tall );
|
||
virtual void RenderTile( int iTile, int x, int y );
|
||
|
||
protected:
|
||
virtual void PerformLayout();
|
||
virtual void OnMousePressed( vgui::MouseCode code );
|
||
virtual void OnMouseDoublePressed( vgui::MouseCode code ) { OnMousePressed( code ); }
|
||
|
||
public:
|
||
void SetDataListPanel( vgui::ListPanel *pPanel );
|
||
void SetPaintAlpha( bool bPaintAlpha );
|
||
|
||
CRenderTextureEditor * GetRenderTxEditor() const { return m_pRenderTxEditor; }
|
||
|
||
protected:
|
||
vgui::ListPanel *m_pListPanel;
|
||
KeyValues * GetTileData( int iTile );
|
||
|
||
protected:
|
||
CRenderTextureEditor *m_pRenderTxEditor;
|
||
|
||
protected:
|
||
enum
|
||
{
|
||
TILE_BORDER = 20,
|
||
TILE_SIZE = 192,
|
||
TILE_TEXTURE_SIZE = 256,
|
||
TILE_TEXT = 35
|
||
};
|
||
|
||
bool m_bPaintAlpha;
|
||
};
|
||
|
||
CRenderTexturesListViewPanel::CRenderTexturesListViewPanel( vgui::Panel *parent, char const *szName ) :
|
||
vgui::TileViewPanelEx( parent, szName ),
|
||
m_pListPanel( NULL ),
|
||
m_bPaintAlpha( false )
|
||
{
|
||
m_pRenderTxEditor = new CRenderTextureEditor( this, "TxEdt" );
|
||
m_pRenderTxEditor->SetPos( 10, 10 );
|
||
m_pRenderTxEditor->PerformLayout();
|
||
m_pRenderTxEditor->SetMoveable( true );
|
||
m_pRenderTxEditor->SetSizeable( false );
|
||
m_pRenderTxEditor->SetClipToParent( true );
|
||
m_pRenderTxEditor->SetTitle( "", true );
|
||
m_pRenderTxEditor->SetCloseButtonVisible( false );
|
||
m_pRenderTxEditor->SetVisible( false );
|
||
}
|
||
|
||
CRenderTexturesListViewPanel::~CRenderTexturesListViewPanel()
|
||
{
|
||
NULL;
|
||
}
|
||
|
||
void CRenderTexturesListViewPanel::PerformLayout()
|
||
{
|
||
BaseClass::PerformLayout();
|
||
}
|
||
|
||
void CRenderTexturesListViewPanel::OnMousePressed( vgui::MouseCode code )
|
||
{
|
||
BaseClass::OnMousePressed( code );
|
||
|
||
// Figure out which tile got hit and pass its data for preview
|
||
m_pRenderTxEditor->Close();
|
||
|
||
if ( !m_pListPanel )
|
||
return;
|
||
|
||
int x, y;
|
||
vgui::input()->GetCursorPos( x, y );
|
||
this->ScreenToLocal( x, y );
|
||
|
||
// Hit test the click
|
||
int iTile, tileX, tileY;
|
||
int htResult = HitTest( x, y, iTile );
|
||
if ( HT_NOTHING == htResult )
|
||
return;
|
||
if ( !GetTileOrg( iTile, tileX, tileY ) )
|
||
return;
|
||
|
||
// Now having the tile retrieve the keyvalues
|
||
int itemId = m_pListPanel->GetItemIDFromRow( iTile );
|
||
if ( itemId < 0 )
|
||
return;
|
||
KeyValues *kv = m_pListPanel->GetItem( itemId );
|
||
if ( !kv )
|
||
return;
|
||
|
||
// Display the tx editor
|
||
m_pRenderTxEditor->SetDispInfo( kv, itemId );
|
||
|
||
if ( tileX + m_pRenderTxEditor->GetWide() > m_li_wide - 2 )
|
||
tileX -= tileX + m_pRenderTxEditor->GetWide() - ( m_li_wide - 2 );
|
||
if ( tileY + m_pRenderTxEditor->GetTall() > m_li_tall - 2 )
|
||
tileY -= tileY + m_pRenderTxEditor->GetTall() - ( m_li_tall - 2 );
|
||
|
||
int iTopLeftX = 0, iTopLeftY = 0;
|
||
for ( vgui::Panel *pPanel = this; ( pPanel = pPanel->GetParent() ) != NULL; )
|
||
{
|
||
iTopLeftX = iTopLeftY = 0;
|
||
pPanel->LocalToScreen( iTopLeftX, iTopLeftY );
|
||
}
|
||
|
||
LocalToScreen( tileX, tileY );
|
||
if ( tileX < iTopLeftX ) tileX = iTopLeftX;
|
||
if ( tileY < iTopLeftY ) tileY = iTopLeftY;
|
||
|
||
m_pRenderTxEditor->SetPos( tileX, tileY );
|
||
m_pRenderTxEditor->Activate();
|
||
}
|
||
|
||
int CRenderTexturesListViewPanel::GetNumTiles()
|
||
{
|
||
return m_pListPanel ? m_pListPanel->GetItemCount() : 0;
|
||
}
|
||
|
||
void CRenderTexturesListViewPanel::GetTileSize( int &wide, int &tall )
|
||
{
|
||
wide = 2 * TILE_BORDER + TILE_SIZE;
|
||
tall = 2 * TILE_BORDER + TILE_SIZE + TILE_TEXT;
|
||
};
|
||
|
||
KeyValues * CRenderTexturesListViewPanel::GetTileData( int iTile )
|
||
{
|
||
int iData = m_pListPanel->GetItemIDFromRow( iTile );
|
||
if ( iData < 0 )
|
||
return NULL;
|
||
|
||
return m_pListPanel->GetItem( iData );
|
||
}
|
||
|
||
void CRenderTexturesListViewPanel::RenderTile( int iTile, int x, int y )
|
||
{
|
||
CAutoMatSysDebugMode auto_matsysdebugmode;
|
||
|
||
KeyValues *kv = GetTileData( iTile );
|
||
if ( !kv )
|
||
return;
|
||
|
||
char const *szTextureFile = kv->GetString( KEYNAME_NAME );
|
||
char const *szTextureGroup = kv->GetString( KEYNAME_TEXTURE_GROUP );
|
||
ITexture *pMatTexture = NULL;
|
||
if ( *szTextureFile )
|
||
pMatTexture = materials->FindTexture( szTextureFile, szTextureGroup, false );
|
||
if ( !pMatTexture )
|
||
pMatTexture = materials->FindTexture( "debugempty", "", false );
|
||
|
||
// Determine the texture size
|
||
int iTxWidth = kv->GetInt( KEYNAME_WIDTH );
|
||
int iTxHeight = kv->GetInt( KEYNAME_HEIGHT );
|
||
int iTxSize = kv->GetInt( KEYNAME_SIZE );
|
||
char const *szTxFormat = kv->GetString( KEYNAME_FORMAT );
|
||
|
||
int iTxFormatLen = strlen( szTxFormat );
|
||
char *szTxFormatSuffix = "";
|
||
if ( iTxFormatLen > 4 )
|
||
{
|
||
fmtlenreduce:
|
||
switch ( szTxFormat[ iTxFormatLen - 1 ] )
|
||
{
|
||
case '8':
|
||
{
|
||
while ( ( iTxFormatLen > 4 ) &&
|
||
( szTxFormat[ iTxFormatLen - 2 ] == '8' ) )
|
||
-- iTxFormatLen;
|
||
}
|
||
break;
|
||
case '6':
|
||
{
|
||
while ( ( iTxFormatLen > 4 ) &&
|
||
( szTxFormat[ iTxFormatLen - 2 ] == '1' ) &&
|
||
( szTxFormat[ iTxFormatLen - 3 ] == '6' ) )
|
||
iTxFormatLen -= 2;
|
||
}
|
||
break;
|
||
case 'F':
|
||
if ( !*szTxFormatSuffix )
|
||
{
|
||
iTxFormatLen --;
|
||
szTxFormatSuffix = "F";
|
||
goto fmtlenreduce;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Dimensions to draw
|
||
int iDrawWidth = iTxWidth;
|
||
int iDrawHeight = iTxHeight;
|
||
|
||
if ( pMatTexture && pMatTexture->IsCubeMap() )
|
||
{
|
||
iDrawWidth = 1024;
|
||
iDrawHeight = 1024;
|
||
}
|
||
|
||
if ( iDrawHeight >= iDrawWidth )
|
||
{
|
||
if ( iDrawHeight > TILE_TEXTURE_SIZE )
|
||
{
|
||
iDrawWidth = iDrawWidth * ( float( TILE_TEXTURE_SIZE ) / iDrawHeight );
|
||
iDrawHeight = TILE_TEXTURE_SIZE;
|
||
}
|
||
|
||
if ( iDrawHeight < 64 )
|
||
{
|
||
iDrawWidth = iDrawWidth * ( float( 64 ) / iDrawHeight );
|
||
iDrawHeight = 64;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( iDrawWidth > TILE_TEXTURE_SIZE )
|
||
{
|
||
iDrawHeight = iDrawHeight * ( float( TILE_TEXTURE_SIZE ) / iDrawWidth );
|
||
iDrawWidth = TILE_TEXTURE_SIZE;
|
||
}
|
||
|
||
if ( iDrawWidth < 64 )
|
||
{
|
||
iDrawHeight = iDrawHeight * ( float( 64 ) / iDrawWidth );
|
||
iDrawWidth = 64;
|
||
}
|
||
}
|
||
|
||
iDrawHeight = iDrawHeight / ( float( TILE_TEXTURE_SIZE ) / float( TILE_SIZE ) );
|
||
iDrawWidth = iDrawWidth / ( float( TILE_TEXTURE_SIZE ) / float( TILE_SIZE ) );
|
||
|
||
iDrawHeight = MAX( iDrawHeight, 4 );
|
||
iDrawWidth = MAX( iDrawWidth, 4 );
|
||
|
||
//
|
||
// Draw frame
|
||
//
|
||
{
|
||
int tileWidth, tileHeight;
|
||
GetTileSize( tileWidth, tileHeight );
|
||
g_pMatSystemSurface->DrawSetColor( 255, 255, 255, 255 );
|
||
g_pMatSystemSurface->DrawOutlinedRect( x + 1, y + 1,
|
||
x + tileWidth - 2 , y + tileHeight - 2 );
|
||
}
|
||
|
||
//
|
||
// Draw all
|
||
//
|
||
|
||
x += TILE_BORDER;
|
||
y += TILE_BORDER/2;
|
||
|
||
int iLenFile = strlen( szTextureFile );
|
||
char const *szPrintFilePrefix = ( iLenFile > 22 ) ? "..." : "";
|
||
char const *szPrintFileName = ( iLenFile > 22 ) ? ( szTextureFile + iLenFile - 22 ) : szTextureFile;
|
||
|
||
char chSizeBuf[20] = {0};
|
||
if ( iTxSize >= 0 )
|
||
{
|
||
FmtCommaNumber( chSizeBuf, iTxSize );
|
||
}
|
||
else
|
||
{
|
||
chSizeBuf[0] = '-';
|
||
}
|
||
|
||
static Color clrLblNormal( 25, 50, 25, 255 );
|
||
static Color clrLblWarn( 75, 75, 0, 255 );
|
||
static Color clrLblError( 200, 0, 0, 255 );
|
||
bool bWarnTile = ( !kv->GetInt( "SpecialTx" ) ) && ( g_warn_enable && ShallWarnTx( kv, pMatTexture ) );
|
||
g_pMatSystemSurface->DrawSetColor( bWarnTile ? clrLblWarn : clrLblNormal );
|
||
g_pMatSystemSurface->DrawFilledRect( x - TILE_BORDER/2, y, x + TILE_BORDER/2 + TILE_SIZE, y + TILE_TEXT );
|
||
|
||
char chInfoText[256] = { 0 };
|
||
sprintf( chInfoText, "%s Kb %dx%d %.*s%s %s",
|
||
chSizeBuf,
|
||
iTxWidth, iTxHeight,
|
||
iTxFormatLen, szTxFormat, szTxFormatSuffix,
|
||
( pMatTexture->GetFlags() & (
|
||
TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_ONEBITALPHA
|
||
) ) ? "***" : "" );
|
||
int iTextMargins[4] = { 0 };
|
||
int iTextHeight = g_pMatSystemSurface->GetFontTall( GetFont() );
|
||
{
|
||
// Compute text extents
|
||
int iTextLen[4] = { 0 };
|
||
iTextLen[0] = 5 + strlen( chSizeBuf );
|
||
iTextLen[1] = strchr( chInfoText, 'x' ) + 1 - chInfoText;
|
||
while ( chInfoText[ iTextLen[1] ] != ' ' )
|
||
++ iTextLen[1];
|
||
++ iTextLen[1];
|
||
iTextLen[2] = 2 + iTextLen[1] + iTxFormatLen + strlen( szTxFormatSuffix );
|
||
iTextLen[3] = strlen( chInfoText );
|
||
for ( int k = 0; k < 4; ++ k )
|
||
iTextMargins[k] = g_pMatSystemSurface->DrawTextLen( GetFont(), "%.*s", iTextLen[k], chInfoText );
|
||
}
|
||
|
||
// Highlights
|
||
if ( bWarnTile )
|
||
{
|
||
g_pMatSystemSurface->DrawSetColor( clrLblError );
|
||
if ( iTxSize > g_warn_texkbytes )
|
||
g_pMatSystemSurface->DrawFilledRect( x - 2, y + iTextHeight + 1, x + iTextMargins[0] - 5, y + TILE_TEXT );
|
||
if ( iTxWidth > g_warn_texdimensions || iTxHeight > g_warn_texdimensions )
|
||
g_pMatSystemSurface->DrawFilledRect( x + iTextMargins[0] - 2, y + iTextHeight + 1, x + iTextMargins[1] - 1, y + TILE_TEXT );
|
||
if ( strcmp( szTxFormat, "DXT1" ) && strcmp( szTxFormat, "DXT5" ) )
|
||
g_pMatSystemSurface->DrawFilledRect( x + iTextMargins[1] + 2, y + iTextHeight + 1, x + iTextMargins[2] - 1, y + TILE_TEXT );
|
||
if ( pMatTexture->GetFlags() & (
|
||
TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_ONEBITALPHA
|
||
) )
|
||
g_pMatSystemSurface->DrawFilledRect( x + iTextMargins[2] + 3, y + iTextHeight + 1, x + iTextMargins[3] + 2, y + TILE_TEXT );
|
||
}
|
||
|
||
g_pMatSystemSurface->DrawColoredTextRect( GetFont(), x, y, TILE_SIZE, TILE_TEXT,
|
||
255, 255, 255, 255,
|
||
"%s%s\n"
|
||
"%s",
|
||
szPrintFilePrefix, szPrintFileName,
|
||
chInfoText
|
||
);
|
||
|
||
y += TILE_TEXT + TILE_BORDER/2;
|
||
|
||
// Images placement
|
||
bool bHasAlpha = m_bPaintAlpha && stricmp( szTxFormat, "DXT1" );
|
||
|
||
int extTxWidth = TILE_SIZE;
|
||
int extTxHeight = TILE_SIZE;
|
||
|
||
int orgTxX = 0, orgTxXA = 0;
|
||
int orgTxY = 0, orgTxYA = 0;
|
||
|
||
if ( bHasAlpha )
|
||
{
|
||
if ( iTxWidth >= iTxHeight * 2 )
|
||
{
|
||
extTxHeight /= 2;
|
||
orgTxYA = extTxHeight + TILE_BORDER/2;
|
||
}
|
||
else if ( iTxHeight >= iTxWidth * 2 )
|
||
{
|
||
extTxWidth /= 2;
|
||
orgTxXA = extTxWidth + TILE_BORDER/2;
|
||
x -= TILE_BORDER/4 + 1;
|
||
}
|
||
else
|
||
{
|
||
extTxHeight /= 2;
|
||
orgTxYA = extTxHeight + TILE_BORDER/2;
|
||
orgTxX = extTxWidth / 4;
|
||
extTxWidth /= 2;
|
||
x -= TILE_BORDER/4 + 1;
|
||
|
||
if ( iDrawWidth > extTxWidth )
|
||
{
|
||
iDrawWidth /= 2;
|
||
iDrawHeight /= 2;
|
||
}
|
||
}
|
||
}
|
||
|
||
enum { IMG_FRAME_OFF = 2 };
|
||
if ( IMaterial *pMaterial = UseDebugMaterial( "debug/debugtexturecolor", pMatTexture, &auto_matsysdebugmode ) )
|
||
{
|
||
g_pMatSystemSurface->DrawSetColor( 255, 255, 255, 255 );
|
||
g_pMatSystemSurface->DrawOutlinedRect( x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
|
||
RenderTexturedRect( this, pMaterial,
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2,
|
||
2, 1 );
|
||
|
||
if ( bHasAlpha )
|
||
{
|
||
orgTxX += orgTxXA;
|
||
orgTxY += orgTxYA;
|
||
if ( IMaterial *pMaterial = UseDebugMaterial( "debug/debugtexturealpha", pMatTexture, &auto_matsysdebugmode ) )
|
||
{
|
||
g_pMatSystemSurface->DrawOutlinedRect( x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
|
||
RenderTexturedRect( this, pMaterial,
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxHeight + iDrawHeight ) / 2,
|
||
2, 1 );
|
||
}
|
||
|
||
orgTxX -= orgTxXA;
|
||
orgTxY -= orgTxYA;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
g_pMatSystemSurface->DrawSetColor( 255, 0, 255, 100 );
|
||
g_pMatSystemSurface->DrawFilledRect(
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2, y + orgTxY + ( extTxWidth - iDrawHeight ) / 2,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2, y + orgTxY + ( extTxWidth + iDrawHeight ) / 2 );
|
||
}
|
||
|
||
if ( IsTextureExcluded( szTextureFile ) )
|
||
{
|
||
g_pMatSystemSurface->DrawSetColor( 200, 0, 0, 255 );
|
||
g_pMatSystemSurface->DrawFilledRect(
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2 - IMG_FRAME_OFF,
|
||
y + orgTxY + ( extTxHeight - iDrawHeight ) / 2 - IMG_FRAME_OFF,
|
||
x + orgTxX + ( extTxWidth + iDrawWidth ) / 2 + IMG_FRAME_OFF,
|
||
y + orgTxY + ( extTxHeight + iDrawHeight ) / 2 + IMG_FRAME_OFF );
|
||
|
||
g_pMatSystemSurface->DrawColoredTextRect( GetFont(),
|
||
x + orgTxX + ( extTxWidth - iDrawWidth ) / 2,
|
||
y + orgTxY + ( extTxHeight - iDrawHeight ) / 2,
|
||
iDrawWidth,
|
||
iDrawHeight,
|
||
255, 255, 255, 255,
|
||
"-X-"
|
||
);
|
||
}
|
||
|
||
y += TILE_SIZE + TILE_BORDER;
|
||
}
|
||
|
||
void CRenderTexturesListViewPanel::SetDataListPanel( vgui::ListPanel *pPanel )
|
||
{
|
||
m_pListPanel = pPanel;
|
||
InvalidateLayout();
|
||
}
|
||
|
||
void CRenderTexturesListViewPanel::SetPaintAlpha( bool bPaintAlpha )
|
||
{
|
||
m_bPaintAlpha = bPaintAlpha;
|
||
Repaint();
|
||
}
|
||
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Shows entity status report if cl_entityreport cvar is set
|
||
//-----------------------------------------------------------------------------
|
||
class CTextureListPanel : public vgui::Frame
|
||
{
|
||
DECLARE_CLASS_SIMPLE( CTextureListPanel, vgui::Frame );
|
||
|
||
public:
|
||
// Construction
|
||
CTextureListPanel( vgui::Panel *parent );
|
||
virtual ~CTextureListPanel( void );
|
||
|
||
// Refresh
|
||
virtual void Paint();
|
||
void EndPaint(); // Still inside paint
|
||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||
virtual bool ShouldDraw();
|
||
virtual void PerformLayout();
|
||
virtual void Close();
|
||
|
||
void OnTurnedOn();
|
||
|
||
private:
|
||
|
||
void UpdateTotalUsageLabel();
|
||
virtual void OnCommand( const char *command );
|
||
MESSAGE_FUNC( OnTextChanged, "TextChanged" );
|
||
|
||
int AddListItem( KeyValues *kv );
|
||
|
||
bool UpdateDisplayedItem( KeyValues *pDispData, KeyValues *kv );
|
||
|
||
|
||
private:
|
||
|
||
// Font to use for drawing
|
||
vgui::HFont m_hFont;
|
||
vgui::ListPanel *m_pListPanel;
|
||
CRenderTexturesListViewPanel *m_pViewPanel;
|
||
|
||
vgui::CheckButton *m_pSpecialTexs;
|
||
vgui::CheckButton *m_pResolveTexturePath;
|
||
CConVarCheckButton *m_pShowTextureMemoryUsageOption;
|
||
CConVarCheckButton *m_pAllTextures;
|
||
CConVarCheckButton *m_pViewTextures;
|
||
vgui::Button *m_pCopyToClipboardButton;
|
||
vgui::ToggleButton *m_pCollapse;
|
||
vgui::CheckButton *m_pAlpha;
|
||
vgui::CheckButton *m_pThumbWarnings;
|
||
|
||
vgui::CheckButton *m_pFilteringChk;
|
||
vgui::TextEntry *m_pFilteringText;
|
||
int m_numDisplayedSizeKB;
|
||
|
||
vgui::Label *m_pCVarListLabel;
|
||
vgui::Label *m_pTotalUsageLabel;
|
||
};
|
||
|
||
|
||
static int __cdecl KilobytesSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
|
||
{
|
||
// Reverse sort order so the bigger textures show up first
|
||
const char *string1 = item1.kv->GetString( KEYNAME_SIZE );
|
||
const char *string2 = item2.kv->GetString( KEYNAME_SIZE );
|
||
int a = atoi( string1 );
|
||
int b = atoi( string2 );
|
||
if( a < b )
|
||
{
|
||
return 1;
|
||
}
|
||
if( a > b )
|
||
{
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
//
|
||
// Smart texture list
|
||
//
|
||
class CSmartTextureKeyValues
|
||
{
|
||
private:
|
||
CSmartTextureKeyValues( CSmartTextureKeyValues const &x );
|
||
CSmartTextureKeyValues& operator = ( CSmartTextureKeyValues const &x );
|
||
|
||
public:
|
||
CSmartTextureKeyValues() : m_p( NULL )
|
||
{
|
||
// Copy the texture list if it is available. It won't be availabe while it's being
|
||
// constructed on another thread. Remember to release when done.
|
||
if ( KeyValues *p = g_pMaterialSystemDebugTextureInfo->LockDebugTextureList() )
|
||
{
|
||
m_p = p->MakeCopy();
|
||
g_pMaterialSystemDebugTextureInfo->UnlockDebugTextureList();
|
||
}
|
||
}
|
||
~CSmartTextureKeyValues() { if ( m_p ) m_p->deleteThis(); m_p = NULL; }
|
||
|
||
KeyValues * Get() const { return m_p; };
|
||
|
||
protected:
|
||
KeyValues *m_p;
|
||
};
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Instances the entity report panel
|
||
// Input : *parent -
|
||
//-----------------------------------------------------------------------------
|
||
CTextureListPanel::CTextureListPanel( vgui::Panel *parent ) :
|
||
BaseClass( parent, "CTextureListPanel" ),
|
||
m_numDisplayedSizeKB( 0 )
|
||
{
|
||
// Need parent here, before loading up textures, so getSurfaceBase
|
||
// will work on this panel ( it's 0 otherwise )
|
||
SetSize( videomode->GetModeWidth() - 20, videomode->GetModeHeight() - 20 );
|
||
SetPos( 10, 10 );
|
||
SetVisible( true );
|
||
SetCursor( 0 );
|
||
|
||
SetTitle( "Texture list", false );
|
||
SetMenuButtonVisible( false );
|
||
|
||
m_hFont = vgui::INVALID_FONT;
|
||
|
||
SetFgColor( Color( 0, 0, 0, 255 ) );
|
||
SetPaintBackgroundEnabled( true );
|
||
|
||
// Init the buttons.
|
||
m_pCVarListLabel = vgui::SETUP_PANEL( new vgui::Label( this, "m_pCVarListLabel",
|
||
"cvars: mat_texture_limit, mat_texture_list, mat_picmip, mat_texture_list_txlod, mat_texture_list_txlod_sync" ) );
|
||
m_pCVarListLabel->SetVisible( false ); // m_pCVarListLabel->SetVisible( true );
|
||
|
||
m_pTotalUsageLabel = vgui::SETUP_PANEL( new vgui::Label( this, "m_pTotalUsageLabel", "" ) );
|
||
m_pTotalUsageLabel->SetVisible( true );
|
||
|
||
m_pSpecialTexs = vgui::SETUP_PANEL( new vgui::CheckButton( this, "service", "Render Targets and Special Textures" ) );
|
||
m_pSpecialTexs->SetVisible( true );
|
||
m_pSpecialTexs->AddActionSignalTarget( this );
|
||
m_pSpecialTexs->SetCommand( "service" );
|
||
|
||
m_pResolveTexturePath = vgui::SETUP_PANEL( new vgui::CheckButton( this, "resolvepath", "Resolve Full Texture Path" ) );
|
||
m_pResolveTexturePath->SetVisible( true );
|
||
m_pResolveTexturePath->AddActionSignalTarget( this );
|
||
m_pResolveTexturePath->SetCommand( "resolvepath" );
|
||
|
||
m_pShowTextureMemoryUsageOption = vgui::SETUP_PANEL( new CConVarCheckButton( this, "m_pShowTextureMemoryUsageOption", "Show Memory Usage on HUD" ) );
|
||
m_pShowTextureMemoryUsageOption->SetVisible( true );
|
||
m_pShowTextureMemoryUsageOption->SetConVar( &mat_show_texture_memory_usage );
|
||
|
||
m_pAllTextures = vgui::SETUP_PANEL( new CConVarCheckButton( this, "m_pAllTextures", "Show ALL textures" ) );
|
||
m_pAllTextures->SetVisible( true );
|
||
m_pAllTextures->SetConVar( &mat_texture_list_all );
|
||
m_pAllTextures->AddActionSignalTarget( this );
|
||
m_pAllTextures->SetCommand( "AllTextures" );
|
||
|
||
m_pViewTextures = vgui::SETUP_PANEL( new CConVarCheckButton( this, "m_pViewTextures", "View textures thumbnails" ) );
|
||
m_pViewTextures->SetVisible( true );
|
||
m_pViewTextures->SetConVar( &mat_texture_list_view );
|
||
m_pViewTextures->AddActionSignalTarget( this );
|
||
m_pViewTextures->SetCommand( "ViewThumbnails" );
|
||
|
||
m_pCopyToClipboardButton = vgui::SETUP_PANEL( new vgui::Button( this, "CopyToClipboard", "Copy to Clipboard" ) );
|
||
if ( m_pCopyToClipboardButton )
|
||
{
|
||
m_pCopyToClipboardButton->AddActionSignalTarget( this );
|
||
m_pCopyToClipboardButton->SetCommand( COPYTOCLIPBOARD_CMDNAME );
|
||
}
|
||
|
||
m_pCollapse = vgui::SETUP_PANEL( new vgui::ToggleButton( this, "Collapse", " " ) );
|
||
m_pCollapse->AddActionSignalTarget( this );
|
||
m_pCollapse->SetCommand( "Collapse" );
|
||
m_pCollapse->SetSelected( true );
|
||
|
||
m_pAlpha = vgui::SETUP_PANEL( new vgui::CheckButton( this, "ShowAlpha", "Alpha" ) );
|
||
m_pAlpha->AddActionSignalTarget( this );
|
||
m_pAlpha->SetCommand( "ShowAlpha" );
|
||
bool bDefaultTxAlphaOn = true;
|
||
m_pAlpha->SetSelected( bDefaultTxAlphaOn );
|
||
|
||
m_pThumbWarnings = vgui::SETUP_PANEL( new vgui::CheckButton( this, "ThumbWarnings", "Warns" ) );
|
||
m_pThumbWarnings->AddActionSignalTarget( this );
|
||
m_pThumbWarnings->SetCommand( "ThumbWarnings" );
|
||
m_pThumbWarnings->SetSelected( g_warn_enable );
|
||
|
||
// Filtering
|
||
m_pFilteringChk = vgui::SETUP_PANEL( new vgui::CheckButton( this, "FilteringChk", "Filter: " ) );
|
||
m_pFilteringChk->AddActionSignalTarget( this );
|
||
m_pFilteringChk->SetCommand( "FilteringChk" );
|
||
m_pFilteringChk->SetSelected( true );
|
||
|
||
m_pFilteringText = vgui::SETUP_PANEL( new vgui::TextEntry( this, "FilteringTxt" ) );
|
||
m_pFilteringText->AddActionSignalTarget( this );
|
||
|
||
// Create the tree control itself.
|
||
m_pListPanel = vgui::SETUP_PANEL( new vgui::ListPanel( this, "List Panel" ) );
|
||
m_pListPanel->SetVisible( !mat_texture_list_view.GetBool() );
|
||
|
||
int col = -1;
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_NAME, "Texture Name", 200, 100, 700, vgui::ListPanel::COLUMN_RESIZEWITHWINDOW );
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_PATH, "Path", 50, 50, 300, 0 );
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_SIZE, "Kilobytes", 50, 50, 50, 0 );
|
||
m_pListPanel->SetSortFunc( col, KilobytesSortFunc );
|
||
m_pListPanel->SetSortColumnEx( col, 0, true ); // advanced sorting setup
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_TEXTURE_GROUP, "Group", 100, 100, 300, 0 );
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_FORMAT, "Format", 250, 50, 300, 0 );
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_WIDTH, "Width", 50, 50, 50, 0 );
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_HEIGHT, "Height", 50, 50, 50, 0 );
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_BINDS_FRAME, "# Binds", 50, 50, 50, 0 );
|
||
m_pListPanel->AddColumnHeader( ++ col, KEYNAME_BINDS_MAX, "BindsMax", 50, 50, 50, 0 );
|
||
|
||
SetBgColor( Color( 0, 0, 0, 100 ) );
|
||
|
||
m_pListPanel->SetBgColor( Color( 0, 0, 0, 100 ) );
|
||
|
||
// Create the view control itself
|
||
m_pViewPanel = vgui::SETUP_PANEL( new CRenderTexturesListViewPanel( this, "View Panel" ) );
|
||
m_pViewPanel->SetVisible( mat_texture_list_view.GetBool() );
|
||
m_pViewPanel->SetBgColor( Color( 0, 0, 0, 255 ) );
|
||
|
||
m_pViewPanel->SetDragEnabled( false );
|
||
m_pViewPanel->SetDropEnabled( false );
|
||
m_pViewPanel->SetPaintAlpha( bDefaultTxAlphaOn );
|
||
|
||
m_pViewPanel->SetDataListPanel( m_pListPanel );
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose:
|
||
//-----------------------------------------------------------------------------
|
||
CTextureListPanel::~CTextureListPanel( void )
|
||
{
|
||
g_pTextureListPanel = NULL;
|
||
}
|
||
|
||
void CTextureListPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
{
|
||
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
||
// If you change this font, be sure to mark it with
|
||
// $use_in_fillrate_mode in its .vmt file
|
||
m_hFont = pScheme->GetFont( "DefaultVerySmall", false );
|
||
Assert( m_hFont );
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose:
|
||
// Output : Returns true on success, false on failure.
|
||
//-----------------------------------------------------------------------------
|
||
bool CTextureListPanel::ShouldDraw( void )
|
||
{
|
||
if ( mat_texture_list.GetInt() )
|
||
return true;
|
||
if ( s_eTxListPanelRequest == TXR_SHOW ||
|
||
s_eTxListPanelRequest == TXR_RUNNING )
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
void CTextureListPanel::PerformLayout()
|
||
{
|
||
BaseClass::PerformLayout();
|
||
|
||
// Put the collapse button in the corner
|
||
m_pCollapse->SetPos( 2, 10 );
|
||
m_pCollapse->SetSize( 10, 10 );
|
||
m_pCollapse->SetVisible( true );
|
||
|
||
bool bCollapsed = m_pCollapse->IsSelected();
|
||
|
||
int x, y, w, t;
|
||
GetClientArea( x, y, w, t );
|
||
|
||
int yOffset = y;
|
||
|
||
// The cvar reminder goes on the top.
|
||
m_pCVarListLabel->SetPos( x, yOffset );
|
||
m_pCVarListLabel->SetWide( w );
|
||
NULL; // yOffset += m_pCVarListLabel->GetTall();
|
||
m_pCVarListLabel->SetVisible( false ); // m_pCVarListLabel->SetVisible( !bCollapsed );
|
||
|
||
m_pTotalUsageLabel->SetPos( x, yOffset );
|
||
m_pTotalUsageLabel->SetWide( w );
|
||
yOffset += m_pTotalUsageLabel->GetTall();
|
||
m_pTotalUsageLabel->SetVisible( !bCollapsed );
|
||
|
||
// Align the check boxes.
|
||
vgui::Panel *buttons[] = {
|
||
m_pSpecialTexs,
|
||
m_pShowTextureMemoryUsageOption,
|
||
m_pAllTextures,
|
||
m_pViewTextures,
|
||
m_pFilteringChk,
|
||
m_pResolveTexturePath,
|
||
m_pCopyToClipboardButton };
|
||
|
||
for ( int i=0; i < ARRAYSIZE( buttons ); i++ )
|
||
{
|
||
buttons[i]->SetPos( x, yOffset );
|
||
buttons[i]->SetWide( w/2 );
|
||
yOffset += buttons[i]->GetTall();
|
||
buttons[i]->SetVisible( !bCollapsed );
|
||
|
||
if ( buttons[i] == m_pViewTextures )
|
||
{
|
||
m_pViewTextures->SetWide( 170 );
|
||
int accumw = 170;
|
||
|
||
m_pAlpha->SetPos( x + accumw + 5, yOffset - m_pViewTextures->GetTall() );
|
||
m_pAlpha->SetWide( (accumw += 85, 85) );
|
||
|
||
m_pThumbWarnings->SetPos( x + accumw + 5, yOffset - m_pViewTextures->GetTall() );
|
||
m_pThumbWarnings->SetWide( (accumw += 85, 85) );
|
||
}
|
||
|
||
if ( buttons[i] == m_pFilteringChk )
|
||
{
|
||
m_pFilteringChk->SetWide( 60 );
|
||
int accumw = 60;
|
||
|
||
m_pFilteringText->SetPos( x + accumw + 5, yOffset - m_pFilteringChk->GetTall() );
|
||
m_pFilteringText->SetWide( ( accumw += 170, 170 ) );
|
||
m_pFilteringText->SetTall( m_pFilteringChk->GetTall() );
|
||
m_pFilteringText->SetVisible( !bCollapsed );
|
||
}
|
||
}
|
||
|
||
if ( bCollapsed )
|
||
{
|
||
int xOffset = 85, iWidth;
|
||
|
||
struct LayoutHorz_t
|
||
{
|
||
vgui::Panel *pPanel;
|
||
int iWidth;
|
||
}
|
||
layout[] =
|
||
{
|
||
{ m_pTotalUsageLabel, 290 },
|
||
{ m_pViewTextures, 170 },
|
||
{ m_pAlpha, 60 },
|
||
{ m_pAllTextures, 135 },
|
||
{ m_pFilteringChk, 60 },
|
||
{ m_pFilteringText, 130 }
|
||
};
|
||
|
||
for ( int k = 0; k < ARRAYSIZE( layout ); ++ k )
|
||
{
|
||
layout[ k ].pPanel->SetPos( xOffset, 2 );
|
||
iWidth = layout[ k ].iWidth;
|
||
iWidth = MIN( w - xOffset - 30, iWidth );
|
||
layout[ k ].pPanel->SetWide( iWidth );
|
||
layout[ k ].pPanel->SetVisible( iWidth > 50 );
|
||
|
||
if ( iWidth > 50 )
|
||
xOffset += iWidth + 5;
|
||
}
|
||
|
||
yOffset = y;
|
||
}
|
||
|
||
m_pAlpha->SetVisible( m_pViewTextures->IsSelected() );
|
||
m_pThumbWarnings->SetVisible( !bCollapsed && m_pViewTextures->IsSelected() );
|
||
|
||
m_pListPanel->SetBounds( x, yOffset, w, t - (yOffset - y) );
|
||
m_pViewPanel->SetBounds( x, yOffset, w, t - (yOffset - y) );
|
||
|
||
m_pListPanel->SetVisible( !mat_texture_list_view.GetBool() );
|
||
m_pViewPanel->SetVisible( mat_texture_list_view.GetBool() );
|
||
}
|
||
|
||
|
||
bool StripDirName( char *pFilename )
|
||
{
|
||
if ( pFilename[0] == 0 )
|
||
return false;
|
||
|
||
char *pLastSlash = pFilename;
|
||
while ( 1 )
|
||
{
|
||
char *pTestSlash = strchr( pLastSlash, '/' );
|
||
if ( !pTestSlash )
|
||
{
|
||
pTestSlash = strchr( pLastSlash, '\\' );
|
||
if ( !pTestSlash )
|
||
break;
|
||
}
|
||
|
||
pTestSlash++; // Skip past the slash.
|
||
pLastSlash = pTestSlash;
|
||
}
|
||
|
||
if ( pLastSlash == pFilename )
|
||
{
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
Assert( pLastSlash[-1] == '/' || pLastSlash[-1] == '\\' );
|
||
pLastSlash[-1] = 0;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
static inline void ToLowerInplace( char *chBuffer )
|
||
{
|
||
for ( char *pch = chBuffer; *pch; ++ pch )
|
||
{
|
||
if ( V_isupper( *pch ) )
|
||
*pch = tolower( *pch );
|
||
}
|
||
}
|
||
|
||
void KeepSpecialKeys( KeyValues *textureList, bool bServiceKeys )
|
||
{
|
||
KeyValues *pNext;
|
||
for ( KeyValues *pCur=textureList->GetFirstSubKey(); pCur; pCur=pNext )
|
||
{
|
||
pNext = pCur->GetNextKey();
|
||
|
||
bool bIsServiceKey = false;
|
||
|
||
char const *szName = pCur->GetString( KEYNAME_NAME );
|
||
if ( StringHasPrefix( szName, "_" ) ||
|
||
StringHasPrefix( szName, "[" ) ||
|
||
!stricmp( szName, "backbuffer" ) ||
|
||
StringHasPrefix( szName, "colorcorrection" ) ||
|
||
!stricmp( szName, "depthbuffer" ) ||
|
||
!stricmp( szName, "frontbuffer" ) ||
|
||
!stricmp( szName, "normalize" ) ||
|
||
!*szName )
|
||
{
|
||
bIsServiceKey = true;
|
||
}
|
||
|
||
if ( bIsServiceKey != bServiceKeys )
|
||
{
|
||
textureList->RemoveSubKey( pCur );
|
||
}
|
||
else if ( bIsServiceKey )
|
||
{
|
||
pCur->SetInt( "SpecialTx", 1 );
|
||
}
|
||
}
|
||
}
|
||
|
||
void KeepKeysMatchingFilter( KeyValues *textureList, char const *szFilter )
|
||
{
|
||
if ( !szFilter || !*szFilter )
|
||
return;
|
||
|
||
char chFilter[MAX_PATH] = {0}, chName[MAX_PATH] = {0};
|
||
|
||
Q_strncpy( chFilter, szFilter, sizeof( chFilter ) - 1 );
|
||
ToLowerInplace( chFilter );
|
||
|
||
KeyValues *pNext;
|
||
for ( KeyValues *pCur=textureList->GetFirstSubKey(); pCur; pCur=pNext )
|
||
{
|
||
pNext = pCur->GetNextKey();
|
||
|
||
char const *szName = pCur->GetString( KEYNAME_NAME );
|
||
|
||
Q_strncpy( chName, szName, sizeof( chName ) - 1 );
|
||
ToLowerInplace( chName );
|
||
|
||
if ( !strstr( chName, chFilter ) )
|
||
{
|
||
textureList->RemoveSubKey( pCur );
|
||
}
|
||
}
|
||
}
|
||
|
||
void CTextureListPanel::UpdateTotalUsageLabel()
|
||
{
|
||
char data[1024], kb1[20], kb2[20], kb3[20];
|
||
FmtCommaNumber( kb1, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_BOUND_LAST_FRAME ) + 511) / 1024 );
|
||
FmtCommaNumber( kb2, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_TOTAL_LOADED ) + 511) / 1024 );
|
||
FmtCommaNumber( kb3, m_numDisplayedSizeKB );
|
||
|
||
if ( bool bCollapsed = m_pCollapse->IsSelected() )
|
||
{
|
||
char const *szTitle = "";
|
||
Q_snprintf( data, sizeof( data ), "%s[F %s Kb] / [T %s Kb] / [S %s Kb]", szTitle, kb1, kb2, kb3 );
|
||
}
|
||
else
|
||
{
|
||
char const *szTitle = "Texture Memory Usage";
|
||
char kbMip1[ 20 ], kbMip2[ 20 ];
|
||
FmtCommaNumber( kbMip1, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_ESTIMATE_PICMIP_1 ) + 511) / 1024 );
|
||
FmtCommaNumber( kbMip2, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_ESTIMATE_PICMIP_2 ) + 511) / 1024 );
|
||
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 );
|
||
}
|
||
|
||
wchar_t unicodeString[1024];
|
||
g_pVGuiLocalize->ConvertANSIToUnicode( data, unicodeString, sizeof( unicodeString ) );
|
||
|
||
m_pTotalUsageLabel->SetText( unicodeString );
|
||
}
|
||
|
||
void CTextureListPanel::OnTextChanged( void )
|
||
{
|
||
OnCommand( "FilteringTxt" );
|
||
}
|
||
|
||
void CTextureListPanel::OnCommand( const char *command )
|
||
{
|
||
if ( !Q_stricmp( command, "Close" ) )
|
||
{
|
||
vgui::Frame::OnCommand( command );
|
||
return;
|
||
}
|
||
|
||
if ( !Q_stricmp( command, "Collapse" ) )
|
||
{
|
||
InvalidateLayout();
|
||
return;
|
||
}
|
||
|
||
if ( !Q_stricmp( command, "ShowAlpha" ) )
|
||
{
|
||
m_pViewPanel->SetPaintAlpha( m_pAlpha->IsSelected() );
|
||
return;
|
||
}
|
||
|
||
if ( !Q_stricmp( command, "ThumbWarnings" ) )
|
||
{
|
||
g_warn_enable = m_pThumbWarnings->IsSelected();
|
||
return;
|
||
}
|
||
|
||
if ( !Q_stricmp( command, "ViewThumbnails" ) )
|
||
{
|
||
InvalidateLayout();
|
||
return;
|
||
}
|
||
|
||
if ( !Q_stricmp( command, COPYTOCLIPBOARD_CMDNAME ) )
|
||
{
|
||
CopyListPanelToClipboard( m_pListPanel );
|
||
return;
|
||
}
|
||
|
||
mat_texture_list_on_f();
|
||
InvalidateLayout();
|
||
}
|
||
|
||
|
||
bool CTextureListPanel::UpdateDisplayedItem( KeyValues *pDispData, KeyValues *kv )
|
||
{
|
||
// Update the item?
|
||
bool bUpdate = false;
|
||
|
||
// do the stuff that changes often separately.
|
||
if ( pDispData->GetInt( KEYNAME_BINDS_FRAME ) != kv->GetInt( KEYNAME_BINDS_FRAME ) )
|
||
{
|
||
pDispData->SetInt( KEYNAME_BINDS_FRAME, kv->GetInt( KEYNAME_BINDS_FRAME ) );
|
||
bUpdate = true;
|
||
}
|
||
if ( pDispData->GetInt( KEYNAME_BINDS_MAX ) != kv->GetInt( KEYNAME_BINDS_MAX ) )
|
||
{
|
||
pDispData->SetInt( KEYNAME_BINDS_MAX, kv->GetInt( KEYNAME_BINDS_MAX ) );
|
||
bUpdate = true;
|
||
}
|
||
|
||
// stuff that changes less frequently
|
||
if( pDispData->GetInt( KEYNAME_SIZE ) != kv->GetInt( KEYNAME_SIZE ) ||
|
||
pDispData->GetInt( KEYNAME_WIDTH ) != kv->GetInt( KEYNAME_WIDTH ) ||
|
||
pDispData->GetInt( KEYNAME_HEIGHT ) != kv->GetInt( KEYNAME_HEIGHT ) ||
|
||
Q_stricmp( pDispData->GetString( KEYNAME_FORMAT ), kv->GetString( KEYNAME_FORMAT ) ) != 0 ||
|
||
Q_stricmp( pDispData->GetString( KEYNAME_PATH ), kv->GetString( KEYNAME_PATH ) ) != 0 ||
|
||
Q_stricmp( pDispData->GetString( KEYNAME_TEXTURE_GROUP ), kv->GetString( KEYNAME_TEXTURE_GROUP ) ) != 0 )
|
||
{
|
||
pDispData->SetInt( KEYNAME_SIZE, kv->GetInt( KEYNAME_SIZE ) );
|
||
pDispData->SetInt( KEYNAME_WIDTH, kv->GetInt( KEYNAME_WIDTH ) );
|
||
pDispData->SetInt( KEYNAME_HEIGHT, kv->GetInt( KEYNAME_HEIGHT ) );
|
||
pDispData->SetString( KEYNAME_FORMAT, kv->GetString( KEYNAME_FORMAT ) );
|
||
pDispData->SetString( KEYNAME_PATH, kv->GetString( KEYNAME_PATH ) );
|
||
pDispData->SetString( KEYNAME_TEXTURE_GROUP, kv->GetString( KEYNAME_TEXTURE_GROUP ) );
|
||
bUpdate = true;
|
||
}
|
||
|
||
return bUpdate;
|
||
}
|
||
|
||
int CTextureListPanel::AddListItem( KeyValues *kv )
|
||
{
|
||
int iItem = m_pListPanel->GetItem( kv->GetString( KEYNAME_NAME ) );
|
||
if ( iItem == -1 )
|
||
{
|
||
// Set this so the GetItem() call above can use the key's name (as opposed to the value of its
|
||
// "Name" subkey) to find this texture again.
|
||
kv->SetName( kv->GetString( KEYNAME_NAME ) );
|
||
|
||
// Add this one.
|
||
iItem = m_pListPanel->AddItem( kv, 0, false, false );
|
||
m_pViewPanel->InvalidateLayout();
|
||
}
|
||
else
|
||
{
|
||
KeyValues *pValues = m_pListPanel->GetItem( iItem );
|
||
bool bNeedUpdate = UpdateDisplayedItem( pValues, kv );
|
||
|
||
if( bNeedUpdate )
|
||
{
|
||
m_pListPanel->ApplyItemChanges( iItem );
|
||
m_pViewPanel->Repaint();
|
||
}
|
||
}
|
||
|
||
return iItem;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose:
|
||
//-----------------------------------------------------------------------------
|
||
|
||
void CTextureListPanel::OnTurnedOn()
|
||
{
|
||
if ( g_bRecursiveRequestToShowTextureList )
|
||
return;
|
||
|
||
if ( m_pListPanel )
|
||
m_pListPanel->DeleteAllItems();
|
||
|
||
if ( CRenderTextureEditor *pRe = m_pViewPanel->GetRenderTxEditor() )
|
||
pRe->Close();
|
||
}
|
||
|
||
void CTextureListPanel::Close()
|
||
{
|
||
mat_texture_list_off_f();
|
||
}
|
||
|
||
void CTextureListPanel::EndPaint()
|
||
{
|
||
UpdateTotalUsageLabel();
|
||
}
|
||
|
||
void CTextureListPanel::Paint()
|
||
{
|
||
VPROF( "CTextureListPanel::Paint" );
|
||
|
||
if ( !m_hFont )
|
||
return;
|
||
|
||
struct EndPaint_t
|
||
{
|
||
CTextureListPanel *m_p;
|
||
EndPaint_t( CTextureListPanel *p ) : m_p( p ) {}
|
||
~EndPaint_t()
|
||
{
|
||
m_p->EndPaint();
|
||
}
|
||
} endpaint( this );
|
||
|
||
if ( !mat_texture_list.GetBool() )
|
||
return;
|
||
|
||
MatTextureModificationRecorded();
|
||
|
||
if ( !g_pMaterialSystemDebugTextureInfo->IsDebugTextureListFresh( 1 ) )
|
||
return;
|
||
|
||
CSmartTextureKeyValues textureList;
|
||
if ( !textureList.Get() )
|
||
return;
|
||
|
||
CRenderTextureEditor *pRte = m_pViewPanel->GetRenderTxEditor();
|
||
if ( ( s_eTxListPanelRequest == TXR_RUNNING ) &&
|
||
pRte->IsVisible() )
|
||
{
|
||
KeyValues *kv = NULL;
|
||
int iHint = 0;
|
||
pRte->GetDispInfo( kv, iHint );
|
||
if ( kv && iHint )
|
||
{
|
||
KeyValues *plv = ( m_pListPanel->IsValidItemID( iHint ) ? m_pListPanel->GetItem( iHint ) : NULL );
|
||
if ( plv && !strcmp( plv->GetString( KEYNAME_NAME ), kv->GetString( KEYNAME_NAME ) ) )
|
||
{
|
||
KeyValues *pValData = plv->GetFirstValue(), *pValRendered = kv->GetFirstValue();
|
||
for ( ; pValData && pValRendered; pValData = pValData->GetNextValue(), pValRendered = pValRendered->GetNextValue() )
|
||
{
|
||
if ( strcmp( pValData->GetString(), pValRendered->GetString() ) )
|
||
break;
|
||
}
|
||
if ( pValData || pValRendered ) // Difference found
|
||
pRte->SetDispInfo( plv, iHint );
|
||
}
|
||
else
|
||
kv = NULL;
|
||
}
|
||
|
||
if ( 0 ) // if ( !kv )
|
||
{
|
||
pRte->Close();
|
||
pRte->SetDispInfo( NULL, 0 );
|
||
}
|
||
}
|
||
|
||
// If we are fetching all textures, then stop loading material system:
|
||
if ( mat_texture_list_all.GetBool() )
|
||
{
|
||
static int s_nFramesForAllTextures = 0;
|
||
|
||
if ( s_eTxListPanelRequest == TXR_RUNNING )
|
||
{
|
||
if ( -- s_nFramesForAllTextures <= 0 )
|
||
{
|
||
mat_texture_list.SetValue( 0 );
|
||
s_eTxListPanelRequest = TXR_SHOW; // Keep displaying our panel
|
||
}
|
||
}
|
||
else
|
||
{
|
||
s_eTxListPanelRequest = TXR_RUNNING;
|
||
s_nFramesForAllTextures = mat_texture_list_all_frames.GetInt();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( s_eTxListPanelRequest == TXR_SHOW )
|
||
{
|
||
// Either first show or turned off "all textures"
|
||
m_pListPanel->RemoveAll();
|
||
m_pViewPanel->InvalidateLayout();
|
||
s_eTxListPanelRequest = TXR_RUNNING;
|
||
return;
|
||
}
|
||
}
|
||
|
||
CBitVec<4096 * 8> itemsTouched;
|
||
|
||
// Remove the textures we don't care for
|
||
KeepSpecialKeys( textureList.Get(), m_pSpecialTexs->IsSelected() );
|
||
|
||
// If filtering is enabled, then do filtering
|
||
if ( m_pFilteringChk->IsSelected() && m_pFilteringText->GetTextLength() )
|
||
{
|
||
char chFilterString[ MAX_PATH ];
|
||
m_pFilteringText->GetText( chFilterString, sizeof( chFilterString ) - 1 );
|
||
chFilterString[ sizeof( chFilterString ) - 1 ] = 0;
|
||
KeepKeysMatchingFilter( textureList.Get(), chFilterString );
|
||
}
|
||
|
||
// Remove scaleform texture
|
||
if ( 1 )
|
||
{
|
||
KeyValues *pNext;
|
||
for ( KeyValues *pCur=textureList.Get()->GetFirstSubKey(); pCur; pCur=pNext )
|
||
{
|
||
pNext = pCur->GetNextKey();
|
||
|
||
char const *szName = pCur->GetString( KEYNAME_NAME );
|
||
|
||
char chName[MAX_PATH] = {0};
|
||
Q_strncpy( chName, szName, sizeof( chName ) - 1 );
|
||
ToLowerInplace( chName );
|
||
|
||
if ( V_stristr( chName, "ScaleformDynamic" ) )
|
||
{
|
||
textureList.Get()->RemoveSubKey( pCur );
|
||
}
|
||
}
|
||
}
|
||
|
||
// Compute the total size of the displayed textures
|
||
int cbTotalDisplayedSizeInBytes = 0;
|
||
|
||
for ( KeyValues *pCur=textureList.Get()->GetFirstSubKey(); pCur; pCur=pCur->GetNextKey() )
|
||
{
|
||
int sizeInBytes = pCur->GetInt( KEYNAME_SIZE );
|
||
|
||
// Accumulate
|
||
cbTotalDisplayedSizeInBytes += sizeInBytes;
|
||
|
||
// Factor in frames
|
||
int numCount = pCur->GetInt( "Count" );
|
||
if ( numCount > 1 )
|
||
sizeInBytes *= numCount;
|
||
|
||
// Size is in kilobytes.
|
||
int sizeInKilo = ( sizeInBytes + 511 ) / 1024;
|
||
pCur->SetInt( KEYNAME_SIZE, sizeInKilo );
|
||
|
||
if ( m_pResolveTexturePath->IsSelected() )
|
||
{
|
||
char chResolveName[ 256 ] = {0}, chResolveNameArg[ 256 ] = {0};
|
||
Q_snprintf( chResolveNameArg, sizeof( chResolveNameArg ) - 1, "materials/%s.vtf", pCur->GetString( KEYNAME_NAME ) );
|
||
char const *szResolvedName = g_pFileSystem->RelativePathToFullPath( chResolveNameArg, "game", chResolveName, sizeof( chResolveName ) - 1 );
|
||
if ( szResolvedName )
|
||
{
|
||
pCur->SetString( KEYNAME_PATH, szResolvedName );
|
||
}
|
||
}
|
||
|
||
int iItem = AddListItem( pCur );
|
||
|
||
if ( iItem < itemsTouched.GetNumBits() )
|
||
itemsTouched.Set( iItem );
|
||
}
|
||
|
||
// Set the displayed size
|
||
m_numDisplayedSizeKB = ( cbTotalDisplayedSizeInBytes + 511 ) / 1024;
|
||
|
||
// Now remove from view items that weren't used.
|
||
int iNext, numRemoved = 0;
|
||
for ( int iCur=m_pListPanel->FirstItem(); iCur != m_pListPanel->InvalidItemID(); iCur=iNext )
|
||
{
|
||
iNext = m_pListPanel->NextItem( iCur );
|
||
|
||
if ( iCur >= itemsTouched.GetNumBits() || !itemsTouched.Get( iCur ) )
|
||
{
|
||
m_pListPanel->RemoveItem( iCur );
|
||
++ numRemoved;
|
||
}
|
||
}
|
||
|
||
// Sorting in list panel
|
||
{
|
||
int iPri, iSec;
|
||
bool bAsc;
|
||
m_pListPanel->GetSortColumnEx( iPri, iSec, bAsc );
|
||
iSec = 0; // always secondary sort by name
|
||
m_pListPanel->SetSortColumnEx( iPri, iSec, bAsc );
|
||
m_pListPanel->SortList();
|
||
}
|
||
|
||
if ( numRemoved )
|
||
{
|
||
m_pViewPanel->InvalidateLayout();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// ------------------------------------------------------------------------------ //
|
||
// Global functions.
|
||
// ------------------------------------------------------------------------------ //
|
||
|
||
void VGui_UpdateTextureListPanel()
|
||
{
|
||
if ( mat_show_texture_memory_usage.GetInt() )
|
||
{
|
||
con_nprint_t info;
|
||
info.index = 4;
|
||
info.time_to_live = 0.2;
|
||
info.color[0] = 1;
|
||
info.color[1] = 0.5;
|
||
info.color[2] = 0;
|
||
info.fixed_width_font = true;
|
||
|
||
char kb1[20], kb2[20];
|
||
FmtCommaNumber( kb1, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_BOUND_LAST_FRAME ) + 511) / 1024 );
|
||
FmtCommaNumber( kb2, (g_pMaterialSystemDebugTextureInfo->GetTextureMemoryUsed( IDebugTextureInfo::MEMORY_TOTAL_LOADED ) + 511) / 1024 );
|
||
|
||
Con_NXPrintf( &info, "Texture Memory Usage: %s Kb / %s Kb", kb1, kb2 );
|
||
}
|
||
|
||
MatViewOverride::DisplaySelectedTextures();
|
||
|
||
if ( IsX360() )
|
||
return;
|
||
|
||
g_pMaterialSystemDebugTextureInfo->EnableGetAllTextures( mat_texture_list_all.GetBool() );
|
||
|
||
g_pMaterialSystemDebugTextureInfo->EnableDebugTextureList( ( mat_texture_list.GetInt() <= 0 ) ? false : true );
|
||
|
||
bool bShouldDrawTxListPanel = g_pTextureListPanel->ShouldDraw();
|
||
if ( g_pTextureListPanel->IsVisible() != bShouldDrawTxListPanel )
|
||
{
|
||
g_pTextureListPanel->SetVisible( bShouldDrawTxListPanel );
|
||
bShouldDrawTxListPanel ? mat_texture_list_on_f() : mat_texture_list_off_f();
|
||
}
|
||
}
|
||
|
||
|
||
void CL_CreateTextureListPanel( vgui::Panel *parent )
|
||
{
|
||
g_pTextureListPanel = new CTextureListPanel( parent );
|
||
}
|
||
|
||
extern ConVar sv_cheats;
|
||
void mat_texture_list_on_f()
|
||
{
|
||
if ( !sv_cheats.GetBool() )
|
||
return;
|
||
|
||
mat_texture_list.SetValue( 1 );
|
||
s_eTxListPanelRequest = TXR_SHOW;
|
||
|
||
g_pTextureListPanel->OnTurnedOn();
|
||
|
||
MatViewOverride::RequestSelectNone();
|
||
}
|
||
void mat_texture_list_off_f()
|
||
{
|
||
mat_texture_list.SetValue( 0 );
|
||
s_eTxListPanelRequest = TXR_HIDE;
|
||
}
|
||
|
||
#endif
|