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.

1471 lines
42 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Contains all texture state for the material system surface to use
  4. //
  5. //===========================================================================//
  6. #include "bitmap/imageformat.h"
  7. #include "vgui_surfacelib/texturedictionary.h"
  8. #include "utllinkedlist.h"
  9. #include "checksum_crc.h"
  10. #include "materialsystem/imaterial.h"
  11. #include "materialsystem/imaterialsystem.h"
  12. #include "tier0/dbg.h"
  13. #include "keyvalues.h"
  14. #include "pixelwriter.h"
  15. #include "materialsystem/imaterialvar.h"
  16. #include "materialsystem/itexture.h"
  17. #include "vtf/vtf.h"
  18. #include "rendersystem/irenderdevice.h"
  19. #include "rendersystem/irendercontext.h"
  20. #include "resourcesystem/stronghandle.h"
  21. #include "utldict.h"
  22. #include "vgui/ISystem.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. #define TEXTURE_ID_UNKNOWN -1
  26. class CMatSystemTexture;
  27. // Case-sensitive string checksum
  28. static CRC32_t Texture_CRCName( const char *string )
  29. {
  30. CRC32_t crc;
  31. CRC32_Init( &crc );
  32. CRC32_ProcessBuffer( &crc, (void *)string, strlen( string ) );
  33. CRC32_Final( &crc );
  34. return crc;
  35. }
  36. // [smessick] Less than function for Xuids.
  37. #if defined( _X360 )
  38. static bool XuidLessFunc( const XUID &lhs, const XUID &rhs )
  39. {
  40. return lhs < rhs;
  41. }
  42. #endif // _X360
  43. class CFontTextureRegen;
  44. //-----------------------------------------------------------------------------
  45. // Purpose:
  46. //-----------------------------------------------------------------------------
  47. class CMatSystemTexture
  48. {
  49. public:
  50. CMatSystemTexture( void );
  51. ~CMatSystemTexture( void );
  52. void SetId( int id ) { m_ID = id; };
  53. CRC32_t GetCRC() const;
  54. void SetCRC( CRC32_t val );
  55. void SetMaterial( const char *pFileName );
  56. void SetMaterial( IMaterial *pMaterial );
  57. // This is used when we want different rendering state sharing the same procedural texture (fonts)
  58. void ReferenceOtherProcedural( CMatSystemTexture *pTexture, IMaterial *pMaterial );
  59. // Source1 version
  60. IMaterial *GetMaterial() { return m_pMaterial; }
  61. // Source2 version
  62. HRenderTexture GetTextureHandle(){ return m_Texture2; }
  63. int Width() const { return m_iWide; }
  64. int Height() const { return m_iTall; }
  65. bool IsProcedural( void ) const;
  66. void SetProcedural( bool proc );
  67. bool IsReference() const { return ( m_Flags & TEXTURE_IS_REFERENCE ) ? true : false; }
  68. // Source1 version
  69. void SetTextureRGBA( const char* rgba, int wide, int tall, ImageFormat format, ETextureScaling eScaling );
  70. // Source2 version
  71. void SetTextureRGBA( IRenderDevice *pRenderDevice, const char *rgba, int width, int height, ImageFormat format, ETextureScaling eScaling );
  72. // Source1 version
  73. void SetSubTextureRGBA( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall );
  74. void SetSubTextureRGBAEx( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat );
  75. // Source2 version
  76. void SetSubTextureRGBA( IRenderDevice *pRenderDevice, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall );
  77. void UpdateSubTextureRGBA( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat );
  78. #if defined( _X360 )
  79. // Update the local gamerpic texture.
  80. virtual bool SetLocalGamerpicTexture( DWORD userIndex );
  81. // Update the given texture with a remote player's gamerpic.
  82. virtual bool SetRemoteGamerpicTexture( XUID xuid );
  83. #endif // _X360
  84. float m_s0, m_t0, m_s1, m_t1;
  85. private:
  86. void CreateRegen( int nWidth, int nHeight, ImageFormat format );
  87. void ReleaseRegen( void );
  88. void CleanUpMaterial();
  89. ITexture *GetTextureValue( void );
  90. #if defined( _X360 )
  91. // Create the gamerpic material and texture.
  92. void CreateGamerpicTexture( void );
  93. #endif // _X360
  94. private:
  95. enum
  96. {
  97. TEXTURE_IS_PROCEDURAL = 0x1,
  98. TEXTURE_IS_REFERENCE = 0x2
  99. };
  100. CRC32_t m_crcFile;
  101. IMaterial *m_pMaterial;
  102. ITexture *m_pTexture; // Source1 texture support
  103. HRenderTextureStrong m_Texture2; // Source2 texture support
  104. int m_iWide;
  105. int m_iTall;
  106. int m_iInputWide;
  107. int m_iInputTall;
  108. int m_ID;
  109. int m_Flags;
  110. CFontTextureRegen *m_pRegen;
  111. };
  112. //-----------------------------------------------------------------------------
  113. // A class that manages textures used by the material system surface
  114. //-----------------------------------------------------------------------------
  115. class CTextureDictionary : public ITextureDictionary
  116. {
  117. public:
  118. CTextureDictionary( void );
  119. void SetRenderDevice( IRenderDevice *pRenderDevice ); // Source2 support
  120. // Create, destroy textures
  121. int CreateTexture( bool procedural = false );
  122. void DestroyTexture( int id );
  123. void DestroyAllTextures();
  124. // Is this a valid id?
  125. bool IsValidId( int id ) const;
  126. // Binds a material to a texture
  127. virtual void BindTextureToFile( int id, const char *pFileName );
  128. virtual void BindTextureToMaterial( int id, IMaterial *pMaterial );
  129. virtual void BindTextureToMaterialReference( int id, int referenceId, IMaterial *pMaterial );
  130. // Texture info
  131. IMaterial *GetTextureMaterial( int id ); // Source1 version
  132. HRenderTexture GetTextureHandle( int textureId ); // Source2 version
  133. void GetTextureSize(int id, int& iWide, int& iTall );
  134. void GetTextureTexCoords( int id, float &s0, float &t0, float &s1, float &t1 );
  135. void SetTextureRGBA( int id, const char* rgba, int wide, int tall );
  136. void SetTextureRGBAEx( int id, const char* rgba, int wide, int tall, ImageFormat format, ETextureScaling eScaling );
  137. void SetSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall );
  138. void SetSubTextureRGBAEx( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat );
  139. void UpdateSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat );
  140. int FindTextureIdForTextureFile( char const *pFileName );
  141. virtual void BindTextureToMaterial2Reference( int id, int referenceId, IMaterial2 *pMaterial ) { Assert(0); }
  142. virtual void BindTextureToMaterial2( int id, IMaterial2 *pMaterial ) { Assert(0); }
  143. virtual IMaterial2 *GetTextureMaterial2( int id ) { Assert(0); return NULL; }
  144. #if defined( _X360 )
  145. //
  146. // Local gamerpic
  147. //
  148. // Get the texture id for the local gamerpic.
  149. virtual int GetLocalGamerpicTextureID( void ) const { return m_LocalGamerpicTextureID; }
  150. // Update the local gamerpic texture. Use the given texture if a gamerpic cannot be loaded.
  151. virtual bool SetLocalGamerpicTexture( DWORD userIndex, const char *pDefaultGamerpicFileName );
  152. //
  153. // Remote gamerpic
  154. //
  155. // Get the texture id for a remote gamerpic with the given xuid.
  156. virtual int GetRemoteGamerpicTextureID( XUID xuid );
  157. // Update the remote gamerpic texture for the given xuid. Use the given texture if a gamerpic cannot be loaded.
  158. virtual bool SetRemoteGamerpicTextureID( XUID xuid, const char *pDefaultGamerpicFileName );
  159. #endif // _X360
  160. public:
  161. CMatSystemTexture *GetTexture( int id );
  162. private:
  163. #if defined( _X360 )
  164. // Create a new remote gamerpic texture entry in the map.
  165. bool CreateRemoteGamerpicTexture( XUID xuid );
  166. // Create a default remote gamerpic texture entry in the map.
  167. bool CreateDefaultRemoteGamerpicTexture( XUID xuid, const char *pDefaultGamerpicFileName );
  168. #endif // _X360
  169. CUtlLinkedList< CMatSystemTexture, unsigned short > m_Textures; // Source1 textures
  170. CUtlDict< int, int> m_TextureIDs;
  171. #if defined( _X360 )
  172. int m_LocalGamerpicTextureID; // texture index for the local gamerpic
  173. struct RemoteGamerpicData
  174. {
  175. int m_TextureID; // index of the remote gamerpic texture
  176. double m_TimeStamp; // last access time
  177. };
  178. enum
  179. {
  180. MAX_REMOTE_GAMERPIC_TEXTURES = 32
  181. };
  182. CUtlMap< XUID, RemoteGamerpicData > m_RemoteGamerpicTextureIDMap; // map of xuids to texture ids
  183. #endif // _X360
  184. };
  185. static CTextureDictionary s_TextureDictionary;
  186. //-----------------------------------------------------------------------------
  187. // A texture regenerator that holds onto the bits at all times
  188. //-----------------------------------------------------------------------------
  189. class CFontTextureRegen : public ITextureRegenerator
  190. {
  191. public:
  192. CFontTextureRegen( int nWidth, int nHeight, ImageFormat format )
  193. {
  194. m_nFormat = format;
  195. m_nWidth = nWidth;
  196. m_nHeight = nHeight;
  197. if ( IsPC() )
  198. {
  199. int size = ImageLoader::GetMemRequired( m_nWidth, m_nHeight, 1, m_nFormat, false );
  200. m_pTextureBits = new unsigned char[size];
  201. memset( m_pTextureBits, 0, size );
  202. }
  203. else
  204. {
  205. // will be allocated as needed
  206. m_pTextureBits = NULL;
  207. }
  208. }
  209. ~CFontTextureRegen( void )
  210. {
  211. DeleteTextureBits();
  212. }
  213. void UpdateBackingBits( Rect_t &subRect, const unsigned char *pBits, Rect_t &uploadRect, ImageFormat format )
  214. {
  215. int size = ImageLoader::GetMemRequired( m_nWidth, m_nHeight, 1, m_nFormat, false );
  216. if ( IsPC() )
  217. {
  218. if ( !m_pTextureBits )
  219. return;
  220. }
  221. else
  222. {
  223. Assert( !m_pTextureBits );
  224. m_pTextureBits = new unsigned char[size];
  225. memset( m_pTextureBits, 0, size );
  226. }
  227. // Copy subrect into backing bits storage
  228. // source data is expected to be in same format as backing bits
  229. int y;
  230. if ( ImageLoader::SizeInBytes( m_nFormat ) == 4 )
  231. {
  232. bool bIsInputFullRect = ( subRect.width != uploadRect.width || subRect.height != uploadRect.height );
  233. Assert( (subRect.x >= 0) && (subRect.y >= 0) );
  234. Assert( (subRect.x + subRect.width <= m_nWidth) && (subRect.y + subRect.height <= m_nHeight) );
  235. for ( y=0; y < subRect.height; ++y )
  236. {
  237. int idx = ( (subRect.y + y) * m_nWidth + subRect.x ) << 2;
  238. unsigned int *pDst = (unsigned int*)(&m_pTextureBits[ idx ]);
  239. int offset = bIsInputFullRect ? (subRect.y+y)*uploadRect.width + subRect.x : y*uploadRect.width;
  240. const unsigned int *pSrc = (const unsigned int *)(&pBits[ offset << 2 ]);
  241. ImageLoader::ConvertImageFormat( (const unsigned char *)pSrc, format,(unsigned char *)pDst, m_nFormat, subRect.width, 1 );
  242. }
  243. }
  244. else
  245. {
  246. // cannot subrect copy when format is not RGBA
  247. if ( subRect.width != m_nWidth || subRect.height != m_nHeight )
  248. {
  249. Assert( 0 );
  250. return;
  251. }
  252. Q_memcpy( m_pTextureBits, pBits, size );
  253. }
  254. }
  255. virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pSubRect )
  256. {
  257. if ( !m_pTextureBits )
  258. return;
  259. Assert( (pVTFTexture->Width() == m_nWidth) && (pVTFTexture->Height() == m_nHeight) );
  260. int nFormatBytes = ImageLoader::SizeInBytes( m_nFormat );
  261. if ( nFormatBytes == 4 )
  262. {
  263. if ( m_nFormat == pVTFTexture->Format() )
  264. {
  265. int ymax = pSubRect->y + pSubRect->height;
  266. for( int y = pSubRect->y; y < ymax; ++y )
  267. {
  268. // copy each row across for the update
  269. char *pchData = (char *)pVTFTexture->ImageData( 0, 0, 0, 0, y ) + pSubRect->x *nFormatBytes;
  270. int size = ImageLoader::GetMemRequired( pSubRect->width, 1, 1, m_nFormat, false );
  271. V_memcpy( pchData, m_pTextureBits + (y * m_nWidth + pSubRect->x) * nFormatBytes, size );
  272. }
  273. }
  274. else
  275. {
  276. // formats don't match so do a pixel by pixel swizel
  277. CPixelWriter pixelWriter;
  278. pixelWriter.SetPixelMemory(
  279. pVTFTexture->Format(),
  280. pVTFTexture->ImageData( 0, 0, 0 ),
  281. pVTFTexture->RowSizeInBytes( 0 ) );
  282. // Now upload the part we've been asked for
  283. int xmax = pSubRect->x + pSubRect->width;
  284. int ymax = pSubRect->y + pSubRect->height;
  285. int x, y;
  286. for( y = pSubRect->y; y < ymax; ++y )
  287. {
  288. pixelWriter.Seek( pSubRect->x, y );
  289. unsigned char *rgba = &m_pTextureBits[ (y * m_nWidth + pSubRect->x) * nFormatBytes ];
  290. for ( x=pSubRect->x; x < xmax; ++x )
  291. {
  292. pixelWriter.WritePixel( rgba[0], rgba[1], rgba[2], rgba[3] );
  293. rgba += nFormatBytes;
  294. }
  295. }
  296. }
  297. }
  298. else
  299. {
  300. // cannot subrect copy when format is not RGBA
  301. if ( pSubRect->width != m_nWidth || pSubRect->height != m_nHeight )
  302. {
  303. Assert( 0 );
  304. return;
  305. }
  306. int size = ImageLoader::GetMemRequired( m_nWidth, m_nHeight, 1, m_nFormat, false );
  307. Q_memcpy( pVTFTexture->ImageData( 0, 0, 0 ), m_pTextureBits, size );
  308. }
  309. }
  310. virtual void Release()
  311. {
  312. // Called by the material system when this needs to go away
  313. DeleteTextureBits();
  314. }
  315. void DeleteTextureBits()
  316. {
  317. if ( m_pTextureBits )
  318. {
  319. delete [] m_pTextureBits;
  320. m_pTextureBits = NULL;
  321. }
  322. }
  323. private:
  324. unsigned char *m_pTextureBits;
  325. short m_nWidth;
  326. short m_nHeight;
  327. ImageFormat m_nFormat;
  328. };
  329. //-----------------------------------------------------------------------------
  330. // Purpose:
  331. //-----------------------------------------------------------------------------
  332. CMatSystemTexture::CMatSystemTexture( void )
  333. {
  334. m_Texture2 = RENDER_TEXTURE_HANDLE_INVALID;
  335. m_pMaterial = NULL;
  336. m_pTexture = NULL;
  337. m_crcFile = (CRC32_t)0;
  338. m_iWide = m_iTall = 0;
  339. m_s0 = m_t0 = 0;
  340. m_s1 = m_t1 = 1;
  341. m_Flags = 0;
  342. m_pRegen = NULL;
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Purpose:
  346. //-----------------------------------------------------------------------------
  347. CMatSystemTexture::~CMatSystemTexture( void )
  348. {
  349. CleanUpMaterial();
  350. }
  351. bool CMatSystemTexture::IsProcedural( void ) const
  352. {
  353. return (m_Flags & TEXTURE_IS_PROCEDURAL) != 0;
  354. }
  355. void CMatSystemTexture::SetProcedural( bool proc )
  356. {
  357. if (proc)
  358. {
  359. m_Flags |= TEXTURE_IS_PROCEDURAL;
  360. }
  361. else
  362. {
  363. m_Flags &= ~TEXTURE_IS_PROCEDURAL;
  364. }
  365. }
  366. void CMatSystemTexture::CleanUpMaterial()
  367. {
  368. if ( m_pMaterial )
  369. {
  370. // causes the underlying texture (if unreferenced) to be deleted as well
  371. m_pMaterial->DecrementReferenceCount();
  372. m_pMaterial->DeleteIfUnreferenced();
  373. m_pMaterial = NULL;
  374. }
  375. if ( m_pTexture )
  376. {
  377. m_pTexture->SetTextureRegenerator( NULL );
  378. m_pTexture->DecrementReferenceCount();
  379. m_pTexture->DeleteIfUnreferenced();
  380. m_pTexture = NULL;
  381. }
  382. ReleaseRegen();
  383. }
  384. void CMatSystemTexture::CreateRegen( int nWidth, int nHeight, ImageFormat format )
  385. {
  386. Assert( IsProcedural() );
  387. if ( !m_pRegen )
  388. {
  389. m_pRegen = new CFontTextureRegen( nWidth, nHeight, format );
  390. }
  391. }
  392. void CMatSystemTexture::ReleaseRegen( void )
  393. {
  394. if (m_pRegen)
  395. {
  396. if (!IsReference())
  397. {
  398. delete m_pRegen;
  399. }
  400. m_pRegen = NULL;
  401. }
  402. }
  403. // Source1 version
  404. // [smessick] Moved this outside of SetTextureRGBA.
  405. static int s_nTextureId = 0;
  406. void CMatSystemTexture::SetTextureRGBA( const char *rgba, int wide, int tall, ImageFormat format, ETextureScaling eScaling )
  407. {
  408. Assert( IsProcedural() );
  409. if ( !IsProcedural() )
  410. return;
  411. if ( !m_pMaterial )
  412. {
  413. int width = wide;
  414. int height = tall;
  415. // Create a procedural material to fit this texture into
  416. char pTextureName[64];
  417. Q_snprintf( pTextureName, sizeof( pTextureName ), "__vgui_texture_%d", s_nTextureId );
  418. ++s_nTextureId;
  419. int nFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT |
  420. TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_SRGB |
  421. TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY;
  422. if ( eScaling == k_ETextureScalingPointSample )
  423. nFlags |= TEXTUREFLAGS_POINTSAMPLE;
  424. Assert( g_pMaterialSystem );
  425. ITexture *pTexture = g_pMaterialSystem->CreateProceduralTexture(
  426. pTextureName,
  427. TEXTURE_GROUP_VGUI,
  428. width,
  429. height,
  430. format,
  431. nFlags );
  432. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  433. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  434. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  435. pVMTKeyValues->SetInt( "$ignorez", 1 );
  436. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  437. pVMTKeyValues->SetInt( "$translucent", 1 );
  438. pVMTKeyValues->SetString( "$basetexture", pTextureName );
  439. IMaterial *pMaterial = g_pMaterialSystem->CreateMaterial( pTextureName, pVMTKeyValues );
  440. pMaterial->Refresh();
  441. // Has to happen after the refresh
  442. pTexture->DecrementReferenceCount();
  443. SetMaterial( pMaterial );
  444. m_iInputTall = tall;
  445. m_iInputWide = wide;
  446. // Undo the extra +1 refCount
  447. pMaterial->DecrementReferenceCount();
  448. }
  449. Assert( wide <= m_iWide );
  450. Assert( tall <= m_iTall );
  451. // Just replace the whole thing
  452. SetSubTextureRGBAEx( 0, 0, (const unsigned char *)rgba, wide, tall, format );
  453. }
  454. //-----------------------------------------------------------------------------
  455. // Source2 version
  456. //-----------------------------------------------------------------------------
  457. void CMatSystemTexture::SetTextureRGBA( IRenderDevice *pRenderDevice, const char *rgba, int width, int height, ImageFormat format, ETextureScaling eScaling )
  458. {
  459. if ( m_Texture2 == RENDER_TEXTURE_HANDLE_INVALID )
  460. {
  461. static intp s_UniqueID = 0x4500000;
  462. TextureHeader_t spec;
  463. memset( &spec, 0, sizeof(TextureHeader_t) );
  464. spec.m_nWidth = width;
  465. spec.m_nHeight = height;
  466. spec.m_nNumMipLevels = 1;
  467. spec.m_nDepth = 1;
  468. spec.m_nImageFormat = IMAGE_FORMAT_RGBA8888;
  469. char pResourceName[16];
  470. Q_snprintf( pResourceName, sizeof(pResourceName), "%d", s_UniqueID );
  471. m_Texture2 = pRenderDevice->FindOrCreateTexture( "matsystemtexture", pResourceName, &spec );
  472. s_UniqueID++;
  473. }
  474. // This is normally set in SetMaterial(), since source2 has no materials just going to use the texture's size for these bounds.
  475. m_iWide = width;
  476. m_iTall = height;
  477. // Just replace the whole thing
  478. SetSubTextureRGBA( pRenderDevice, 0, 0, (const unsigned char *)rgba, width, height );
  479. }
  480. #if defined( _X360 )
  481. //-----------------------------------------------------------------------------
  482. // Create the gamerpic material and texture.
  483. //-----------------------------------------------------------------------------
  484. void CMatSystemTexture::CreateGamerpicTexture( void )
  485. {
  486. Assert( m_pMaterial == NULL );
  487. // create a procedural material to fit this texture into
  488. char pTextureName[64];
  489. Q_snprintf( pTextureName, sizeof( pTextureName ), "__vgui_texture_%d", s_nTextureId );
  490. ++s_nTextureId;
  491. ITexture *pTexture = g_pMaterialSystem->CreateGamerpicTexture(
  492. pTextureName,
  493. TEXTURE_GROUP_VGUI,
  494. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT |
  495. TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD |
  496. TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY | TEXTUREFLAGS_POINTSAMPLE );
  497. Assert( pTexture != NULL );
  498. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  499. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  500. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  501. pVMTKeyValues->SetInt( "$ignorez", 1 );
  502. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  503. pVMTKeyValues->SetInt( "$translucent", 1 );
  504. pVMTKeyValues->SetString( "$basetexture", pTextureName );
  505. IMaterial *pMaterial = g_pMaterialSystem->CreateMaterial( pTextureName, pVMTKeyValues );
  506. pMaterial->Refresh();
  507. // Has to happen after the refresh
  508. pTexture->DecrementReferenceCount();
  509. SetMaterial( pMaterial );
  510. // undo the extra +1 refCount
  511. pMaterial->DecrementReferenceCount();
  512. }
  513. //-----------------------------------------------------------------------------
  514. // Update the given texture with the player gamerpic for the local player at the given index.
  515. //-----------------------------------------------------------------------------
  516. bool CMatSystemTexture::SetLocalGamerpicTexture( DWORD userIndex )
  517. {
  518. Assert( IsProcedural() );
  519. if ( !IsProcedural() )
  520. {
  521. return false;
  522. }
  523. // Create the material and texture.
  524. if ( !m_pMaterial )
  525. {
  526. CreateGamerpicTexture();
  527. }
  528. // Update the gamerpic texture.
  529. if ( m_pMaterial != NULL )
  530. {
  531. return g_pMaterialSystem->UpdateLocalGamerpicTexture( m_pTexture, userIndex );
  532. }
  533. return false;
  534. }
  535. //-----------------------------------------------------------------------------
  536. // Update the given texture with a remote player's gamerpic.
  537. //-----------------------------------------------------------------------------
  538. bool CMatSystemTexture::SetRemoteGamerpicTexture( XUID xuid )
  539. {
  540. Assert( IsProcedural() );
  541. if ( !IsProcedural() )
  542. {
  543. return false;
  544. }
  545. // Create the material and texture.
  546. if ( !m_pMaterial )
  547. {
  548. CreateGamerpicTexture();
  549. }
  550. // Update the gamerpic texture.
  551. if ( m_pMaterial != NULL )
  552. {
  553. return g_pMaterialSystem->UpdateRemoteGamerpicTexture( m_pTexture, xuid );
  554. }
  555. return false;
  556. }
  557. #endif // _X360
  558. //-----------------------------------------------------------------------------
  559. // Purpose:
  560. //-----------------------------------------------------------------------------
  561. ITexture *CMatSystemTexture::GetTextureValue( void )
  562. {
  563. Assert( IsProcedural() );
  564. if ( !m_pMaterial )
  565. return NULL;
  566. return m_pTexture;
  567. }
  568. void CMatSystemTexture::SetSubTextureRGBA( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall )
  569. {
  570. SetSubTextureRGBAEx( drawX, drawY, rgba, subTextureWide, subTextureTall, IMAGE_FORMAT_RGBA8888 );
  571. }
  572. void CMatSystemTexture::SetSubTextureRGBAEx( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat format )
  573. {
  574. ITexture *pTexture = GetTextureValue();
  575. if ( !pTexture )
  576. return;
  577. Assert( IsProcedural() );
  578. if ( !IsProcedural() )
  579. return;
  580. Assert( drawX < m_iWide );
  581. Assert( drawY < m_iTall );
  582. Assert( drawX + subTextureWide <= m_iWide );
  583. Assert( drawY + subTextureTall <= m_iTall );
  584. Assert( m_pRegen );
  585. Assert( rgba );
  586. Rect_t subRect;
  587. subRect.x = drawX;
  588. subRect.y = drawY;
  589. subRect.width = MIN(subTextureWide,m_iWide-drawX);
  590. subRect.height = MIN(subTextureTall,m_iTall-drawY);
  591. Rect_t textureSize;
  592. textureSize.x = 0;
  593. textureSize.y = 0;
  594. textureSize.width = subTextureWide;
  595. textureSize.height = subTextureTall;
  596. m_pRegen->UpdateBackingBits( subRect, rgba, textureSize, format );
  597. pTexture->Download( &subRect );
  598. if ( IsGameConsole() )
  599. {
  600. // xboxissue - no need to persist "backing bits", saves memory
  601. // the texture (commonly font page) "backing bits" are allocated during UpdateBackingBits() which get blitted
  602. // into by procedural regeneration in preparation for download() which then subrect blits
  603. // out of and into target texture (d3d upload)
  604. // the "backing bits" are then no longer required
  605. m_pRegen->DeleteTextureBits();
  606. }
  607. }
  608. void CMatSystemTexture::UpdateSubTextureRGBA( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat )
  609. {
  610. ITexture *pTexture = GetTextureValue();
  611. if ( !pTexture )
  612. return;
  613. Assert( IsProcedural() );
  614. if ( !IsProcedural() )
  615. return;
  616. Assert( drawX < m_iWide );
  617. Assert( drawY < m_iTall );
  618. Assert( drawX + subTextureWide <= m_iWide );
  619. Assert( drawY + subTextureTall <= m_iTall );
  620. Assert( m_pRegen );
  621. Assert( rgba );
  622. Rect_t subRect;
  623. subRect.x = drawX;
  624. subRect.y = drawY;
  625. subRect.width = subTextureWide;
  626. subRect.height = subTextureTall;
  627. Rect_t textureSize;
  628. textureSize.x = 0;
  629. textureSize.y = 0;
  630. textureSize.width = m_iInputWide;
  631. textureSize.height = m_iInputTall;
  632. m_pRegen->UpdateBackingBits( subRect, rgba, textureSize, imageFormat );
  633. pTexture->Download( &subRect );
  634. if ( IsGameConsole() )
  635. {
  636. // xboxissue - no need to persist "backing bits", saves memory
  637. // the texture (commonly font page) "backing bits" are allocated during UpdateBackingBits() which get blitted
  638. // into by procedural regeneration in preparation for download() which then subrect blits
  639. // out of and into target texture (d3d upload)
  640. // the "backing bits" are then no longer required
  641. m_pRegen->DeleteTextureBits();
  642. }
  643. }
  644. //-----------------------------------------------------------------------------
  645. // Source2 version
  646. //-----------------------------------------------------------------------------
  647. void CMatSystemTexture::SetSubTextureRGBA( IRenderDevice *pRenderDevice, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall )
  648. {
  649. Assert( m_Texture2 != RENDER_TEXTURE_HANDLE_INVALID );
  650. CRenderContextPtr pRenderContext( pRenderDevice, RENDER_TARGET_BINDING_BACK_BUFFER );
  651. Rect_t myRect = { drawX, drawY, subTextureWide, subTextureTall };
  652. pRenderContext->SetTextureData( m_Texture2, NULL, rgba, subTextureWide * subTextureTall * 4, false, 0, &myRect );
  653. }
  654. //-----------------------------------------------------------------------------
  655. //
  656. //-----------------------------------------------------------------------------
  657. void CMatSystemTexture::SetCRC( CRC32_t val )
  658. {
  659. m_crcFile = val;
  660. }
  661. //-----------------------------------------------------------------------------
  662. //
  663. //-----------------------------------------------------------------------------
  664. CRC32_t CMatSystemTexture::GetCRC() const
  665. {
  666. return m_crcFile;
  667. }
  668. //-----------------------------------------------------------------------------
  669. // Source1 version
  670. //-----------------------------------------------------------------------------
  671. void CMatSystemTexture::SetMaterial( IMaterial *pMaterial )
  672. {
  673. if ( !g_pMaterialSystem )
  674. return;
  675. if ( pMaterial )
  676. {
  677. // Increment the reference count of the new material
  678. // Do it before cleaning up the old material just in
  679. // case the old material refers to the new one, we
  680. // wouldn't want to destroy the new material.
  681. pMaterial->IncrementReferenceCount();
  682. }
  683. // Decrement references to old texture
  684. CleanUpMaterial();
  685. m_pMaterial = pMaterial;
  686. if (!m_pMaterial)
  687. {
  688. m_iWide = m_iTall = 0;
  689. m_s0 = m_t0 = 0.0f;
  690. m_s1 = m_t1 = 1.0f;
  691. return;
  692. }
  693. // Compute texture size
  694. m_iWide = m_pMaterial->GetMappingWidth();
  695. m_iTall = m_pMaterial->GetMappingHeight();
  696. // Compute texture coordinates
  697. float flPixelCenterX = 0.0f;
  698. float flPixelCenterY = 0.0f;
  699. // TOGL Linux/Win now automatically accounts for the half pixel offset between D3D9 vs. GL, but OSX's version of togl doesn't
  700. if ( !IsOSX() && !IsX360() )
  701. {
  702. // only do texel fudges on D3D
  703. if ( m_iWide > 0.0f && m_iTall > 0.0f)
  704. {
  705. flPixelCenterX = 0.5f / m_iWide;
  706. flPixelCenterY = 0.5f / m_iTall;
  707. }
  708. }
  709. m_s0 = flPixelCenterX;
  710. m_t0 = flPixelCenterY;
  711. // FIXME: Old code used +, it should be - yes?!??!
  712. m_s1 = 1.0 - flPixelCenterX;
  713. m_t1 = 1.0 - flPixelCenterY;
  714. if ( IsProcedural() )
  715. {
  716. bool bFound;
  717. IMaterialVar *pNameVar = m_pMaterial->FindVar( "$baseTexture", &bFound );
  718. if ( bFound && pNameVar->IsDefined() )
  719. {
  720. m_pTexture = pNameVar->GetTextureValue();
  721. if ( m_pTexture )
  722. {
  723. m_pTexture->IncrementReferenceCount();
  724. // Upload new data
  725. CreateRegen( m_iWide, m_iTall, m_pTexture->GetImageFormat() );
  726. m_pTexture->SetTextureRegenerator( m_pRegen );
  727. }
  728. }
  729. }
  730. }
  731. //-----------------------------------------------------------------------------
  732. // This is used when we want different rendering state sharing the same procedural texture (fonts)
  733. //-----------------------------------------------------------------------------
  734. void CMatSystemTexture::ReferenceOtherProcedural( CMatSystemTexture *pTexture, IMaterial *pMaterial )
  735. {
  736. // Decrement references to old texture
  737. CleanUpMaterial();
  738. Assert( pTexture->IsProcedural() );
  739. m_Flags |= TEXTURE_IS_REFERENCE;
  740. m_pMaterial = pMaterial;
  741. if (!m_pMaterial)
  742. {
  743. m_iWide = m_iTall = 0;
  744. m_s0 = m_t0 = 0.0f;
  745. m_s1 = m_t1 = 1.0f;
  746. return;
  747. }
  748. m_iWide = pTexture->m_iWide;
  749. m_iTall = pTexture->m_iTall;
  750. m_s0 = pTexture->m_s0;
  751. m_t0 = pTexture->m_t0;
  752. m_s1 = pTexture->m_s1;
  753. m_t1 = pTexture->m_t1;
  754. Assert( (pMaterial->GetMappingWidth() == m_iWide) && (pMaterial->GetMappingHeight() == m_iTall) );
  755. // Increment its reference count
  756. m_pMaterial->IncrementReferenceCount();
  757. bool bFound;
  758. IMaterialVar *tv = m_pMaterial->FindVar( "$baseTexture", &bFound );
  759. if ( bFound )
  760. {
  761. m_pTexture = tv->GetTextureValue();
  762. if ( m_pTexture )
  763. {
  764. m_pTexture->IncrementReferenceCount();
  765. Assert( m_pTexture == pTexture->m_pTexture );
  766. // Reference, but do *not* create a new one!!!
  767. m_pRegen = pTexture->m_pRegen;
  768. }
  769. }
  770. }
  771. void CMatSystemTexture::SetMaterial( const char *pFileName )
  772. {
  773. // Get a pointer to the new material
  774. Assert( g_pMaterialSystem );
  775. IMaterial *pMaterial = g_pMaterialSystem->FindMaterial( pFileName, TEXTURE_GROUP_VGUI );
  776. #if defined( DEVELOPMENT_ONLY ) || defined( ALLOW_TEXT_MODE )
  777. static bool s_bTextMode = CommandLine()->HasParm( "-textmode" );
  778. #else
  779. const bool s_bTextMode = false;
  780. #endif
  781. if ( IsErrorMaterial( pMaterial ) && !s_bTextMode )
  782. {
  783. if (IsOSX())
  784. {
  785. printf( "\n ##### Missing Vgui material %s\n", pFileName );
  786. }
  787. Msg( "--- Missing Vgui material %s\n", pFileName );
  788. }
  789. SetMaterial( pMaterial );
  790. }
  791. //-----------------------------------------------------------------------------
  792. // Singleton instance
  793. //-----------------------------------------------------------------------------
  794. ITextureDictionary *TextureDictionary()
  795. {
  796. return &s_TextureDictionary;
  797. }
  798. //-----------------------------------------------------------------------------
  799. // Constructor.
  800. //-----------------------------------------------------------------------------
  801. CTextureDictionary::CTextureDictionary( void )
  802. {
  803. // First entry is bogus texture
  804. m_Textures.AddToTail();
  805. #if defined( _X360 )
  806. // Set the local gamerpic index to be invalid.
  807. m_LocalGamerpicTextureID = INVALID_TEXTURE_ID;
  808. // Set the less than function for the remote gamerpic map.
  809. m_RemoteGamerpicTextureIDMap.SetLessFunc( XuidLessFunc );
  810. #endif // _X360
  811. }
  812. //-----------------------------------------------------------------------------
  813. // Create, destroy textures
  814. //-----------------------------------------------------------------------------
  815. int CTextureDictionary::CreateTexture( bool procedural /*=false*/ )
  816. {
  817. int idx = m_Textures.AddToTail();
  818. CMatSystemTexture &texture = m_Textures[idx];
  819. texture.SetProcedural( procedural );
  820. texture.SetId( idx );
  821. return idx;
  822. }
  823. void CTextureDictionary::DestroyTexture( int id )
  824. {
  825. Assert( id != m_Textures.InvalidIndex() && m_Textures.IsInList( id ) );
  826. if ( id != INVALID_TEXTURE_ID )
  827. {
  828. if ( m_Textures.IsInList( id ) )
  829. {
  830. m_Textures.Remove( (unsigned short)id );
  831. }
  832. }
  833. }
  834. void CTextureDictionary::DestroyAllTextures()
  835. {
  836. m_Textures.RemoveAll();
  837. #if defined( _X360 )
  838. // Clean the map as well. All ids were destroyed in m_Textures.RemoveAll().
  839. m_RemoteGamerpicTextureIDMap.RemoveAll();
  840. // This texture id was destroyed in m_Textures.RemoveAll().
  841. m_LocalGamerpicTextureID = INVALID_TEXTURE_ID;
  842. #endif // _X360
  843. // First entry is bogus texture
  844. m_Textures.AddToTail();
  845. CMatSystemTexture &texture = m_Textures[0];
  846. texture.SetId( 0 );
  847. }
  848. //-----------------------------------------------------------------------------
  849. // Fill in texture contents
  850. //-----------------------------------------------------------------------------
  851. void CTextureDictionary::SetTextureRGBA( int id, const char* rgba, int wide, int tall )
  852. {
  853. SetTextureRGBAEx( id, rgba, wide, tall, IMAGE_FORMAT_RGBA8888, k_ETextureScalingPointSample );
  854. }
  855. void CTextureDictionary::SetTextureRGBAEx( int id, const char* rgba, int wide, int tall, ImageFormat format, ETextureScaling eScaling )
  856. {
  857. if (!IsValidId(id))
  858. {
  859. Msg( "SetTextureRGBA: Invalid texture id %i\n", id );
  860. return;
  861. }
  862. CMatSystemTexture &texture = m_Textures[id];
  863. if ( g_pMaterialSystem )
  864. {
  865. // Source1 support
  866. texture.SetTextureRGBA( rgba, wide, tall, format, eScaling );
  867. }
  868. else
  869. {
  870. // Source2 support
  871. texture.SetTextureRGBA( g_pRenderDevice, rgba, wide, tall, format, eScaling );
  872. }
  873. }
  874. //-----------------------------------------------------------------------------
  875. // Fill in texture contents
  876. //-----------------------------------------------------------------------------
  877. void CTextureDictionary::SetSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall )
  878. {
  879. SetSubTextureRGBAEx( id, drawX, drawY, rgba, subTextureWide, subTextureTall, IMAGE_FORMAT_RGBA8888 );
  880. }
  881. void CTextureDictionary::SetSubTextureRGBAEx( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat format )
  882. {
  883. if (!IsValidId(id))
  884. {
  885. Msg( "SetSubTextureRGBA: Invalid texture id %i\n", id );
  886. return;
  887. }
  888. CMatSystemTexture &texture = m_Textures[id];
  889. if ( g_pMaterialSystem )
  890. {
  891. // Source1 support
  892. texture.SetSubTextureRGBAEx( drawX, drawY, rgba, subTextureWide, subTextureTall, format );
  893. }
  894. else
  895. {
  896. // Source2 support
  897. texture.SetSubTextureRGBA( g_pRenderDevice, drawX, drawY, rgba, subTextureWide, subTextureTall );
  898. }
  899. }
  900. void CTextureDictionary::UpdateSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat )
  901. {
  902. if (!IsValidId(id))
  903. {
  904. Msg( "UpdateSubTextureRGBA: Invalid texture id %i\n", id );
  905. return;
  906. }
  907. CMatSystemTexture &texture = m_Textures[id];
  908. texture.UpdateSubTextureRGBA( drawX, drawY, rgba, subTextureWide, subTextureTall, imageFormat );
  909. }
  910. #if defined( _X360 )
  911. //-----------------------------------------------------------------------------
  912. // Update the local gamerpic texture. Use the given texture if a gamerpic cannot be loaded.
  913. //-----------------------------------------------------------------------------
  914. bool CTextureDictionary::SetLocalGamerpicTexture( DWORD userIndex, const char *pDefaultGamerpicFileName )
  915. {
  916. Assert( pDefaultGamerpicFileName != NULL );
  917. if ( !IsValidId( m_LocalGamerpicTextureID ) )
  918. {
  919. // Create the local gamerpic texture id.
  920. m_LocalGamerpicTextureID = CreateTexture( true );
  921. }
  922. else if ( !m_Textures[m_LocalGamerpicTextureID].IsProcedural() )
  923. {
  924. // The existing texture must be procedural to use a gamerpic. If the existing one
  925. // isn't, then destroy it. This can happen if the texture is using the default image.
  926. DestroyTexture( m_LocalGamerpicTextureID );
  927. m_LocalGamerpicTextureID = CreateTexture( true );
  928. }
  929. // Fill the texture with the local gamerpic.
  930. CMatSystemTexture &texture = m_Textures[m_LocalGamerpicTextureID];
  931. if ( !texture.SetLocalGamerpicTexture( userIndex ) )
  932. {
  933. // Remove the bad texture.
  934. DestroyTexture( m_LocalGamerpicTextureID );
  935. // Try to use the default texture instead.
  936. m_LocalGamerpicTextureID = CreateTexture( false ); // not procedural
  937. BindTextureToFile( m_LocalGamerpicTextureID, pDefaultGamerpicFileName );
  938. }
  939. return IsValidId( m_LocalGamerpicTextureID );
  940. }
  941. //-----------------------------------------------------------------------------
  942. // Get the texture id for a remote gamerpic with the given xuid.
  943. //-----------------------------------------------------------------------------
  944. int CTextureDictionary::GetRemoteGamerpicTextureID( XUID xuid )
  945. {
  946. int index = m_RemoteGamerpicTextureIDMap.Find( xuid );
  947. if ( index != m_RemoteGamerpicTextureIDMap.InvalidIndex() )
  948. {
  949. RemoteGamerpicData &gamerpicData = m_RemoteGamerpicTextureIDMap.Element( index );
  950. gamerpicData.m_TimeStamp = g_pVGuiSystem->GetCurrentTime(); // save the time stamp
  951. return gamerpicData.m_TextureID;
  952. }
  953. return INVALID_TEXTURE_ID;
  954. }
  955. //-----------------------------------------------------------------------------
  956. // Create a new remote gamerpic texture entry in the map
  957. //-----------------------------------------------------------------------------
  958. bool CTextureDictionary::CreateRemoteGamerpicTexture( XUID xuid )
  959. {
  960. // Check for a bad xuid.
  961. if ( xuid == INVALID_XUID )
  962. {
  963. Msg( "[CTextureDictionary] invalid xuid %d!\n", xuid );
  964. return false;
  965. }
  966. // Create the new texture.
  967. int id = CreateTexture( true );
  968. if ( !IsValidId( id ) )
  969. {
  970. return false;
  971. }
  972. // Update the gamerpic texture.
  973. CMatSystemTexture &texture = m_Textures[id];
  974. if ( !texture.SetRemoteGamerpicTexture( xuid ) )
  975. {
  976. DestroyTexture( id );
  977. return false;
  978. }
  979. // Add a new entry in the map.
  980. RemoteGamerpicData gamerpicData;
  981. gamerpicData.m_TextureID = id;
  982. gamerpicData.m_TimeStamp = g_pVGuiSystem->GetCurrentTime(); // set the time stamp
  983. m_RemoteGamerpicTextureIDMap.Insert( xuid, gamerpicData );
  984. return true;
  985. }
  986. //-----------------------------------------------------------------------------
  987. // Create a remote gamerpic texture using the given default image
  988. //-----------------------------------------------------------------------------
  989. bool CTextureDictionary::CreateDefaultRemoteGamerpicTexture( XUID xuid, const char *pDefaultGamerpicFileName )
  990. {
  991. // Check for a bad xuid.
  992. if ( xuid == INVALID_XUID )
  993. {
  994. Msg( "[CTextureDictionary] invalid xuid %d!\n", xuid );
  995. return false;
  996. }
  997. // Create the new texture.
  998. int id = CreateTexture( false ); // not procedural
  999. if ( !IsValidId( id ) )
  1000. {
  1001. return false;
  1002. }
  1003. // Load the texture from file.
  1004. BindTextureToFile( id, pDefaultGamerpicFileName );
  1005. // Add a new entry in the map.
  1006. RemoteGamerpicData gamerpicData;
  1007. gamerpicData.m_TextureID = id;
  1008. gamerpicData.m_TimeStamp = g_pVGuiSystem->GetCurrentTime(); // set the time stamp
  1009. m_RemoteGamerpicTextureIDMap.Insert( xuid, gamerpicData );
  1010. return true;
  1011. }
  1012. //-----------------------------------------------------------------------------
  1013. // Update the remote gamerpic texture for the given xuid. Use the given texture if a gamerpic cannot be loaded.
  1014. //-----------------------------------------------------------------------------
  1015. bool CTextureDictionary::SetRemoteGamerpicTextureID( XUID xuid, const char *pDefaultGamerpicFileName )
  1016. {
  1017. int id = GetRemoteGamerpicTextureID( xuid );
  1018. if ( IsValidId( id ) )
  1019. {
  1020. // Update the existing gamerpic texture for this xuid.
  1021. CMatSystemTexture &texture = m_Textures[id];
  1022. if ( !texture.SetRemoteGamerpicTexture( xuid ) )
  1023. {
  1024. // Remove from the map and the texture array.
  1025. m_RemoteGamerpicTextureIDMap.Remove( xuid );
  1026. DestroyTexture( id );
  1027. // Use the default texture.
  1028. return CreateDefaultRemoteGamerpicTexture( xuid, pDefaultGamerpicFileName );
  1029. }
  1030. }
  1031. else
  1032. {
  1033. if ( m_RemoteGamerpicTextureIDMap.Count() >= MAX_REMOTE_GAMERPIC_TEXTURES )
  1034. {
  1035. //
  1036. // Find the oldest entry in the map.
  1037. //
  1038. int gamerpicCount = m_RemoteGamerpicTextureIDMap.Count();
  1039. COMPILE_TIME_ASSERT( MAX_REMOTE_GAMERPIC_TEXTURES > 1 );
  1040. RemoteGamerpicData &gamerpicData = m_RemoteGamerpicTextureIDMap.Element( 0 );
  1041. int gamerpicIndex = 0;
  1042. for ( int i = 1; i < gamerpicCount; ++i )
  1043. {
  1044. RemoteGamerpicData &nextGamerpicData = m_RemoteGamerpicTextureIDMap.Element( i );
  1045. if ( nextGamerpicData.m_TimeStamp < gamerpicData.m_TimeStamp )
  1046. {
  1047. gamerpicData = nextGamerpicData;
  1048. gamerpicIndex = i;
  1049. }
  1050. }
  1051. // Remove the oldest entry.
  1052. id = gamerpicData.m_TextureID;
  1053. m_RemoteGamerpicTextureIDMap.RemoveAt( gamerpicIndex );
  1054. DestroyTexture( id );
  1055. }
  1056. // Create a new entry.
  1057. if ( !CreateRemoteGamerpicTexture( xuid ) )
  1058. {
  1059. return CreateDefaultRemoteGamerpicTexture( xuid, pDefaultGamerpicFileName );
  1060. }
  1061. }
  1062. return true;
  1063. }
  1064. #endif // _X360
  1065. //-----------------------------------------------------------------------------
  1066. // Returns true if the id is valid
  1067. //-----------------------------------------------------------------------------
  1068. bool CTextureDictionary::IsValidId( int id ) const
  1069. {
  1070. Assert( id != 0 );
  1071. if ( id == 0 )
  1072. return false;
  1073. if( m_Textures.IsValidIndex( id ) )
  1074. {
  1075. if ( !m_Textures.IsInList( id ) )
  1076. {
  1077. return false;
  1078. }
  1079. return true;
  1080. }
  1081. return false;
  1082. }
  1083. //-----------------------------------------------------------------------------
  1084. // Binds a file to a particular texture
  1085. //-----------------------------------------------------------------------------
  1086. void CTextureDictionary::BindTextureToFile( int id, const char *pFileName )
  1087. {
  1088. if (!IsValidId(id))
  1089. {
  1090. Msg( "BindTextureToFile: Invalid texture id for file %s\n", pFileName );
  1091. return;
  1092. }
  1093. CMatSystemTexture &texture = m_Textures[id];
  1094. // Reload from file if the material was never loaded, or if the filename has changed at all
  1095. CRC32_t fileNameCRC = Texture_CRCName( pFileName );
  1096. if ( !texture.GetMaterial() || fileNameCRC != texture.GetCRC() )
  1097. {
  1098. // New texture name
  1099. texture.SetCRC( fileNameCRC );
  1100. texture.SetMaterial( pFileName );
  1101. }
  1102. }
  1103. //-----------------------------------------------------------------------------
  1104. // Binds a material to a texture
  1105. //-----------------------------------------------------------------------------
  1106. void CTextureDictionary::BindTextureToMaterial( int id, IMaterial *pMaterial )
  1107. {
  1108. if (!IsValidId(id))
  1109. {
  1110. Msg( "BindTextureToFile: Invalid texture id %d\n", id );
  1111. return;
  1112. }
  1113. CMatSystemTexture &texture = m_Textures[id];
  1114. texture.SetMaterial( pMaterial );
  1115. }
  1116. //-----------------------------------------------------------------------------
  1117. // Binds a material to a texture reference
  1118. //-----------------------------------------------------------------------------
  1119. void CTextureDictionary::BindTextureToMaterialReference( int id, int referenceId, IMaterial *pMaterial )
  1120. {
  1121. if (!IsValidId(id) || !IsValidId(referenceId))
  1122. {
  1123. Msg( "BindTextureToFile: Invalid texture ids %d %d\n", id, referenceId );
  1124. return;
  1125. }
  1126. CMatSystemTexture &texture = m_Textures[id];
  1127. CMatSystemTexture &textureSource = m_Textures[referenceId];
  1128. texture.ReferenceOtherProcedural( &textureSource, pMaterial );
  1129. }
  1130. //-----------------------------------------------------------------------------
  1131. // Returns the material associated with an id
  1132. //-----------------------------------------------------------------------------
  1133. IMaterial *CTextureDictionary::GetTextureMaterial( int id )
  1134. {
  1135. if (!IsValidId(id))
  1136. return NULL;
  1137. return m_Textures[id].GetMaterial();
  1138. }
  1139. //-----------------------------------------------------------------------------
  1140. // Returns the texture handle associated with an id
  1141. //-----------------------------------------------------------------------------
  1142. HRenderTexture CTextureDictionary::GetTextureHandle( int id )
  1143. {
  1144. if (!IsValidId(id))
  1145. return NULL;
  1146. return m_Textures[id].GetTextureHandle();
  1147. }
  1148. //-----------------------------------------------------------------------------
  1149. // Returns the material size associated with an id
  1150. //-----------------------------------------------------------------------------
  1151. void CTextureDictionary::GetTextureSize(int id, int& iWide, int& iTall )
  1152. {
  1153. if (!IsValidId(id))
  1154. {
  1155. iWide = iTall = 0;
  1156. return;
  1157. }
  1158. iWide = m_Textures[id].Width();
  1159. iTall = m_Textures[id].Height();
  1160. }
  1161. //-----------------------------------------------------------------------------
  1162. //
  1163. //-----------------------------------------------------------------------------
  1164. void CTextureDictionary::GetTextureTexCoords( int id, float &s0, float &t0, float &s1, float &t1 )
  1165. {
  1166. if (!IsValidId(id))
  1167. {
  1168. s0 = t0 = 0.0f;
  1169. s1 = t1 = 1.0f;
  1170. return;
  1171. }
  1172. s0 = m_Textures[id].m_s0;
  1173. t0 = m_Textures[id].m_t0;
  1174. s1 = m_Textures[id].m_s1;
  1175. t1 = m_Textures[id].m_t1;
  1176. }
  1177. //-----------------------------------------------------------------------------
  1178. // Purpose:
  1179. // Input : id -
  1180. // Output : CMatSystemTexture
  1181. //-----------------------------------------------------------------------------
  1182. CMatSystemTexture *CTextureDictionary::GetTexture( int id )
  1183. {
  1184. if (!IsValidId(id))
  1185. return NULL;
  1186. return &m_Textures[ id ];
  1187. }
  1188. //-----------------------------------------------------------------------------
  1189. // Purpose:
  1190. // Input : *pFileName -
  1191. //-----------------------------------------------------------------------------
  1192. int CTextureDictionary::FindTextureIdForTextureFile( char const *pFileName )
  1193. {
  1194. for ( int i = m_Textures.Head(); i != m_Textures.InvalidIndex(); i = m_Textures.Next( i ) )
  1195. {
  1196. CMatSystemTexture *tex = &m_Textures[i];
  1197. if ( !tex )
  1198. continue;
  1199. IMaterial *mat = tex->GetMaterial();
  1200. if ( !mat )
  1201. continue;
  1202. if ( !stricmp( mat->GetName(), pFileName ) )
  1203. return i;
  1204. }
  1205. return -1;
  1206. }