Counter Strike : Global Offensive Source Code
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.

265 lines
7.8 KiB

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