//========= 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 ); }