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.

1429 lines
38 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implementation of IEditorTexture interface for materials.
  4. //
  5. // Materials are kept in a directory tree containing pairs of VMT
  6. // and VTF files. Each pair of files represents a material.
  7. //
  8. //=============================================================================//
  9. #include "stdafx.h"
  10. #include <process.h>
  11. #include <afxtempl.h>
  12. #include <io.h>
  13. #include <sys\stat.h>
  14. #include <fcntl.h>
  15. #include "hammer.h"
  16. #include "MapDoc.h"
  17. #include "Material.h"
  18. #include "Options.h"
  19. #include "MainFrm.h"
  20. #include "GlobalFunctions.h"
  21. #include "WADTypes.h"
  22. #include "BSPFile.h"
  23. #include "materialsystem/IMaterialSystem.h"
  24. #include "materialsystem/IMaterialSystemHardwareConfig.h"
  25. #include "materialsystem/MaterialSystem_Config.h"
  26. #include "materialsystem/MaterialSystemUtil.h"
  27. #include "materialsystem/ITexture.h"
  28. #include "materialsystem/IMaterial.h"
  29. #include "bitmap/imageformat.h" // hack : don't want to include this just for ImageFormat
  30. #include "FileSystem.h"
  31. #include "StudioModel.h"
  32. #include "tier1/strtools.h"
  33. #include "tier0/dbg.h"
  34. #include "TextureSystem.h"
  35. #include "materialproxyfactory_wc.h"
  36. #include "vstdlib/cvar.h"
  37. #include "interface.h"
  38. // memdbgon must be the last include file in a .cpp file!!!
  39. #include <tier0/memdbgon.h>
  40. #pragma warning(disable:4244)
  41. #define _GraphicCacheAllocate(n) malloc(n)
  42. MaterialSystem_Config_t g_materialSystemConfig;
  43. static MaterialHandle_t g_CurrMaterial;
  44. extern void ScaleBitmap(CSize sizeSrc, CSize sizeDest, char *src, char *dest);
  45. struct MaterialCacheEntry_t
  46. {
  47. char szName[MAX_PATH]; //
  48. CMaterial *pMaterial; //
  49. int nRefCount; //
  50. };
  51. //-----------------------------------------------------------------------------
  52. // Purpose:
  53. // This class speeds up the call to IMaterial::GetPreviewImageProperties because
  54. // we call it thousands of times per level load when there are detail props.
  55. //-----------------------------------------------------------------------------
  56. class CPreviewImagePropertiesCache
  57. {
  58. public:
  59. //-----------------------------------------------------------------------------
  60. // Purpose: Anyone can call this instead of IMaterial::GetPreviewImageProperties
  61. // and it'll be a lot faster if there are redundant calls to it.
  62. //-----------------------------------------------------------------------------
  63. static PreviewImageRetVal_t GetPreviewImageProperties( IMaterial *pMaterial, int *width, int *height, ImageFormat *imageFormat, bool* isTranslucent )
  64. {
  65. int i = s_PreviewImagePropertiesCache.Find( pMaterial );
  66. if ( i == s_PreviewImagePropertiesCache.InvalidIndex() )
  67. {
  68. // Add an entry to the cache.
  69. CPreviewImagePropertiesCache::CEntry entry;
  70. entry.m_RetVal = pMaterial->GetPreviewImageProperties( &entry.m_Width, &entry.m_Height, &entry.m_ImageFormat, &entry.m_bIsTranslucent );
  71. i = s_PreviewImagePropertiesCache.Insert( pMaterial, entry );
  72. }
  73. CPreviewImagePropertiesCache::CEntry &entry = s_PreviewImagePropertiesCache[i];
  74. *width = entry.m_Width;
  75. *height = entry.m_Height;
  76. *imageFormat = entry.m_ImageFormat;
  77. *isTranslucent = entry.m_bIsTranslucent;
  78. return entry.m_RetVal;
  79. }
  80. private:
  81. class CEntry
  82. {
  83. public:
  84. int m_Width;
  85. int m_Height;
  86. ImageFormat m_ImageFormat;
  87. bool m_bIsTranslucent;
  88. PreviewImageRetVal_t m_RetVal;
  89. };
  90. static bool PreviewImageLessFunc( IMaterial* const &a, IMaterial* const &b )
  91. {
  92. return a < b;
  93. }
  94. static CUtlMap<IMaterial*, CPreviewImagePropertiesCache::CEntry> s_PreviewImagePropertiesCache;
  95. };
  96. CUtlMap<IMaterial*, CPreviewImagePropertiesCache::CEntry> CPreviewImagePropertiesCache::s_PreviewImagePropertiesCache( 64, 64, &CPreviewImagePropertiesCache::PreviewImageLessFunc );
  97. //-----------------------------------------------------------------------------
  98. // Purpose: stuff for caching textures in memory.
  99. //-----------------------------------------------------------------------------
  100. class CMaterialImageCache
  101. {
  102. public:
  103. CMaterialImageCache(int maxNumGraphicsLoaded);
  104. ~CMaterialImageCache(void);
  105. void EnCache( CMaterial *pMaterial );
  106. protected:
  107. CMaterial **pool;
  108. int cacheSize;
  109. int currentID; // next one to get killed.
  110. };
  111. //-----------------------------------------------------------------------------
  112. // Purpose: Constructor. Allocates a pool of material pointers.
  113. // Input : maxNumGraphicsLoaded -
  114. //-----------------------------------------------------------------------------
  115. CMaterialImageCache::CMaterialImageCache(int maxNumGraphicsLoaded)
  116. {
  117. cacheSize = maxNumGraphicsLoaded;
  118. pool = new CMaterialPtr[cacheSize];
  119. if (pool != NULL)
  120. {
  121. memset(pool, 0, sizeof(CMaterialPtr) * cacheSize);
  122. }
  123. currentID = 0;
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Purpose: Destructor. Frees the pool memory.
  127. //-----------------------------------------------------------------------------
  128. CMaterialImageCache::~CMaterialImageCache(void)
  129. {
  130. if (pool != NULL)
  131. {
  132. delete [] pool;
  133. }
  134. }
  135. //-----------------------------------------------------------------------------
  136. // Purpose:
  137. // Input : *pMaterial -
  138. //-----------------------------------------------------------------------------
  139. void CMaterialImageCache::EnCache( CMaterial *pMaterial )
  140. {
  141. if (pMaterial->m_pData != NULL)
  142. {
  143. // Already cached.
  144. return;
  145. }
  146. // kill currentID
  147. if ((pool[currentID]) && (pool[currentID]->HasData()))
  148. {
  149. pool[currentID]->FreeData();
  150. }
  151. pool[currentID] = pMaterial;
  152. pMaterial->LoadMaterialImage();
  153. currentID = ( currentID + 1 ) % cacheSize;
  154. #if 0
  155. OutputDebugString( "CMaterialCache::Encache: " );
  156. OutputDebugString( pMaterial->m_szName );
  157. OutputDebugString( "\n" );
  158. #endif
  159. }
  160. static CMaterialImageCache *g_pMaterialImageCache = NULL;
  161. //-----------------------------------------------------------------------------
  162. // Purpose:
  163. //-----------------------------------------------------------------------------
  164. CMaterialCache::CMaterialCache(void)
  165. {
  166. m_pCache = NULL;
  167. m_nMaxEntries = 0;
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. //-----------------------------------------------------------------------------
  172. CMaterialCache::~CMaterialCache(void)
  173. {
  174. if (m_pCache != NULL)
  175. {
  176. delete m_pCache;
  177. }
  178. }
  179. //-----------------------------------------------------------------------------
  180. // Purpose: Allocates cache memory for a given number of materials.
  181. // Input : nMaxEntries - Maximum number of materials in the cache.
  182. // Output : Returns true on success, false on failure.
  183. //-----------------------------------------------------------------------------
  184. bool CMaterialCache::Create(int nMaxEntries)
  185. {
  186. Assert((m_pCache == NULL) && (m_nMaxEntries == 0));
  187. if (m_pCache != NULL)
  188. {
  189. delete m_pCache;
  190. m_pCache = NULL;
  191. m_nMaxEntries = 0;
  192. }
  193. if (nMaxEntries <= 0)
  194. {
  195. nMaxEntries = 500;
  196. }
  197. m_pCache = new MaterialCacheEntry_t[nMaxEntries];
  198. if (m_pCache != NULL)
  199. {
  200. memset(m_pCache, 0, sizeof(m_pCache[0]) * nMaxEntries);
  201. m_nMaxEntries = nMaxEntries;
  202. }
  203. return(m_pCache != NULL);
  204. }
  205. //-----------------------------------------------------------------------------
  206. // Purpose: Factory. Creates a material by name, first looking in the cache.
  207. // Input : pszMaterialName - Name of material, ie "brick/brickfloor01".
  208. // Output : Returns a pointer to the new material object, NULL if the given
  209. // material did not exist.
  210. //-----------------------------------------------------------------------------
  211. CMaterial *CMaterialCache::CreateMaterial(const char *pszMaterialName)
  212. {
  213. CMaterial *pMaterial = NULL;
  214. if (pszMaterialName != NULL)
  215. {
  216. //
  217. // Find this material in the cache. If it is here, return it.
  218. //
  219. pMaterial = FindMaterial(pszMaterialName);
  220. if (pMaterial == NULL)
  221. {
  222. //
  223. // Not found in the cache, try to create it.
  224. //
  225. pMaterial = CMaterial::CreateMaterial(pszMaterialName, true);
  226. if (pMaterial != NULL)
  227. {
  228. //
  229. // Success. Add the newly created material to the cache.
  230. //
  231. AddMaterial(pMaterial);
  232. return(pMaterial);
  233. }
  234. }
  235. else
  236. {
  237. //
  238. // Found in the cache, bump the reference count.
  239. //
  240. AddRef(pMaterial);
  241. }
  242. }
  243. return(pMaterial);
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Purpose: Finds a material in the cache.
  247. // Input : char *pszMaterialName -
  248. // Output : CMaterial
  249. //-----------------------------------------------------------------------------
  250. void CMaterialCache::AddMaterial(CMaterial *pMaterial)
  251. {
  252. if (pMaterial != NULL)
  253. {
  254. Assert(m_nEntries < m_nMaxEntries);
  255. if (m_nEntries < m_nMaxEntries)
  256. {
  257. m_pCache[m_nEntries].pMaterial = pMaterial;
  258. m_pCache[m_nEntries].nRefCount = 1;
  259. m_nEntries++;
  260. }
  261. }
  262. }
  263. //-----------------------------------------------------------------------------
  264. // Purpose: Increments the reference count on a material in the cache. Called by
  265. // client code when a pointer to the model is copied, making that
  266. // reference independent.
  267. // Input : pModel - Model for which to increment the reference count.
  268. //-----------------------------------------------------------------------------
  269. void CMaterialCache::AddRef(CMaterial *pMaterial)
  270. {
  271. for (int i = 0; i < m_nEntries; i++)
  272. {
  273. if (m_pCache[i].pMaterial == pMaterial)
  274. {
  275. m_pCache[i].nRefCount++;
  276. return;
  277. }
  278. }
  279. }
  280. //-----------------------------------------------------------------------------
  281. // Purpose: Finds a material in the cache by name.
  282. // Input : char *pszMaterialName -
  283. // Output : CMaterial
  284. //-----------------------------------------------------------------------------
  285. CMaterial *CMaterialCache::FindMaterial(const char *pszMaterialName)
  286. {
  287. if (pszMaterialName != NULL)
  288. {
  289. for (int i = 0; i < m_nEntries; i++)
  290. {
  291. if (!stricmp(m_pCache[i].pMaterial->GetName(), pszMaterialName))
  292. {
  293. return(m_pCache[i].pMaterial);
  294. }
  295. }
  296. }
  297. return(NULL);
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Purpose: Decrements the reference count of a material, deleting it and
  301. // removing it from the cache if its reference count becomes zero.
  302. // Input : pMaterial - Material to release.
  303. //-----------------------------------------------------------------------------
  304. void CMaterialCache::Release(CMaterial *pMaterial)
  305. {
  306. if (pMaterial != NULL)
  307. {
  308. for (int i = 0; i < m_nEntries; i++)
  309. {
  310. if (m_pCache[i].pMaterial == pMaterial)
  311. {
  312. m_pCache[i].nRefCount--;
  313. if (m_pCache[i].nRefCount == 0)
  314. {
  315. delete m_pCache[i].pMaterial;
  316. m_nEntries--;
  317. m_pCache[i] = m_pCache[m_nEntries];
  318. memset(&m_pCache[m_nEntries], 0, sizeof(m_pCache[0]));
  319. }
  320. break;
  321. }
  322. }
  323. }
  324. }
  325. //-----------------------------------------------------------------------------
  326. // Purpose: Constructor. Initializes data members.
  327. //-----------------------------------------------------------------------------
  328. CMaterial::CMaterial(void)
  329. {
  330. memset(m_szName, 0, sizeof(m_szName));
  331. memset(m_szFileName, 0, sizeof(m_szFileName));
  332. memset(m_szKeywords, 0, sizeof(m_szKeywords));
  333. m_nPreviewImageWidth = 0;
  334. m_nPreviewImageHeight = 0;
  335. m_nTextureID = 0;
  336. m_pData = NULL;
  337. m_bLoaded = false;
  338. m_pMaterial = NULL;
  339. m_TranslucentBaseTexture = false;
  340. }
  341. //-----------------------------------------------------------------------------
  342. // Purpose: Destructor. Frees texture image data and palette.
  343. //-----------------------------------------------------------------------------
  344. CMaterial::~CMaterial(void)
  345. {
  346. //
  347. // Free image data.
  348. //
  349. if (m_pData != NULL)
  350. {
  351. free(m_pData);
  352. m_pData = NULL;
  353. }
  354. /* FIXME: Texture manager shuts down after the material system
  355. if (m_pMaterial)
  356. {
  357. m_pMaterial->DecrementReferenceCount();
  358. m_pMaterial = NULL;
  359. }
  360. */
  361. }
  362. #define MATERIAL_PREFIX_LEN 10
  363. //-----------------------------------------------------------------------------
  364. // Finds all .VMT files in a particular directory
  365. //-----------------------------------------------------------------------------
  366. bool CMaterial::LoadMaterialsInDirectory( char const* pDirectoryName, int nDirectoryNameLen,
  367. IMaterialEnumerator *pEnum, int nContext, int nFlags )
  368. {
  369. //Assert( Q_strnicmp( pDirectoryName, "materials", 9 ) == 0 );
  370. char *pWildCard;
  371. pWildCard = ( char * )stackalloc( nDirectoryNameLen + 7 );
  372. Q_snprintf( pWildCard, nDirectoryNameLen + 7, "%s/*.vmt", pDirectoryName );
  373. if ( !g_pFileSystem )
  374. {
  375. return false;
  376. }
  377. FileFindHandle_t findHandle;
  378. const char *pFileName = g_pFullFileSystem->FindFirstEx( pWildCard, "GAME", &findHandle );
  379. while( pFileName )
  380. {
  381. if (IsIgnoredMaterial(pFileName))
  382. {
  383. pFileName = g_pFullFileSystem->FindNext( findHandle );
  384. continue;
  385. }
  386. if( !g_pFullFileSystem->FindIsDirectory( findHandle ) )
  387. {
  388. // Strip off the 'materials/' part of the material name.
  389. char *pFileNameWithPath;
  390. int nAllocSize = nDirectoryNameLen + Q_strlen(pFileName) + 2;
  391. pFileNameWithPath = (char *)stackalloc( nAllocSize );
  392. Q_snprintf( pFileNameWithPath, nAllocSize, "%s/%s", &pDirectoryName[MATERIAL_PREFIX_LEN], pFileName );
  393. Q_strnlwr( pFileNameWithPath, nAllocSize );
  394. // Strip off the extension...
  395. char *pExt = Q_strrchr( pFileNameWithPath, '.');
  396. if (pExt)
  397. *pExt = 0;
  398. if (!pEnum->EnumMaterial( pFileNameWithPath, nContext ))
  399. {
  400. return false;
  401. }
  402. }
  403. pFileName = g_pFullFileSystem->FindNext( findHandle );
  404. }
  405. g_pFullFileSystem->FindClose( findHandle );
  406. return true;
  407. }
  408. //-----------------------------------------------------------------------------
  409. // Discovers all .VMT files lying under a particular directory
  410. // It only finds their names so we can generate shell materials for them
  411. // that we can load up at a later time
  412. //-----------------------------------------------------------------------------
  413. bool CMaterial::InitDirectoryRecursive( char const* pDirectoryName,
  414. IMaterialEnumerator *pEnum, int nContext, int nFlags )
  415. {
  416. // Make sure this is an ok directory, otherwise don't bother
  417. if (ShouldSkipMaterial( pDirectoryName + MATERIAL_PREFIX_LEN, nFlags ))
  418. return true;
  419. // Compute directory name length
  420. int nDirectoryNameLen = Q_strlen( pDirectoryName );
  421. if (!LoadMaterialsInDirectory( pDirectoryName, nDirectoryNameLen, pEnum, nContext, nFlags ))
  422. return false;
  423. char *pWildCard = ( char * )stackalloc( nDirectoryNameLen + 5 );
  424. strcpy(pWildCard, pDirectoryName);
  425. strcat(pWildCard, "/*.*");
  426. int nPathStrLen = nDirectoryNameLen + 1;
  427. FileFindHandle_t findHandle;
  428. const char *pFileName = g_pFullFileSystem->FindFirstEx( pWildCard, "GAME", &findHandle );
  429. while( pFileName )
  430. {
  431. if (!IsIgnoredMaterial(pFileName))
  432. {
  433. if ((pFileName[0] != '.') || (pFileName[1] != '.' && pFileName[1] != 0))
  434. {
  435. if( g_pFullFileSystem->FindIsDirectory( findHandle ) )
  436. {
  437. int fileNameStrLen = Q_strlen( pFileName );
  438. char *pFileNameWithPath = ( char * )stackalloc( nPathStrLen + fileNameStrLen + 1 );
  439. memcpy( pFileNameWithPath, pWildCard, nPathStrLen );
  440. pFileNameWithPath[nPathStrLen] = '\0';
  441. Q_strncat( pFileNameWithPath, pFileName, nPathStrLen + fileNameStrLen + 1 );
  442. if (!InitDirectoryRecursive( pFileNameWithPath, pEnum, nContext, nFlags ))
  443. return false;
  444. }
  445. }
  446. }
  447. pFileName = g_pFullFileSystem->FindNext( findHandle );
  448. }
  449. return true;
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Discovers all .VMT files lying under a particular directory
  453. // It only finds their names so we can generate shell materials for them
  454. // that we can load up at a later time
  455. //-----------------------------------------------------------------------------
  456. void CMaterial::EnumerateMaterials( IMaterialEnumerator *pEnum, const char *szRoot, int nContext, int nFlags )
  457. {
  458. InitDirectoryRecursive( szRoot, pEnum, nContext, nFlags );
  459. }
  460. //-----------------------------------------------------------------------------
  461. // Purpose: Called from GetFirst/GetNextMaterialName to skip unwanted materials.
  462. // Input : pszName - Name of material to evaluate.
  463. // nFlags - One or more of the following:
  464. // INCLUDE_ALL_MATERIALS
  465. // INCLUDE_WORLD_MATERIALS
  466. // INCLUDE_MODEL_MATERIALS
  467. // Output : Returns true to skip, false to not skip this material.
  468. //-----------------------------------------------------------------------------
  469. bool CMaterial::ShouldSkipMaterial(const char *pszName, int nFlags)
  470. {
  471. static char szStrippedName[MAX_PATH];
  472. // if NULL skip it
  473. if( !pszName )
  474. return true;
  475. //
  476. // check against the list of user-defined exclusion directories
  477. //
  478. for( int i = 0; i < g_pGameConfig->m_MaterialExcludeCount; i++ )
  479. {
  480. // This will guarantee the match is at the start of the string
  481. const char *pMatchFound = Q_stristr( pszName, g_pGameConfig->m_MaterialExclusions[i].szDirectory );
  482. if( pMatchFound == pszName )
  483. return true;
  484. }
  485. // also check against any FGD-defined exclusions
  486. if (pGD != NULL)
  487. {
  488. for( int i = 0; i < pGD->m_FGDMaterialExclusions.Count(); i++ )
  489. {
  490. const char *pMatchFound = Q_stristr( pszName, pGD->m_FGDMaterialExclusions[i].szDirectory );
  491. if( pMatchFound == pszName )
  492. return true;
  493. }
  494. }
  495. return false;
  496. #if 0
  497. bool bSkip = false;
  498. if (pszName != NULL)
  499. {
  500. if (!(nFlags & INCLUDE_MODEL_MATERIALS))
  501. {
  502. if (_strnicmp(pszName, "models/", 7) == 0)
  503. {
  504. bSkip = true;
  505. }
  506. }
  507. if (!(nFlags & INCLUDE_WORLD_MATERIALS))
  508. {
  509. if (_strnicmp(pszName, "models/", 7) != 0)
  510. {
  511. bSkip = true;
  512. }
  513. }
  514. }
  515. else
  516. {
  517. bSkip = true;
  518. }
  519. return(bSkip);
  520. #endif
  521. }
  522. //-----------------------------------------------------------------------------
  523. // Purpose: Factory. Creates a material by name.
  524. // Input : pszMaterialName - Name of material, ie "brick/brickfloor01".
  525. // Output : Returns a pointer to the new material object, NULL if the given
  526. // material did not exist.
  527. //-----------------------------------------------------------------------------
  528. CMaterial *CMaterial::CreateMaterial(const char *pszMaterialName, bool bLoadImmediately, bool* pFound)
  529. {
  530. Assert (pszMaterialName);
  531. CMaterial *pMaterial = new CMaterial;
  532. Assert( pMaterial );
  533. // Store off the material name so we can load it later if we need to
  534. Q_snprintf( pMaterial->m_szFileName, MAX_PATH, pszMaterialName );
  535. Q_snprintf( pMaterial->m_szName, MAX_PATH, pszMaterialName );
  536. //
  537. // Find the material by name and load it.
  538. //
  539. if (bLoadImmediately)
  540. {
  541. bool bFound = pMaterial->LoadMaterial();
  542. // Returns if the material was found or not
  543. if (pFound)
  544. *pFound = bFound;
  545. }
  546. return pMaterial;
  547. }
  548. bool CMaterial::IsIgnoredMaterial( const char *pName )
  549. {
  550. //TODO: make this a customizable user option?
  551. if ( !Q_strnicmp(pName, ".svn", 4) || strstr (pName, ".svn") ||
  552. !Q_strnicmp(pName, "models", 6) || strstr (pName, "models") )
  553. return true;
  554. return false;
  555. }
  556. //-----------------------------------------------------------------------------
  557. // Will actually load the material bits
  558. // We don't want to load them all at once because it takes way too long
  559. //-----------------------------------------------------------------------------
  560. bool CMaterial::LoadMaterial()
  561. {
  562. bool bFound = true;
  563. if (!m_bLoaded)
  564. {
  565. if (IsIgnoredMaterial(m_szFileName))
  566. {
  567. return false;
  568. }
  569. m_bLoaded = true;
  570. IMaterial *pMat = materials->FindMaterial(m_szFileName, TEXTURE_GROUP_OTHER);
  571. if ( IsErrorMaterial( pMat ) )
  572. bFound = false;
  573. Assert( pMat );
  574. if (!pMat)
  575. {
  576. return false;
  577. }
  578. if (!LoadMaterialHeader(pMat))
  579. {
  580. // dvs: yeaaaaaaaaah, we're gonna disable this until the spew can be reduced
  581. //Msg( mwError,"Load material header failed: %s", m_szFileName );
  582. bFound = false;
  583. pMat = materials->FindMaterial("debug/debugempty", TEXTURE_GROUP_OTHER);
  584. if (pMat)
  585. {
  586. LoadMaterialHeader(pMat);
  587. }
  588. }
  589. }
  590. return bFound;
  591. }
  592. //-----------------------------------------------------------------------------
  593. // Reloads owing to a material change
  594. //-----------------------------------------------------------------------------
  595. void CMaterial::Reload( bool bFullReload )
  596. {
  597. // Don't bother if we're not loaded yet
  598. if (!m_bLoaded)
  599. return;
  600. FreeData();
  601. if ( m_pMaterial )
  602. {
  603. m_pMaterial->DecrementReferenceCount();
  604. }
  605. m_pMaterial = materials->FindMaterial(m_szFileName, TEXTURE_GROUP_OTHER);
  606. Assert( m_pMaterial );
  607. if ( bFullReload )
  608. m_pMaterial->Refresh();
  609. PreviewImageRetVal_t retVal;
  610. bool translucentBaseTexture;
  611. ImageFormat eImageFormat;
  612. int width, height;
  613. retVal = m_pMaterial->GetPreviewImageProperties(&width, &height, &eImageFormat, &translucentBaseTexture);
  614. if (retVal == MATERIAL_PREVIEW_IMAGE_BAD)
  615. return;
  616. m_nPreviewImageWidth = width;
  617. m_nPreviewImageHeight = height;
  618. m_TranslucentBaseTexture = translucentBaseTexture;
  619. // Find the keywords for this material from the vmt file.
  620. bool bFound;
  621. IMaterialVar *pVar = m_pMaterial->FindVar("%keywords", &bFound, false);
  622. if (bFound)
  623. {
  624. strcpy(m_szKeywords, pVar->GetStringValue());
  625. // Register the keywords
  626. g_Textures.RegisterTextureKeywords( this );
  627. }
  628. }
  629. //-----------------------------------------------------------------------------
  630. // Returns the material
  631. //-----------------------------------------------------------------------------
  632. IMaterial* CMaterial::GetMaterial( bool bForceLoad )
  633. {
  634. if ( bForceLoad )
  635. LoadMaterial();
  636. return m_pMaterial;
  637. }
  638. //-----------------------------------------------------------------------------
  639. // Purpose:
  640. //-----------------------------------------------------------------------------
  641. void CMaterial::DrawIcon( CDC *pDC, CMaterial* pIcon, RECT& dstRect )
  642. {
  643. if (!pIcon)
  644. return;
  645. g_pMaterialImageCache->EnCache(pIcon);
  646. RECT rect, dst;
  647. rect.left = 0; rect.right = pIcon->GetWidth();
  648. // FIXME: Workaround the fact that materials must be power of 2, I want 12 bite
  649. rect.top = 2; rect.bottom = pIcon->GetHeight() - 2;
  650. dst = dstRect;
  651. float dstHeight = dstRect.bottom - dstRect.top;
  652. float srcAspect = (float)(rect.right - rect.left) / (float)(rect.bottom - rect.top);
  653. dst.right = dst.left + (dstHeight * srcAspect);
  654. pIcon->DrawBitmap( pDC, rect, dst );
  655. dstRect.left += dst.right - dst.left;
  656. }
  657. //-----------------------------------------------------------------------------
  658. // Purpose:
  659. // Input : pDC -
  660. // dstRect -
  661. // detectErrors -
  662. //-----------------------------------------------------------------------------
  663. void CMaterial::DrawBrowserIcons( CDC *pDC, RECT& dstRect, bool detectErrors )
  664. {
  665. static CMaterial* pTranslucentIcon = 0;
  666. static CMaterial* pOpaqueIcon = 0;
  667. static CMaterial* pSelfIllumIcon = 0;
  668. static CMaterial* pBaseAlphaEnvMapMaskIcon = 0;
  669. static CMaterial* pErrorIcon = 0;
  670. if (!pTranslucentIcon)
  671. {
  672. pTranslucentIcon = CreateMaterial("editor/translucenticon", true);
  673. pOpaqueIcon = CreateMaterial("editor/opaqueicon", true);
  674. pSelfIllumIcon = CreateMaterial("editor/selfillumicon", true);
  675. pBaseAlphaEnvMapMaskIcon = CreateMaterial("editor/basealphaenvmapmaskicon", true);
  676. pErrorIcon = CreateMaterial("editor/erroricon", true);
  677. Assert( pTranslucentIcon && pOpaqueIcon && pSelfIllumIcon && pBaseAlphaEnvMapMaskIcon && pErrorIcon );
  678. }
  679. bool error = false;
  680. IMaterial* pMaterial = GetMaterial();
  681. if ( pMaterial->GetMaterialVarFlag( MATERIAL_VAR_TRANSLUCENT ) )
  682. {
  683. DrawIcon( pDC, pTranslucentIcon, dstRect );
  684. if (detectErrors)
  685. {
  686. error = error || !m_TranslucentBaseTexture;
  687. }
  688. }
  689. else
  690. {
  691. DrawIcon( pDC, pOpaqueIcon, dstRect );
  692. }
  693. if ( pMaterial->GetMaterialVarFlag( MATERIAL_VAR_SELFILLUM ))
  694. {
  695. DrawIcon( pDC, pSelfIllumIcon, dstRect );
  696. if (detectErrors)
  697. {
  698. error = error || !m_TranslucentBaseTexture;
  699. }
  700. }
  701. if ( pMaterial->GetMaterialVarFlag( MATERIAL_VAR_BASEALPHAENVMAPMASK ))
  702. {
  703. DrawIcon( pDC, pBaseAlphaEnvMapMaskIcon, dstRect );
  704. if (detectErrors)
  705. {
  706. error = error || !m_TranslucentBaseTexture;
  707. }
  708. }
  709. if (error)
  710. {
  711. DrawIcon( pDC, pErrorIcon, dstRect );
  712. }
  713. }
  714. //-----------------------------------------------------------------------------
  715. // Purpose:
  716. // Input : pDC -
  717. // srcRect -
  718. // dstRect -
  719. //-----------------------------------------------------------------------------
  720. void CMaterial::DrawBitmap( CDC *pDC, RECT& srcRect, RECT& dstRect )
  721. {
  722. static struct
  723. {
  724. BITMAPINFOHEADER bmih;
  725. unsigned short colorindex[256];
  726. } bmi;
  727. int srcWidth = srcRect.right - srcRect.left;
  728. int srcHeight = srcRect.bottom - srcRect.top;
  729. BITMAPINFOHEADER &bmih = bmi.bmih;
  730. memset(&bmih, 0, sizeof(bmih));
  731. bmih.biSize = sizeof(bmih);
  732. bmih.biWidth = srcWidth;
  733. bmih.biHeight = -srcHeight;
  734. bmih.biCompression = BI_RGB;
  735. bmih.biBitCount = 24;
  736. bmih.biPlanes = 1;
  737. static BOOL bInit = false;
  738. if (!bInit)
  739. {
  740. bInit = true;
  741. for (int i = 0; i < 256; i++)
  742. {
  743. bmi.colorindex[i] = i;
  744. }
  745. }
  746. int dest_width = dstRect.right - dstRect.left;
  747. int dest_height = dstRect.bottom - dstRect.top;
  748. // ** bits **
  749. SetStretchBltMode(pDC->m_hDC, COLORONCOLOR);
  750. if (StretchDIBits(pDC->m_hDC, dstRect.left, dstRect.top, dest_width, dest_height,
  751. srcRect.left, -srcRect.top, srcWidth, srcHeight, m_pData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, SRCCOPY) == GDI_ERROR)
  752. {
  753. Msg(mwError, "CMaterial::Draw(): StretchDIBits failed.");
  754. }
  755. }
  756. //-----------------------------------------------------------------------------
  757. // Purpose:
  758. // Input : *pDC -
  759. // rect -
  760. // iFontHeight -
  761. // dwFlags -
  762. //-----------------------------------------------------------------------------
  763. void CMaterial::Draw(CDC *pDC, RECT& rect, int iFontHeight, int iIconHeight, DrawTexData_t &DrawTexData)//, BrowserData_t *pBrowserData)
  764. {
  765. g_pMaterialImageCache->EnCache(this);
  766. if (!this->HasData())
  767. {
  768. return;
  769. }
  770. if (m_nPreviewImageWidth <= 0)
  771. {
  772. NoData:
  773. // draw "no data"
  774. CFont *pOldFont = (CFont*) pDC->SelectStockObject(ANSI_VAR_FONT);
  775. COLORREF cr = pDC->SetTextColor(RGB(0xff, 0xff, 0xff));
  776. COLORREF cr2 = pDC->SetBkColor(RGB(0, 0, 0));
  777. // draw black rect first
  778. pDC->FillRect(&rect, CBrush::FromHandle(HBRUSH(GetStockObject(BLACK_BRUSH))));
  779. // then text
  780. pDC->TextOut(rect.left+2, rect.top+2, "No Image", 8);
  781. pDC->SelectObject(pOldFont);
  782. pDC->SetTextColor(cr);
  783. pDC->SetBkColor(cr2);
  784. return;
  785. }
  786. // no data -
  787. if (!m_pData)
  788. {
  789. // try to load -
  790. if (!Load())
  791. {
  792. // can't load -
  793. goto NoData;
  794. }
  795. }
  796. // Draw the material image
  797. RECT srcRect, dstRect;
  798. srcRect.left = 0;
  799. srcRect.top = 0;
  800. srcRect.right = m_nPreviewImageWidth;
  801. srcRect.bottom = m_nPreviewImageHeight;
  802. dstRect = rect;
  803. if (DrawTexData.nFlags & drawCaption)
  804. {
  805. dstRect.bottom -= iFontHeight + 4;
  806. }
  807. if (DrawTexData.nFlags & drawIcons)
  808. {
  809. dstRect.bottom -= iIconHeight;
  810. }
  811. if (!(DrawTexData.nFlags & drawResizeAlways))
  812. {
  813. if (m_nPreviewImageWidth < dstRect.right - dstRect.left )
  814. {
  815. dstRect.right = dstRect.left + m_nPreviewImageWidth;
  816. }
  817. if (m_nPreviewImageHeight < dstRect.bottom - dstRect.top )
  818. {
  819. dstRect.bottom = dstRect.top + m_nPreviewImageHeight;
  820. }
  821. }
  822. DrawBitmap( pDC, srcRect, dstRect );
  823. // Draw the icons
  824. if (DrawTexData.nFlags & drawIcons)
  825. {
  826. dstRect = rect;
  827. if (DrawTexData.nFlags & drawCaption)
  828. {
  829. dstRect.bottom -= iFontHeight + 5;
  830. }
  831. dstRect.top = dstRect.bottom - iIconHeight;
  832. DrawBrowserIcons(pDC, dstRect, (DrawTexData.nFlags & drawErrors) != 0 );
  833. }
  834. // ** caption **
  835. if (DrawTexData.nFlags & drawCaption)
  836. {
  837. // draw background for name
  838. CBrush brCaption(RGB(0, 0, 255));
  839. CRect rcCaption(rect);
  840. rcCaption.top = rcCaption.bottom - (iFontHeight + 5);
  841. pDC->FillRect(rcCaption, &brCaption);
  842. // draw name
  843. char szShortName[MAX_PATH];
  844. int iLen = GetShortName(szShortName);
  845. pDC->TextOut(rect.left, rect.bottom - (iFontHeight + 4), szShortName, iLen);
  846. // draw usage count
  847. if (DrawTexData.nFlags & drawUsageCount)
  848. {
  849. CString str;
  850. str.Format("%d", DrawTexData.nUsageCount);
  851. CSize size = pDC->GetTextExtent(str);
  852. pDC->TextOut(rect.right - size.cx, rect.bottom - (iFontHeight + 4), str);
  853. }
  854. }
  855. }
  856. //-----------------------------------------------------------------------------
  857. // Purpose:
  858. //-----------------------------------------------------------------------------
  859. void CMaterial::FreeData( void )
  860. {
  861. free( m_pData );
  862. m_pData = NULL;
  863. }
  864. //-----------------------------------------------------------------------------
  865. // Purpose: Returns a string of comma delimited keywords associated with this
  866. // material.
  867. // Input : pszKeywords - Buffer to receive keywords, NULL to query string length.
  868. // Output : Returns the number of characters in the keyword string.
  869. //-----------------------------------------------------------------------------
  870. int CMaterial::GetKeywords(char *pszKeywords) const
  871. {
  872. // To access keywords, we have to have the header loaded
  873. const_cast<CMaterial*>(this)->Load();
  874. if (pszKeywords != NULL)
  875. {
  876. strcpy(pszKeywords, m_szKeywords);
  877. }
  878. return(strlen(m_szKeywords));
  879. }
  880. //-----------------------------------------------------------------------------
  881. // Purpose:
  882. // Input : *pszName -
  883. // Output : int
  884. //-----------------------------------------------------------------------------
  885. int CMaterial::GetShortName(char *pszName) const
  886. {
  887. if (pszName != NULL)
  888. {
  889. strcpy(pszName, m_szName);
  890. }
  891. return(strlen(m_szName));
  892. }
  893. //-----------------------------------------------------------------------------
  894. // Purpose:
  895. // Input : material -
  896. // Output : Returns true on success, false on failure.
  897. //-----------------------------------------------------------------------------
  898. bool CMaterial::LoadMaterialHeader( IMaterial *pMat )
  899. {
  900. PreviewImageRetVal_t retVal;
  901. bool translucentBaseTexture;
  902. ImageFormat eImageFormat;
  903. int width, height;
  904. retVal = CPreviewImagePropertiesCache::GetPreviewImageProperties( pMat, &width, &height, &eImageFormat, &translucentBaseTexture);
  905. if (retVal == MATERIAL_PREVIEW_IMAGE_BAD)
  906. return false;
  907. m_pMaterial = pMat;
  908. m_pMaterial->IncrementReferenceCount();
  909. m_nPreviewImageWidth = width;
  910. m_nPreviewImageHeight = height;
  911. m_TranslucentBaseTexture = translucentBaseTexture;
  912. // Find the keywords for this material from the vmt file.
  913. bool bFound;
  914. IMaterialVar *pVar = pMat->FindVar("%keywords", &bFound, false);
  915. if (bFound)
  916. {
  917. strcpy(m_szKeywords, pVar->GetStringValue());
  918. // Register the keywords
  919. g_Textures.RegisterTextureKeywords( this );
  920. }
  921. return(true);
  922. }
  923. //-----------------------------------------------------------------------------
  924. // Purpose: Returns the full path of the file from which this material was loaded.
  925. //-----------------------------------------------------------------------------
  926. const char *CMaterial::GetFileName( void ) const
  927. {
  928. return(m_szFileName);
  929. }
  930. //-----------------------------------------------------------------------------
  931. // Purpose:
  932. //-----------------------------------------------------------------------------
  933. bool CMaterial::IsWater( void ) const
  934. {
  935. bool bFound;
  936. IMaterialVar *pVar = m_pMaterial->FindVar( "$surfaceprop", &bFound, false );
  937. if ( bFound )
  938. {
  939. if ( !strcmp( "water", pVar->GetStringValue() ) )
  940. return true;
  941. }
  942. return false;
  943. }
  944. //-----------------------------------------------------------------------------
  945. // Purpose: If the buffer pointer passed in is not NULL, copies the image data
  946. // in RGB format to the buffer
  947. // Input : pImageRGB - Pointer to buffer that receives the image data. If the
  948. // pointer is NULL, no data is copied, only the data size is returned.
  949. // Output : Returns a the size of the RGB image in bytes.
  950. //-----------------------------------------------------------------------------
  951. int CMaterial::GetImageDataRGB( void *pImageRGB )
  952. {
  953. Assert( m_nPreviewImageWidth > 0 );
  954. if ( pImageRGB != NULL )
  955. {
  956. Load();
  957. g_pMaterialImageCache->EnCache( this );
  958. if (!this->HasData())
  959. {
  960. return(NULL);
  961. }
  962. unsigned char *src, *dst;
  963. src = ( unsigned char * )m_pData;
  964. dst = (unsigned char *)pImageRGB;
  965. for( ; src < ( unsigned char * )m_pData + m_nPreviewImageWidth * m_nPreviewImageHeight * 3; src += 3, dst += 3 )
  966. {
  967. dst[0] = src[2];
  968. dst[1] = src[1];
  969. dst[2] = src[0];
  970. }
  971. return( m_nPreviewImageWidth * m_nPreviewImageHeight * 3 );
  972. }
  973. return( m_nPreviewImageWidth * m_nPreviewImageHeight * 3 );
  974. }
  975. //-----------------------------------------------------------------------------
  976. // Purpose: If the buffer pointer passed in is not NULL, copies the image data
  977. // in RGBA format to the buffer
  978. // Input : pImageRGBA - Pointer to buffer that receives the image data. If the
  979. // pointer is NULL, no data is copied, only the data size is returned.
  980. // Output : Returns a the size of the RGBA image in bytes.
  981. //-----------------------------------------------------------------------------
  982. int CMaterial::GetImageDataRGBA(void *pImageRGBA)
  983. {
  984. Assert( m_nPreviewImageWidth > 0 );
  985. if (pImageRGBA != NULL)
  986. {
  987. Load();
  988. g_pMaterialImageCache->EnCache(this);
  989. if (!this->HasData())
  990. {
  991. return(NULL);
  992. }
  993. unsigned char *src, *dst;
  994. src = (unsigned char *)m_pData;
  995. dst = (unsigned char *)pImageRGBA;
  996. while (src < (unsigned char *)m_pData + m_nPreviewImageWidth * m_nPreviewImageHeight * 4);
  997. {
  998. dst[0] = src[2];
  999. dst[1] = src[1];
  1000. dst[2] = src[0];
  1001. dst[3] = 0;
  1002. src += 4;
  1003. dst += 4;
  1004. }
  1005. }
  1006. return(m_nPreviewImageWidth * m_nPreviewImageHeight * 4);
  1007. }
  1008. //-----------------------------------------------------------------------------
  1009. // Purpose:
  1010. // Input : size -
  1011. //-----------------------------------------------------------------------------
  1012. void CMaterial::GetSize(SIZE &size) const
  1013. {
  1014. const_cast<CMaterial*>(this)->Load();
  1015. Assert( m_nPreviewImageWidth >= 0 );
  1016. size.cx = m_nPreviewImageWidth;
  1017. size.cy = m_nPreviewImageHeight;
  1018. }
  1019. //-----------------------------------------------------------------------------
  1020. // Purpose: Loads this material's image from disk if it is not already loaded.
  1021. // Output : Returns true on success, false on failure.
  1022. //-----------------------------------------------------------------------------
  1023. bool CMaterial::Load( void )
  1024. {
  1025. LoadMaterial();
  1026. return true;
  1027. }
  1028. //-----------------------------------------------------------------------------
  1029. // cache in the image size only when we need to
  1030. //-----------------------------------------------------------------------------
  1031. int CMaterial::GetMappingWidth(void) const
  1032. {
  1033. const_cast<CMaterial*>(this)->Load();
  1034. return m_pMaterial ? m_pMaterial->GetMappingWidth() : 0;
  1035. }
  1036. int CMaterial::GetMappingHeight(void) const
  1037. {
  1038. const_cast<CMaterial*>(this)->Load();
  1039. return m_pMaterial ? m_pMaterial->GetMappingHeight() : 0;
  1040. }
  1041. //-----------------------------------------------------------------------------
  1042. // cache in the image size only when we need to
  1043. //-----------------------------------------------------------------------------
  1044. int CMaterial::GetPreviewImageWidth(void) const
  1045. {
  1046. const_cast<CMaterial*>(this)->Load();
  1047. return(m_nPreviewImageWidth);
  1048. }
  1049. int CMaterial::GetPreviewImageHeight(void) const
  1050. {
  1051. const_cast<CMaterial*>(this)->Load();
  1052. return(m_nPreviewImageHeight);
  1053. }
  1054. // change this to GetPreviewImageWidth
  1055. int CMaterial::GetWidth(void) const
  1056. {
  1057. return GetPreviewImageWidth();
  1058. }
  1059. int CMaterial::GetHeight(void) const
  1060. {
  1061. return GetPreviewImageHeight();
  1062. }
  1063. float CMaterial::GetDecalScale(void) const
  1064. {
  1065. const_cast<CMaterial*>(this)->Load();
  1066. IMaterialVar *decalScaleVar;
  1067. bool found;
  1068. decalScaleVar = m_pMaterial->FindVar( "$decalScale", &found, false );
  1069. if( !found )
  1070. {
  1071. return 1.0f;
  1072. }
  1073. else
  1074. {
  1075. return decalScaleVar->GetFloatValue();
  1076. }
  1077. }
  1078. //-----------------------------------------------------------------------------
  1079. // Purpose:
  1080. // Output : Returns true on success, false on failure.
  1081. //-----------------------------------------------------------------------------
  1082. bool CMaterial::LoadMaterialImage( void )
  1083. {
  1084. Load();
  1085. if ((!m_nPreviewImageWidth) || (!m_nPreviewImageHeight))
  1086. return(false);
  1087. m_pData = malloc(m_nPreviewImageWidth * m_nPreviewImageHeight * 3);
  1088. Assert(m_pData);
  1089. ImageFormat imageFormat;
  1090. // if( _strnicmp( m_pMaterial->GetName(), "decals", 6 ) == 0 )
  1091. // {
  1092. // imageFormat = IMAGE_FORMAT_BGR888_BLUESCREEN;
  1093. // }
  1094. // else
  1095. {
  1096. imageFormat = IMAGE_FORMAT_BGR888;
  1097. }
  1098. PreviewImageRetVal_t retVal;
  1099. retVal = m_pMaterial->GetPreviewImage( (unsigned char *)m_pData, m_nPreviewImageWidth, m_nPreviewImageHeight, imageFormat );
  1100. return (retVal != MATERIAL_PREVIEW_IMAGE_BAD);
  1101. }
  1102. static void InitMaterialSystemConfig(MaterialSystem_Config_t *pConfig)
  1103. {
  1104. pConfig->bEditMode = true;
  1105. pConfig->m_nAASamples = 0;
  1106. pConfig->SetFlag( MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP, true);
  1107. // When I do this the model browser layout is horked...
  1108. // pConfig->SetFlag( MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS, true );
  1109. }
  1110. static char const *s_rt_names[]={"_rt_albedo","_rt_normal","_rt_position",
  1111. "_rt_accbuf" };
  1112. ImageFormat s_rt_formats[]={ IMAGE_FORMAT_RGBA32323232F, IMAGE_FORMAT_RGBA32323232F,
  1113. IMAGE_FORMAT_RGBA32323232F,
  1114. IMAGE_FORMAT_RGBA16161616F };
  1115. static CTextureReference sg_ExtraFP16Targets[NELEMS(s_rt_names)];
  1116. void AllocateLightingPreviewtextures(void)
  1117. {
  1118. static bool bHaveAllocated=false;
  1119. if (! bHaveAllocated )
  1120. {
  1121. bHaveAllocated = true;
  1122. MaterialSystemInterface()->BeginRenderTargetAllocation();
  1123. for(int idx=0;idx<NELEMS(sg_ExtraFP16Targets);idx++)
  1124. sg_ExtraFP16Targets[idx].Init(
  1125. materials->CreateNamedRenderTargetTextureEx2(
  1126. s_rt_names[idx],
  1127. 512, 512, RT_SIZE_DEFAULT, s_rt_formats[idx],
  1128. MATERIAL_RT_DEPTH_SHARED,
  1129. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  1130. CREATERENDERTARGETFLAGS_HDR )
  1131. );
  1132. // End block in which all render targets should be allocated (kicking off an Alt-Tab type
  1133. // behavior)
  1134. MaterialSystemInterface()->EndRenderTargetAllocation();
  1135. }
  1136. }
  1137. //-----------------------------------------------------------------------------
  1138. // Purpose:
  1139. // Output : Returns true on success, false on failure.
  1140. //-----------------------------------------------------------------------------
  1141. bool CMaterial::Initialize( HWND hwnd )
  1142. {
  1143. // NOTE: This gets set to true later upon creating a 3d view.
  1144. g_materialSystemConfig = materials->GetCurrentConfigForVideoCard();
  1145. if ( !APP()->IsFoundryMode() )
  1146. {
  1147. InitMaterialSystemConfig( &g_materialSystemConfig );
  1148. }
  1149. // Create a cache for material images (for browsing and uploading to the driver).
  1150. if (g_pMaterialImageCache == NULL)
  1151. {
  1152. g_pMaterialImageCache = new CMaterialImageCache(500);
  1153. if (g_pMaterialImageCache == NULL)
  1154. return false ;
  1155. }
  1156. if ( !APP()->IsFoundryMode() )
  1157. {
  1158. materials->OverrideConfig( g_materialSystemConfig, false );
  1159. // Set the mode
  1160. // When setting the mode, we need to grab the parent window
  1161. // since that's going to enclose all our little render windows
  1162. g_materialSystemConfig.m_VideoMode.m_Width = g_materialSystemConfig.m_VideoMode.m_Height = 0;
  1163. g_materialSystemConfig.m_VideoMode.m_Format = IMAGE_FORMAT_BGRA8888;
  1164. g_materialSystemConfig.m_VideoMode.m_RefreshRate = 0;
  1165. g_materialSystemConfig.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
  1166. g_materialSystemConfig.SetFlag( MATSYS_VIDCFG_FLAGS_RESIZING, true );
  1167. if (!MaterialSystemInterface()->SetMode( hwnd, g_materialSystemConfig ) )
  1168. return false;
  1169. }
  1170. return true;
  1171. }
  1172. //-----------------------------------------------------------------------------
  1173. // Purpose: Restores the material system to an uninitialized state.
  1174. //-----------------------------------------------------------------------------
  1175. void CMaterial::ShutDown(void)
  1176. {
  1177. for ( int i = 0; i < NELEMS(sg_ExtraFP16Targets); ++i )
  1178. {
  1179. sg_ExtraFP16Targets[i].Shutdown();
  1180. }
  1181. if (materials != NULL)
  1182. {
  1183. materials->UncacheAllMaterials();
  1184. }
  1185. delete g_pMaterialImageCache;
  1186. g_pMaterialImageCache = NULL;
  1187. }