Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
7.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "matsys_controls/proceduraltexturepanel.h"
  7. #include "matsys_controls/matsyscontrols.h"
  8. #include "materialsystem/imaterialsystem.h"
  9. #include "materialsystem/itexture.h"
  10. #include "VGuiMatSurface/IMatSystemSurface.h"
  11. #include "tier1/KeyValues.h"
  12. #include "pixelwriter.h"
  13. using namespace vgui;
  14. //-----------------------------------------------------------------------------
  15. // constructor
  16. //-----------------------------------------------------------------------------
  17. CProceduralTexturePanel::CProceduralTexturePanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
  18. {
  19. m_pImageBuffer = NULL;
  20. m_bMaintainProportions = false;
  21. m_bUsePaintRect = false;
  22. m_PaintRect.x = m_PaintRect.y = 0;
  23. m_PaintRect.width = m_PaintRect.height = 0;
  24. }
  25. CProceduralTexturePanel::~CProceduralTexturePanel()
  26. {
  27. CleanUp();
  28. }
  29. //-----------------------------------------------------------------------------
  30. // initialization, shutdown
  31. //-----------------------------------------------------------------------------
  32. bool CProceduralTexturePanel::Init( int nWidth, int nHeight, bool bAllocateImageBuffer )
  33. {
  34. m_nWidth = nWidth;
  35. m_nHeight = nHeight;
  36. if ( bAllocateImageBuffer )
  37. {
  38. m_pImageBuffer = new BGRA8888_t[nWidth * nHeight];
  39. }
  40. m_TextureSubRect.x = m_TextureSubRect.y = 0;
  41. m_TextureSubRect.width = nWidth;
  42. m_TextureSubRect.height = nHeight;
  43. char pTemp[512];
  44. Q_snprintf( pTemp, 512, "__%s", GetName() );
  45. ITexture *pTex = MaterialSystem()->CreateProceduralTexture( pTemp, TEXTURE_GROUP_VGUI,
  46. m_nWidth, m_nHeight, IMAGE_FORMAT_BGRX8888,
  47. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_NOMIP |
  48. TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY );
  49. pTex->SetTextureRegenerator( this );
  50. m_ProceduralTexture.Init( pTex );
  51. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  52. pVMTKeyValues->SetString( "$basetexture", pTemp );
  53. pVMTKeyValues->SetInt( "$nocull", 1 );
  54. pVMTKeyValues->SetInt( "$nodebug", 1 );
  55. m_ProceduralMaterial.Init( MaterialSystem()->CreateMaterial( pTemp, pVMTKeyValues ));
  56. m_nTextureID = MatSystemSurface()->CreateNewTextureID( false );
  57. MatSystemSurface()->DrawSetTextureMaterial( m_nTextureID, m_ProceduralMaterial );
  58. return true;
  59. }
  60. void CProceduralTexturePanel::Shutdown()
  61. {
  62. CleanUp();
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Maintain proportions when drawing
  66. //-----------------------------------------------------------------------------
  67. void CProceduralTexturePanel::MaintainProportions( bool bEnable )
  68. {
  69. m_bMaintainProportions = bEnable;
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Returns the image buffer + dimensions
  73. //-----------------------------------------------------------------------------
  74. void CProceduralTexturePanel::CleanUp()
  75. {
  76. if ( (ITexture*)m_ProceduralTexture )
  77. {
  78. m_ProceduralTexture->SetTextureRegenerator( NULL );
  79. }
  80. m_ProceduralTexture.Shutdown();
  81. m_ProceduralMaterial.Shutdown();
  82. if ( m_pImageBuffer )
  83. {
  84. delete[] m_pImageBuffer;
  85. m_pImageBuffer = NULL;
  86. }
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Default implementation of regenerate texture bits
  90. //-----------------------------------------------------------------------------
  91. void CProceduralTexturePanel::RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect )
  92. {
  93. Assert( m_pImageBuffer );
  94. Assert( pVTFTexture->FrameCount() == 1 );
  95. Assert( pVTFTexture->FaceCount() == 1 );
  96. Assert( !pTexture->IsMipmapped() );
  97. int nWidth, nHeight, nDepth;
  98. pVTFTexture->ComputeMipLevelDimensions( 0, &nWidth, &nHeight, &nDepth );
  99. Assert( nDepth == 1 );
  100. Assert( nWidth == m_nWidth && nHeight == m_nHeight );
  101. CPixelWriter pixelWriter;
  102. pixelWriter.SetPixelMemory( pVTFTexture->Format(),
  103. pVTFTexture->ImageData( 0, 0, 0 ), pVTFTexture->RowSizeInBytes( 0 ) );
  104. for ( int y = 0; y < nHeight; ++y )
  105. {
  106. pixelWriter.Seek( 0, y );
  107. BGRA8888_t *pTexel = &m_pImageBuffer[y * m_nWidth];
  108. for ( int x = 0; x < nWidth; ++x, ++pTexel )
  109. {
  110. pixelWriter.WritePixel( pTexel->r, pTexel->g, pTexel->b, pTexel->a );
  111. }
  112. }
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Returns the image buffer + dimensions
  116. //-----------------------------------------------------------------------------
  117. BGRA8888_t *CProceduralTexturePanel::GetImageBuffer()
  118. {
  119. Assert( m_pImageBuffer );
  120. return m_pImageBuffer;
  121. }
  122. int CProceduralTexturePanel::GetImageWidth() const
  123. {
  124. return m_nWidth;
  125. }
  126. int CProceduralTexturePanel::GetImageHeight() const
  127. {
  128. return m_nHeight;
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Sets the paint rect
  132. //-----------------------------------------------------------------------------
  133. void CProceduralTexturePanel::SetPaintRect( const Rect_t *pPaintRect )
  134. {
  135. m_bUsePaintRect = ( pPaintRect != NULL );
  136. if ( m_bUsePaintRect )
  137. {
  138. m_PaintRect = *pPaintRect;
  139. }
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Sets the draw rect
  143. //-----------------------------------------------------------------------------
  144. void CProceduralTexturePanel::SetTextureSubRect( const Rect_t &subRect )
  145. {
  146. m_TextureSubRect = subRect;
  147. }
  148. //-----------------------------------------------------------------------------
  149. // Redownloads the procedural texture
  150. //-----------------------------------------------------------------------------
  151. void CProceduralTexturePanel::DownloadTexture()
  152. {
  153. m_ProceduralTexture->Download();
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Paints the texture
  157. //-----------------------------------------------------------------------------
  158. void CProceduralTexturePanel::Paint( void )
  159. {
  160. vgui::surface()->DrawSetTexture( m_nTextureID );
  161. vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
  162. int x = 0;
  163. int y = 0;
  164. int w, h;
  165. GetSize( w, h );
  166. if ( m_bUsePaintRect )
  167. {
  168. x = m_PaintRect.x;
  169. y = m_PaintRect.y;
  170. w = m_PaintRect.width;
  171. h = m_PaintRect.height;
  172. }
  173. if ( m_bMaintainProportions )
  174. {
  175. if ( m_TextureSubRect.width > m_TextureSubRect.height )
  176. {
  177. h = w * m_TextureSubRect.height / m_TextureSubRect.width;
  178. }
  179. else
  180. {
  181. w = h * m_TextureSubRect.width / m_TextureSubRect.height;
  182. }
  183. }
  184. // Rotated version of the bitmap!
  185. // Rotate about the center of the bitmap
  186. vgui::Vertex_t verts[4];
  187. verts[0].m_Position.Init( x, y );
  188. verts[0].m_TexCoord.Init( (float)m_TextureSubRect.x / m_nWidth, (float)m_TextureSubRect.y / m_nHeight );
  189. verts[1].m_Position.Init( w+x, y );
  190. verts[1].m_TexCoord.Init( (float)(m_TextureSubRect.x + m_TextureSubRect.width) / m_nWidth, (float)m_TextureSubRect.y / m_nHeight );
  191. verts[2].m_Position.Init( w+x, h+y );
  192. verts[2].m_TexCoord.Init( (float)(m_TextureSubRect.x + m_TextureSubRect.width) / m_nWidth, (float)(m_TextureSubRect.y + m_TextureSubRect.height) / m_nHeight );
  193. verts[3].m_Position.Init( x, h+y );
  194. verts[3].m_TexCoord.Init( (float)m_TextureSubRect.x / m_nWidth, (float)(m_TextureSubRect.y + m_TextureSubRect.height) / m_nHeight );
  195. vgui::surface()->DrawTexturedPolygon( 4, verts );
  196. }