You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
7.2 KiB
240 lines
7.2 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//===========================================================================//
|
||
|
|
||
|
#include "matsys_controls/proceduraltexturepanel.h"
|
||
|
#include "matsys_controls/matsyscontrols.h"
|
||
|
#include "materialsystem/imaterialsystem.h"
|
||
|
#include "materialsystem/itexture.h"
|
||
|
#include "VGuiMatSurface/IMatSystemSurface.h"
|
||
|
#include "tier1/KeyValues.h"
|
||
|
#include "pixelwriter.h"
|
||
|
|
||
|
|
||
|
using namespace vgui;
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// constructor
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CProceduralTexturePanel::CProceduralTexturePanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
|
||
|
{
|
||
|
m_pImageBuffer = NULL;
|
||
|
m_bMaintainProportions = false;
|
||
|
m_bUsePaintRect = false;
|
||
|
m_PaintRect.x = m_PaintRect.y = 0;
|
||
|
m_PaintRect.width = m_PaintRect.height = 0;
|
||
|
}
|
||
|
|
||
|
CProceduralTexturePanel::~CProceduralTexturePanel()
|
||
|
{
|
||
|
CleanUp();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// initialization, shutdown
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CProceduralTexturePanel::Init( int nWidth, int nHeight, bool bAllocateImageBuffer )
|
||
|
{
|
||
|
m_nWidth = nWidth;
|
||
|
m_nHeight = nHeight;
|
||
|
if ( bAllocateImageBuffer )
|
||
|
{
|
||
|
m_pImageBuffer = new BGRA8888_t[nWidth * nHeight];
|
||
|
}
|
||
|
|
||
|
m_TextureSubRect.x = m_TextureSubRect.y = 0;
|
||
|
m_TextureSubRect.width = nWidth;
|
||
|
m_TextureSubRect.height = nHeight;
|
||
|
|
||
|
char pTemp[512];
|
||
|
Q_snprintf( pTemp, 512, "__%s", GetName() );
|
||
|
|
||
|
ITexture *pTex = MaterialSystem()->CreateProceduralTexture( pTemp, TEXTURE_GROUP_VGUI,
|
||
|
m_nWidth, m_nHeight, IMAGE_FORMAT_BGRX8888,
|
||
|
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_NOMIP |
|
||
|
TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY );
|
||
|
pTex->SetTextureRegenerator( this );
|
||
|
m_ProceduralTexture.Init( pTex );
|
||
|
|
||
|
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
|
||
|
pVMTKeyValues->SetString( "$basetexture", pTemp );
|
||
|
pVMTKeyValues->SetInt( "$nocull", 1 );
|
||
|
pVMTKeyValues->SetInt( "$nodebug", 1 );
|
||
|
m_ProceduralMaterial.Init( MaterialSystem()->CreateMaterial( pTemp, pVMTKeyValues ));
|
||
|
|
||
|
m_nTextureID = MatSystemSurface()->CreateNewTextureID( false );
|
||
|
MatSystemSurface()->DrawSetTextureMaterial( m_nTextureID, m_ProceduralMaterial );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CProceduralTexturePanel::Shutdown()
|
||
|
{
|
||
|
CleanUp();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Maintain proportions when drawing
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CProceduralTexturePanel::MaintainProportions( bool bEnable )
|
||
|
{
|
||
|
m_bMaintainProportions = bEnable;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Returns the image buffer + dimensions
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CProceduralTexturePanel::CleanUp()
|
||
|
{
|
||
|
if ( (ITexture*)m_ProceduralTexture )
|
||
|
{
|
||
|
m_ProceduralTexture->SetTextureRegenerator( NULL );
|
||
|
}
|
||
|
m_ProceduralTexture.Shutdown();
|
||
|
m_ProceduralMaterial.Shutdown();
|
||
|
|
||
|
if ( m_pImageBuffer )
|
||
|
{
|
||
|
delete[] m_pImageBuffer;
|
||
|
m_pImageBuffer = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Default implementation of regenerate texture bits
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CProceduralTexturePanel::RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect )
|
||
|
{
|
||
|
Assert( m_pImageBuffer );
|
||
|
Assert( pVTFTexture->FrameCount() == 1 );
|
||
|
Assert( pVTFTexture->FaceCount() == 1 );
|
||
|
Assert( !pTexture->IsMipmapped() );
|
||
|
|
||
|
int nWidth, nHeight, nDepth;
|
||
|
pVTFTexture->ComputeMipLevelDimensions( 0, &nWidth, &nHeight, &nDepth );
|
||
|
Assert( nDepth == 1 );
|
||
|
Assert( nWidth == m_nWidth && nHeight == m_nHeight );
|
||
|
|
||
|
CPixelWriter pixelWriter;
|
||
|
pixelWriter.SetPixelMemory( pVTFTexture->Format(),
|
||
|
pVTFTexture->ImageData( 0, 0, 0 ), pVTFTexture->RowSizeInBytes( 0 ) );
|
||
|
|
||
|
for ( int y = 0; y < nHeight; ++y )
|
||
|
{
|
||
|
pixelWriter.Seek( 0, y );
|
||
|
BGRA8888_t *pTexel = &m_pImageBuffer[y * m_nWidth];
|
||
|
for ( int x = 0; x < nWidth; ++x, ++pTexel )
|
||
|
{
|
||
|
pixelWriter.WritePixel( pTexel->r, pTexel->g, pTexel->b, pTexel->a );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Returns the image buffer + dimensions
|
||
|
//-----------------------------------------------------------------------------
|
||
|
BGRA8888_t *CProceduralTexturePanel::GetImageBuffer()
|
||
|
{
|
||
|
Assert( m_pImageBuffer );
|
||
|
return m_pImageBuffer;
|
||
|
}
|
||
|
|
||
|
int CProceduralTexturePanel::GetImageWidth() const
|
||
|
{
|
||
|
return m_nWidth;
|
||
|
}
|
||
|
|
||
|
int CProceduralTexturePanel::GetImageHeight() const
|
||
|
{
|
||
|
return m_nHeight;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Sets the paint rect
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CProceduralTexturePanel::SetPaintRect( const Rect_t *pPaintRect )
|
||
|
{
|
||
|
m_bUsePaintRect = ( pPaintRect != NULL );
|
||
|
if ( m_bUsePaintRect )
|
||
|
{
|
||
|
m_PaintRect = *pPaintRect;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Sets the draw rect
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CProceduralTexturePanel::SetTextureSubRect( const Rect_t &subRect )
|
||
|
{
|
||
|
m_TextureSubRect = subRect;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Redownloads the procedural texture
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CProceduralTexturePanel::DownloadTexture()
|
||
|
{
|
||
|
m_ProceduralTexture->Download();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Paints the texture
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CProceduralTexturePanel::Paint( void )
|
||
|
{
|
||
|
vgui::surface()->DrawSetTexture( m_nTextureID );
|
||
|
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
|
||
|
|
||
|
int x = 0;
|
||
|
int y = 0;
|
||
|
int w, h;
|
||
|
GetSize( w, h );
|
||
|
if ( m_bUsePaintRect )
|
||
|
{
|
||
|
x = m_PaintRect.x;
|
||
|
y = m_PaintRect.y;
|
||
|
w = m_PaintRect.width;
|
||
|
h = m_PaintRect.height;
|
||
|
}
|
||
|
|
||
|
if ( m_bMaintainProportions )
|
||
|
{
|
||
|
if ( m_TextureSubRect.width > m_TextureSubRect.height )
|
||
|
{
|
||
|
h = w * m_TextureSubRect.height / m_TextureSubRect.width;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
w = h * m_TextureSubRect.width / m_TextureSubRect.height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Rotated version of the bitmap!
|
||
|
// Rotate about the center of the bitmap
|
||
|
vgui::Vertex_t verts[4];
|
||
|
verts[0].m_Position.Init( x, y );
|
||
|
verts[0].m_TexCoord.Init( (float)m_TextureSubRect.x / m_nWidth, (float)m_TextureSubRect.y / m_nHeight );
|
||
|
|
||
|
verts[1].m_Position.Init( w+x, y );
|
||
|
verts[1].m_TexCoord.Init( (float)(m_TextureSubRect.x + m_TextureSubRect.width) / m_nWidth, (float)m_TextureSubRect.y / m_nHeight );
|
||
|
|
||
|
verts[2].m_Position.Init( w+x, h+y );
|
||
|
verts[2].m_TexCoord.Init( (float)(m_TextureSubRect.x + m_TextureSubRect.width) / m_nWidth, (float)(m_TextureSubRect.y + m_TextureSubRect.height) / m_nHeight );
|
||
|
|
||
|
verts[3].m_Position.Init( x, h+y );
|
||
|
verts[3].m_TexCoord.Init( (float)m_TextureSubRect.x / m_nWidth, (float)(m_TextureSubRect.y + m_TextureSubRect.height) / m_nHeight );
|
||
|
|
||
|
vgui::surface()->DrawTexturedPolygon( 4, verts );
|
||
|
}
|