BVB Source Codes

CRYENGINE Show MatMan.cpp Source code

Return Download CRYENGINE: download MatMan.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   MatMan.cpp
  5. //  Version:     v1.00
  6. //  Created:     28/5/2001 by Vladimir Kajalin
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: Material Manager Implementation
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15. #include "MatMan.h"
  16. #include "3dEngine.h"
  17. #include "ObjMan.h"
  18. #include <CryRenderer/IRenderer.h>
  19. #include "SurfaceTypeManager.h"
  20. #include <Cry3DEngine/CGF/CGFContent.h>
  21. #include <CrySystem/File/IResourceManager.h>
  22.  
  23. #define MATERIAL_EXT                    ".mtl"
  24. #define MATERIAL_NODRAW                 "nodraw"
  25.  
  26. #define MATERIAL_DECALS_FOLDER          "Materials/Decals"
  27. #define MATERIAL_DECALS_SEARCH_WILDCARD "*.mtl"
  28. #define MTL_LEVEL_CACHE_PAK             "mtl.pak"
  29.  
  30. //////////////////////////////////////////////////////////////////////////
  31. struct MaterialHelpers CMatMan::s_materialHelpers;
  32.  
  33. int CMatMan::e_sketch_mode = 0;
  34. int CMatMan::e_pre_sketch_spec = 0;
  35. int CMatMan::e_texeldensity = 0;
  36.  
  37. #if !defined(_RELEASE)
  38. static const char* szReplaceMe = "EngineAssets/TextureMsg/ReplaceMe.tif";
  39. static const char* szGeomNotBreakable = "EngineAssets/TextureMsg/GeomNotBreakable.tif";
  40. #else
  41. static const char* szReplaceMe = "EngineAssets/TextureMsg/ReplaceMeRelease.tif";
  42. static const char* szGeomNotBreakable = "EngineAssets/TextureMsg/ReplaceMeRelease.tif";
  43. #endif
  44.  
  45. static void OnSketchModeChange(ICVar* pVar)
  46. {
  47.         int mode = pVar->GetIVal();
  48.         ((CMatMan*)gEnv->p3DEngine->GetMaterialManager())->SetSketchMode(mode);
  49. }
  50.  
  51. static void OnDebugTexelDensityChange(ICVar* pVar)
  52. {
  53.         int mode = pVar->GetIVal();
  54.         ((CMatMan*)gEnv->p3DEngine->GetMaterialManager())->SetTexelDensityDebug(mode);
  55. }
  56.  
  57. //////////////////////////////////////////////////////////////////////////
  58. CMatMan::CMatMan()
  59. {
  60.         m_bInitialized = false;
  61.         m_bLoadSurfaceTypesInInit = true;
  62.         m_pListener = NULL;
  63.         m_pDefaultMtl = NULL;
  64.         m_pDefaultTerrainLayersMtl = NULL;
  65.         m_pDefaultLayersMtl = NULL;
  66.         m_pDefaultHelperMtl = NULL;
  67.         m_pNoDrawMtl = NULL;
  68.         m_nDelayedDeleteID = 0;
  69.  
  70.         m_pSurfaceTypeManager = new CSurfaceTypeManager();
  71.  
  72.         REGISTER_CVAR_CB(e_sketch_mode, 0, VF_CHEAT, "Enables Sketch mode drawing", OnSketchModeChange);
  73.         REGISTER_CVAR_CB(e_texeldensity, 0, VF_CHEAT,
  74.                          "Enables texel density debug\n"
  75.                          " 1: Objects texel density\n"
  76.                          " 2: Objects texel density with colored mipmaps\n"
  77.                          " 3: Terrain texel density\n"
  78.                          " 4: Terrain texel density with colored mipmaps\n",
  79.                          OnDebugTexelDensityChange);
  80.  
  81.         m_pXmlParser = GetISystem()->GetXmlUtils()->CreateXmlParser();
  82.  
  83. #if defined(ENABLE_CONSOLE_MTL_VIZ)
  84.         CMatInfo::RegisterConsoleMatCVar();
  85. #endif
  86.  
  87. }
  88.  
  89. //////////////////////////////////////////////////////////////////////////
  90. CMatMan::~CMatMan()
  91. {
  92.         delete m_pSurfaceTypeManager;
  93.         int nNotUsed = 0, nNotUsedParents = 0;
  94.         m_pDefaultMtl = NULL;
  95.         m_pDefaultTerrainLayersMtl = NULL;
  96.         m_pDefaultLayersMtl = NULL;
  97.         m_pDefaultHelperMtl = NULL;
  98.  
  99.         /*
  100.            for (MtlSet::iterator it = m_mtlSet.begin(); it != m_mtlSet.end(); ++it)
  101.            {
  102.            IMaterial *pMtl = *it;
  103.            SShaderItem Sh = pMtl->GetShaderItem();
  104.            if(Sh.m_pShader)
  105.            {
  106.             Sh.m_pShader->Release();
  107.             Sh.m_pShader = 0;
  108.            }
  109.            if(Sh.m_pShaderResources)
  110.            {
  111.             Sh.m_pShaderResources->Release();
  112.             Sh.m_pShaderResources = 0;
  113.            }
  114.            pMtl->SetShaderItem( Sh );
  115.  
  116.            if(!(pMtl->GetFlags()&MIF_CHILD))
  117.            if(!(pMtl->GetFlags()&MIF_WASUSED))
  118.            {
  119.             PrintMessage("Warning: CMatMan::~CMatMan: Material was loaded but never used: %s", pMtl->GetName());
  120.             nNotUsed += (pMtl->GetSubMtlCount()+1);
  121.             nNotUsedParents++;
  122.            }
  123.            if (pMtl->GetNumRefs() > 1)
  124.            {
  125.             //
  126.             PrintMessage("Warning: CMatMan::~CMatMan: Material %s is being referenced", pMtl->GetName());
  127.            }
  128.            }
  129.          */
  130.  
  131.         if (nNotUsed)
  132.                 PrintMessage("Warning: CMatMan::~CMatMan: %d(%d) of %" PRISIZE_T " materials was not used in level",
  133.                              nNotUsedParents, nNotUsed, m_mtlNameMap.size());
  134. }
  135.  
  136. //////////////////////////////////////////////////////////////////////////
  137. const char* CMatMan::UnifyName(const char* sMtlName) const
  138. {
  139.         static char name[260];
  140.         int n = strlen(sMtlName);
  141.  
  142.         //TODO: change this code to not use a statically allocated buffer and return it ...
  143.         //TODO: provide a general name unification function, which can be used in other places as well and remove this thing
  144.         if (n >= 260)
  145.                 Error("Static buffer size exceeded by material name!");
  146.  
  147.         for (int i = 0; i < n && i < sizeof(name); i++)
  148.         {
  149.                 name[i] = CryStringUtils::toLowerAscii(sMtlName[i]);
  150.                 if (sMtlName[i] == '.')
  151.                 {
  152.                         n = i;
  153.                         break;
  154.                 }
  155.                 else if (sMtlName[i] == '\\')
  156.                 {
  157.                         name[i] = '/';
  158.                 }
  159.         }
  160.         PREFAST_ASSUME(n >= 0 && n < 260);
  161.         name[n] = 0;
  162.         return name;
  163. }
  164.  
  165. //////////////////////////////////////////////////////////////////////////
  166. IMaterial* CMatMan::CreateMaterial(const char* sMtlName, int nMtlFlags)
  167. {
  168.         CMatInfo* pMat = new CMatInfo;
  169.  
  170.         //m_mtlSet.insert( pMat );
  171.         pMat->SetName(sMtlName);
  172.         pMat->SetFlags(nMtlFlags | pMat->GetFlags());
  173.         if (!(nMtlFlags & MTL_FLAG_PURE_CHILD))
  174.         {
  175.                 m_mtlNameMap[UnifyName(sMtlName)] = pMat;
  176.         }
  177.  
  178.         if (nMtlFlags & MTL_FLAG_NON_REMOVABLE)
  179.         {
  180.                 // Add reference to this material to prevent its deletion.
  181.                 m_nonRemovables.push_back(pMat);
  182.         }
  183.  
  184.         return pMat;
  185. }
  186.  
  187. //////////////////////////////////////////////////////////////////////////
  188. void CMatMan::NotifyCreateMaterial(IMaterial* pMtl)
  189. {
  190.         if (m_pListener)
  191.                 m_pListener->OnCreateMaterial(pMtl);
  192. }
  193.  
  194. //////////////////////////////////////////////////////////////////////////
  195. void CMatMan::DelayedMaterialDeletion()
  196. {
  197.         uint32 nID = (m_nDelayedDeleteID + 1) % MATERIAL_DELETION_DELAY;
  198.  
  199.         AUTO_LOCK(m_DelayedDeletionMtlsLock);
  200.         while (!m_DelayedDeletionMtls[nID].empty())
  201.         {
  202.                 _smart_ptr<CMatInfo> ptr = m_DelayedDeletionMtls[nID].back();
  203.                 m_DelayedDeletionMtls[nID].pop_back();
  204.         }
  205.  
  206.         m_nDelayedDeleteID = nID;
  207. }
  208.  
  209. //////////////////////////////////////////////////////////////////////////
  210. void CMatMan::ForceDelayedMaterialDeletion()
  211. {
  212.         // make sure nothing is in flight on RT if we force delete materials
  213.         if (GetRenderer())
  214.         {
  215.                 GetRenderer()->StopLoadtimeFlashPlayback();
  216.                 GetRenderer()->FlushRTCommands(true, true, true);
  217.         }
  218.  
  219.         AUTO_LOCK(m_DelayedDeletionMtlsLock);
  220.         for (uint32 i = 0; i < MATERIAL_DELETION_DELAY; i++)
  221.         {
  222.                 // clear list m_nDelayedDeleteID last because sub materials can still be added there when clearing the other lists
  223.                 const int nListIndex = (m_nDelayedDeleteID + 1 + i) % MATERIAL_DELETION_DELAY;
  224.                 while (!m_DelayedDeletionMtls[nListIndex].empty())
  225.                 {
  226.                         _smart_ptr<CMatInfo> ptr = m_DelayedDeletionMtls[nListIndex].back();
  227.                         ptr->ShutDown();
  228.                         m_DelayedDeletionMtls[nListIndex].pop_back();
  229.                 }
  230.         }
  231. }
  232.  
  233. //////////////////////////////////////////////////////////////////////////
  234. void CMatMan::DelayedDelete(CMatInfo* pMat)
  235. {
  236.         AUTO_LOCK(m_DelayedDeletionMtlsLock);
  237.         m_DelayedDeletionMtls[m_nDelayedDeleteID].push_back(pMat);
  238. }
  239.  
  240. //////////////////////////////////////////////////////////////////////////
  241. void CMatMan::Unregister(CMatInfo* pMat)
  242. {
  243.         assert(pMat);
  244.  
  245.         if (!(pMat->m_Flags & MTL_FLAG_PURE_CHILD))
  246.                 m_mtlNameMap.erase(CONST_TEMP_STRING(UnifyName(pMat->GetName())));
  247.  
  248.         if (m_pListener)
  249.                 m_pListener->OnDeleteMaterial(pMat);
  250. }
  251.  
  252. //////////////////////////////////////////////////////////////////////////
  253. void CMatMan::RenameMaterial(IMaterial* pMtl, const char* sNewName)
  254. {
  255.         assert(pMtl);
  256.         const char* sName = pMtl->GetName();
  257.         if (*sName != '\0')
  258.         {
  259.                 m_mtlNameMap.erase(CONST_TEMP_STRING(UnifyName(pMtl->GetName())));
  260.         }
  261.         pMtl->SetName(sNewName);
  262.         m_mtlNameMap[UnifyName(sNewName)] = pMtl;
  263. }
  264.  
  265. //////////////////////////////////////////////////////////////////////////
  266. IMaterial* CMatMan::FindMaterial(const char* sMtlName) const
  267. {
  268.         const char* name = UnifyName(sMtlName);
  269.  
  270.         MtlNameMap::const_iterator it = m_mtlNameMap.find(CONST_TEMP_STRING(name));
  271.  
  272.         if (it == m_mtlNameMap.end())
  273.                 return 0;
  274.  
  275.         return it->second;
  276. }
  277.  
  278. //////////////////////////////////////////////////////////////////////////
  279. IMaterial* CMatMan::LoadMaterial(const char* sMtlName, bool bMakeIfNotFound, bool bNonremovable, unsigned long nLoadingFlags)
  280. {
  281.         if (!m_bInitialized)
  282.                 InitDefaults();
  283.  
  284.         if (m_pDefaultMtl && GetCVars()->e_StatObjPreload == 2)
  285.                 return m_pDefaultMtl;
  286.  
  287.         const char* name = UnifyName(sMtlName);
  288.  
  289.         MtlNameMap::const_iterator it = m_mtlNameMap.find(CONST_TEMP_STRING(name));
  290.  
  291.         IMaterial* pMtl = 0;
  292.  
  293.         if (it != m_mtlNameMap.end())
  294.         {
  295.                 pMtl = it->second;
  296.                 return pMtl;
  297.         }
  298.  
  299.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Materials");
  300.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_MTL, EMemStatContextFlags::MSF_Instance, "%s", name);
  301.         LOADING_TIME_PROFILE_SECTION_ARGS(sMtlName); // Only profile actually loading of the material.
  302.  
  303.         CRY_DEFINE_ASSET_SCOPE("Material", sMtlName);
  304.  
  305.         if (!pMtl)
  306.         {
  307.                 if (!(nLoadingFlags & ELoadingFlagsPreviewMode))
  308.                 {
  309.                         if (m_pListener)
  310.                         {
  311.                                 pMtl = m_pListener->OnLoadMaterial(sMtlName, bMakeIfNotFound, nLoadingFlags);
  312.                                 if (pMtl)
  313.                                 {
  314.                                         if (bNonremovable)
  315.                                                 m_nonRemovables.push_back(static_cast<CMatInfo*>(pMtl));
  316.  
  317.                                         if (pMtl && e_sketch_mode != 0)
  318.                                         {
  319.                                                 ((CMatInfo*)pMtl)->SetSketchMode(e_sketch_mode);
  320.                                         }
  321.                                         if (pMtl->GetFlags() & MTL_FLAG_TRACEABLE_TEXTURE)
  322.                                                 pMtl->SetKeepLowResSysCopyForDiffTex();
  323.                                         return pMtl;
  324.                                 }
  325.                         }
  326.                 }
  327.  
  328.                 // Try to load material from file.
  329.                 stack_string filename = name;
  330.                 stack_string::size_type extPos = filename.find('.');
  331.  
  332.                 // If we've got an alternate material suffix, try appending that on the end of the
  333.                 // requested material, and if a material exists with that name use it instead.
  334.                 //
  335.                 // Note that we still register the material under the original name, so subsequent
  336.                 // lookups will get the alternate.  That does mean that if all affected materials
  337.                 // aren't released after switching or turning off the alt name the wrong materials
  338.                 // will be returned, but since we use the same suffix for an entire level it
  339.                 // doesn't seem to be an issue..
  340.                 if (!m_altSuffix.empty())
  341.                 {
  342.                         if (extPos == stack_string::npos)
  343.                         {
  344.                                 filename += m_altSuffix;
  345.                                 filename += MATERIAL_EXT;
  346.                         }
  347.                         else
  348.                         {
  349.                                 filename.insert(extPos, m_altSuffix);
  350.                         }
  351.  
  352.                         CCryFile testFile;
  353.  
  354.                         // If we find an alt material use it, otherwise switch back to the normal one
  355.                         if (testFile.Open(filename.c_str(), "rb"))
  356.                         {
  357.                                 extPos = filename.find('.');
  358.                         }
  359.                         else
  360.                         {
  361.                                 filename = name;
  362.                         }
  363.                 }
  364.  
  365.                 if (extPos == stack_string::npos)
  366.                         filename += MATERIAL_EXT;
  367.  
  368.                 static int nRecursionCounter = 0;
  369.  
  370.                 bool bCanCleanPools = nRecursionCounter == 0; // Only clean pool, when we are called not recursively.
  371.                 nRecursionCounter++;
  372.  
  373.                 XmlNodeRef mtlNode;
  374.                 if (m_pXmlParser)
  375.                 {
  376.                         // WARNING!!!
  377.                         // Shared XML parser does not support recursion!!!
  378.                         // On parsing a new XML file all previous XmlNodes are invalidated.
  379.                         mtlNode = m_pXmlParser->ParseFile(filename.c_str(), bCanCleanPools);
  380.                 }
  381.                 else
  382.                 {
  383.                         mtlNode = GetSystem()->LoadXmlFromFile(filename.c_str());
  384.                 }
  385.  
  386.                 if (mtlNode)
  387.                 {
  388.                         pMtl = MakeMaterialFromXml(name, name, mtlNode, false, 0, 0, nLoadingFlags);
  389.  
  390.                         if (pMtl && e_sketch_mode != 0)
  391.                         {
  392.                                 ((CMatInfo*)pMtl)->SetSketchMode(e_sketch_mode);
  393.                         }
  394.                 }
  395.  
  396.                 nRecursionCounter--;
  397.         }
  398.  
  399. #if defined(ENABLE_CONSOLE_MTL_VIZ)
  400.         if (pMtl && CMatInfo::IsConsoleMatModeEnabled())
  401.         {
  402.                 assert(gEnv->IsEditor());
  403.                 pMtl->LoadConsoleMaterial();
  404.         }
  405. #endif
  406.  
  407.         if (pMtl && pMtl->GetFlags() & MTL_FLAG_TRACEABLE_TEXTURE)
  408.                 pMtl->SetKeepLowResSysCopyForDiffTex();
  409.  
  410.         if (!pMtl && bMakeIfNotFound)
  411.         {
  412.                 pMtl = m_pDefaultMtl;
  413.         }
  414.  
  415.         if (bNonremovable && pMtl)
  416.                 m_nonRemovables.push_back(static_cast<CMatInfo*>(pMtl));
  417.  
  418.         return pMtl;
  419. }
  420.  
  421. //////////////////////////////////////////////////////////////////////////
  422. IMaterial* CMatMan::MakeMaterialFromXml(const char* sMtlName, const char* sMtlFilename, XmlNodeRef node, bool bForcePureChild, uint16 sortPrio, IMaterial* pExistingMtl, unsigned long nLoadingFlags, IMaterial* pParentMtl)
  423. {
  424.         int mtlFlags = 0;
  425.         CryFixedStringT<128> shaderName;
  426.         uint64 nShaderGenMask = 0;
  427.  
  428.         assert(node != 0);
  429.  
  430.         SInputShaderResourcesPtr sr = GetRenderer() ?
  431.                                       GetRenderer()->EF_CreateInputShaderResource() : nullptr;
  432.  
  433.         if (sr)
  434.         {
  435.                 sr->m_SortPrio = sortPrio;
  436.         }
  437.  
  438.         // Loading
  439.         node->getAttr("MtlFlags", mtlFlags);
  440.         mtlFlags &= (MTL_FLAGS_SAVE_MASK); // Clean flags that are not supposed to be save/loaded.
  441.         if (bForcePureChild)
  442.                 mtlFlags |= MTL_FLAG_PURE_CHILD;
  443.  
  444.         IMaterial* pMtl = pExistingMtl;
  445.         if (!pMtl)
  446.         {
  447.                 pMtl = CreateMaterial(sMtlName, mtlFlags);
  448.         }
  449.         else
  450.         {
  451.                 pMtl->SetFlags(mtlFlags | pMtl->GetFlags());
  452.         }
  453.  
  454.         const char* matTemplate = NULL;
  455.  
  456.         if (!(mtlFlags & MTL_FLAG_MULTI_SUBMTL))
  457.         {
  458.                 matTemplate = node->getAttr("MatTemplate");
  459.                 pMtl->SetMatTemplate(matTemplate);
  460.                 //
  461.                 shaderName = node->getAttr("Shader");
  462.  
  463.                 if (!(mtlFlags & MTL_64BIT_SHADERGENMASK))
  464.                 {
  465.                         uint32 nShaderGenMask32 = 0;
  466.                         node->getAttr("GenMask", nShaderGenMask32);
  467.                         nShaderGenMask = nShaderGenMask32;
  468.  
  469.                         // Remap 32bit flags to 64 bit version
  470.                         nShaderGenMask = GetRenderer() ?
  471.                                          GetRenderer()->EF_GetRemapedShaderMaskGen((const char*) shaderName, nShaderGenMask) : 0;
  472.                         mtlFlags |= MTL_64BIT_SHADERGENMASK;
  473.                 }
  474.                 else
  475.                         node->getAttr("GenMask", nShaderGenMask);
  476.  
  477.                 if (GetRenderer())
  478.                 {
  479.                         if (node->haveAttr("StringGenMask"))
  480.                         {
  481.                                 const char* pszShaderGenMask = node->getAttr("StringGenMask");
  482.                                 nShaderGenMask = GetRenderer()->EF_GetShaderGlobalMaskGenFromString((const char*)shaderName, pszShaderGenMask, nShaderGenMask);  // get common mask gen
  483.                         }
  484.                         else
  485.                         {
  486.                                 // version doens't has string gen mask yet ? Remap flags if needed
  487.                                 nShaderGenMask = GetRenderer()->EF_GetRemapedShaderMaskGen((const char*)shaderName, nShaderGenMask, ((mtlFlags & MTL_64BIT_SHADERGENMASK) != 0));
  488.                         }
  489.                 }
  490.                 mtlFlags |= MTL_64BIT_SHADERGENMASK;
  491.  
  492.                 const char* surfaceType = node->getAttr("SurfaceType");
  493.                 pMtl->SetSurfaceType(surfaceType);
  494.  
  495.                 if (stricmp(shaderName, "nodraw") == 0)
  496.                         mtlFlags |= MTL_FLAG_NODRAW;
  497.  
  498.                 pMtl->SetFlags(mtlFlags | pMtl->GetFlags());
  499.  
  500.                 if (sr)
  501.                 {
  502.                         s_materialHelpers.SetLightingFromXml(*sr, node);
  503.                         s_materialHelpers.SetTexturesFromXml(*sr, node, sMtlFilename);
  504.                         s_materialHelpers.MigrateXmlLegacyData(*sr, node);
  505.  
  506.                         for (EEfResTextures texId = EFTT_DIFFUSE; texId < EFTT_MAX; texId = EEfResTextures(texId + 1))
  507.                         {
  508.                                 // Ignore textures with drive letters in them
  509.                                 const char* name = sr->m_Textures[texId].m_Name;
  510.                                 if (name && (strchr(name, ':') != NULL))
  511.                                 {
  512.                                         CryLog("Invalid texture '%s' found in material '%s'", name, sMtlName);
  513.                                 }
  514.                         }
  515.                 }
  516.  
  517.         }
  518.  
  519.         //////////////////////////////////////////////////////////////////////////
  520.         // Check if we have a link name
  521.         //////////////////////////////////////////////////////////////////////////
  522.         XmlNodeRef pLinkName = node->findChild("MaterialLinkName");
  523.         if (pLinkName)
  524.         {
  525.                 const char* szLinkName = pLinkName->getAttr("name");
  526.                 pMtl->SetMaterialLinkName(szLinkName);
  527.         }
  528.  
  529.         if (sr)
  530.         {
  531.                 //////////////////////////////////////////////////////////////////////////
  532.                 // Check if we have vertex deform.
  533.                 //////////////////////////////////////////////////////////////////////////
  534.                 s_materialHelpers.SetVertexDeformFromXml(*sr, node);
  535.  
  536.                 //////////////////////////////////////////////////////////////////////////
  537.                 // Check for detail decal
  538.                 //////////////////////////////////////////////////////////////////////////
  539.                 if (mtlFlags & MTL_FLAG_DETAIL_DECAL)
  540.                         s_materialHelpers.SetDetailDecalFromXml(*sr, node);
  541.                 else
  542.                         sr->m_DetailDecalInfo.Reset();
  543.  
  544.                 //////////////////////////////////////////////////////////////////////////
  545.                 // Load public parameters.
  546.                 XmlNodeRef publicVarsNode = node->findChild("PublicParams");
  547.  
  548.                 //////////////////////////////////////////////////////////////////////////
  549.                 // Reload shader item with new resources and shader.
  550.                 if (!(mtlFlags & MTL_FLAG_MULTI_SUBMTL))
  551.                 {
  552.                         sr->m_szMaterialName = sMtlName;
  553.                         LoadMaterialShader(pMtl, pParentMtl, shaderName.c_str(), nShaderGenMask, *sr, publicVarsNode, nLoadingFlags);
  554.                 }
  555.         }
  556.  
  557.         //////////////////////////////////////////////////////////////////////////
  558.         // Load material layers data
  559.         //////////////////////////////////////////////////////////////////////////
  560.  
  561.         if (pMtl && pMtl->GetShaderItem().m_pShader && pMtl->GetShaderItem().m_pShaderResources)
  562.         {
  563.                 XmlNodeRef pMtlLayersNode = node->findChild("MaterialLayers");
  564.                 if (pMtlLayersNode)
  565.                 {
  566.                         int nLayerCount = min((int) MTL_LAYER_MAX_SLOTS, (int) pMtlLayersNode->getChildCount());
  567.                         if (nLayerCount)
  568.                         {
  569.                                 uint8 nMaterialLayerFlags = 0;
  570.  
  571.                                 pMtl->SetLayerCount(nLayerCount);
  572.                                 for (int l(0); l < nLayerCount; ++l)
  573.                                 {
  574.                                         XmlNodeRef pLayerNode = pMtlLayersNode->getChild(l);
  575.                                         if (pLayerNode)
  576.                                         {
  577.                                                 if (const char* pszShaderName = pLayerNode->getAttr("Name"))
  578.                                                 {
  579.                                                         bool bNoDraw = false;
  580.                                                         pLayerNode->getAttr("NoDraw", bNoDraw);
  581.  
  582.                                                         uint8 nLayerFlags = 0;
  583.                                                         if (bNoDraw)
  584.                                                         {
  585.                                                                 nLayerFlags |= MTL_LAYER_USAGE_NODRAW;
  586.  
  587.                                                                 if (!strcmpi(pszShaderName, "frozenlayerwip"))
  588.                                                                         nMaterialLayerFlags |= MTL_LAYER_FROZEN;
  589.                                                                 else if (!strcmpi(pszShaderName, "cloaklayer"))
  590.                                                                         nMaterialLayerFlags |= MTL_LAYER_CLOAK;
  591.                                                         }
  592.                                                         else
  593.                                                                 nLayerFlags &= ~MTL_LAYER_USAGE_NODRAW;
  594.  
  595.                                                         bool bFadeOut = false;
  596.                                                         pLayerNode->getAttr("FadeOut", bFadeOut);
  597.                                                         if (bFadeOut)
  598.                                                         {
  599.                                                                 nLayerFlags |= MTL_LAYER_USAGE_FADEOUT;
  600.                                                         }
  601.                                                         else
  602.                                                         {
  603.                                                                 nLayerFlags &= ~MTL_LAYER_USAGE_FADEOUT;
  604.                                                         }
  605.  
  606.                                                         if (sr)
  607.                                                         {
  608.                                                                 XmlNodeRef pPublicsParamsNode = pLayerNode->findChild("PublicParams");
  609.                                                                 sr->m_szMaterialName = sMtlName;
  610.                                                                 LoadMaterialLayerSlot(l, pMtl, pszShaderName, *sr, pPublicsParamsNode, nLayerFlags);
  611.                                                         }
  612.                                                 }
  613.                                         }
  614.                                 }
  615.  
  616.                                 SShaderItem pShaderItemBase = pMtl->GetShaderItem();
  617.                                 if (pShaderItemBase.m_pShaderResources)
  618.                                         pShaderItemBase.m_pShaderResources->SetMtlLayerNoDrawFlags(nMaterialLayerFlags);
  619.                         }
  620.                 }
  621.         }
  622.  
  623.         // Serialize sub materials.
  624.         XmlNodeRef childsNode = node->findChild("SubMaterials");
  625.         if (childsNode)
  626.         {
  627.                 int nSubMtls = childsNode->getChildCount();
  628.                 pMtl->SetSubMtlCount(nSubMtls);
  629.                 for (int i = 0; i < nSubMtls; i++)
  630.                 {
  631.                         XmlNodeRef mtlNode = childsNode->getChild(i);
  632.                         if (mtlNode->isTag("Material"))
  633.                         {
  634.                                 const char* name = mtlNode->getAttr("Name");
  635.                                 IMaterial* pChildMtl = MakeMaterialFromXml(name, sMtlName, mtlNode, true, nSubMtls - i - 1, 0, nLoadingFlags, pMtl);
  636.                                 if (pChildMtl)
  637.                                         pMtl->SetSubMtl(i, pChildMtl);
  638.                                 else
  639.                                         pMtl->SetSubMtl(i, m_pDefaultMtl);
  640.                         }
  641.                         else
  642.                         {
  643.                                 const char* name = mtlNode->getAttr("Name");
  644.                                 if (name[0])
  645.                                 {
  646.                                         IMaterial* pChildMtl = LoadMaterial(name, true, false, nLoadingFlags);
  647.                                         if (pChildMtl)
  648.                                                 pMtl->SetSubMtl(i, pChildMtl);
  649.                                 }
  650.                         }
  651.                 }
  652.         }
  653.         //
  654.         if (matTemplate != NULL && strlen(matTemplate) != 0 && strcmp(matTemplate, sMtlName) != 0)
  655.         {
  656.                 CMatInfo* pMtlTmpl = NULL;
  657.                 pMtlTmpl = static_cast<CMatInfo*>(gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(matTemplate, false));
  658.                 if (pMtlTmpl)
  659.                 {
  660.                         pMtlTmpl->Copy(static_cast<CMatInfo*>(pMtl), MTL_COPY_DEFAULT);
  661.                         return pMtl;
  662.                 }
  663.         }
  664.         //
  665.         return pMtl;
  666. }
  667.  
  668. //////////////////////////////////////////////////////////////////////////
  669. bool CMatMan::LoadMaterialShader(IMaterial* pMtl, IMaterial* pParentMtl, const char* sShader, uint64 nShaderGenMask, SInputShaderResources& sr, XmlNodeRef& publicsNode, unsigned long nLoadingFlags)
  670. {
  671.         // Mark material invalid by default.
  672.         sr.m_ResFlags = pMtl->GetFlags();
  673.  
  674.         // Set public params.
  675.         if (publicsNode)
  676.         {
  677.                 // Copy public params from the shader.
  678.                 //sr.m_ShaderParams = shaderItem.m_pShader->GetPublicParams();
  679.                 // Parse public parameters, and assign them to source shader resources.
  680.                 ParsePublicParams(sr, publicsNode);
  681.                 //shaderItem.m_pShaderResources->SetShaderParams(&sr, shaderItem.m_pShader);
  682.         }
  683.  
  684.         IRenderer::SLoadShaderItemArgs args(pMtl, pParentMtl);
  685.         SShaderItem shaderItem = gEnv->pRenderer->EF_LoadShaderItem(sShader, false, 0, &sr, nShaderGenMask, &args);
  686.         if (!shaderItem.m_pShader || (shaderItem.m_pShader->GetFlags() & EF_NOTFOUND) != 0)
  687.         {
  688.                 Warning("Failed to load shader \"%s\" in material \"%s\"", sShader, pMtl->GetName());
  689.                 if (!shaderItem.m_pShader)
  690.                         return false;
  691.         }
  692.         pMtl->AssignShaderItem(shaderItem);
  693.  
  694.         return true;
  695. }
  696.  
  697. bool CMatMan::LoadMaterialLayerSlot(uint32 nSlot, IMaterial* pMtl, const char* szShaderName, SInputShaderResources& pBaseResources, XmlNodeRef& pPublicsNode, uint8 nLayerFlags)
  698. {
  699.         if (!pMtl || pMtl->GetLayer(nSlot) || !pPublicsNode)
  700.         {
  701.                 return false;
  702.         }
  703.  
  704.         // need to handle no draw case
  705.         if (stricmp(szShaderName, "nodraw") == 0)
  706.         {
  707.                 // no shader = skip layer
  708.                 return false;
  709.         }
  710.  
  711.         // Get base material/shaderItem info
  712.         SInputShaderResourcesPtr pInputResources = GetRenderer()->EF_CreateInputShaderResource();
  713.         SShaderItem pShaderItemBase = pMtl->GetShaderItem();
  714.  
  715.         uint32 nMaskGenBase = (uint32)pShaderItemBase.m_pShader->GetGenerationMask();
  716.         SShaderGen* pShaderGenBase = pShaderItemBase.m_pShader->GetGenerationParams();
  717.  
  718.         // copy diffuse and bump textures names
  719.  
  720.         pInputResources->m_szMaterialName = pBaseResources.m_szMaterialName;
  721.         pInputResources->m_Textures[EFTT_DIFFUSE].m_Name = pBaseResources.m_Textures[EFTT_DIFFUSE].m_Name;
  722.         pInputResources->m_Textures[EFTT_NORMALS].m_Name = pBaseResources.m_Textures[EFTT_NORMALS].m_Name;
  723.  
  724.         // Check if names are valid - else replace with default textures
  725.  
  726.         if (pInputResources->m_Textures[EFTT_DIFFUSE].m_Name.empty())
  727.         {
  728.                 pInputResources->m_Textures[EFTT_DIFFUSE].m_Name = szReplaceMe;
  729.                 //              pInputResources->m_Textures[EFTT_DIFFUSE].m_Name = "<default>";
  730.         }
  731.  
  732.         if (pInputResources->m_Textures[EFTT_NORMALS].m_Name.empty())
  733.         {
  734.                 pInputResources->m_Textures[EFTT_NORMALS].m_Name = "EngineAssets/Textures/white_ddn.dds";
  735.         }
  736.  
  737.         // Load layer shader item
  738.         IShader* pNewShader = gEnv->pRenderer->EF_LoadShader(szShaderName, 0);
  739.         if (!pNewShader)
  740.         {
  741.                 Warning("Failed to load material layer shader %s in Material %s", szShaderName, pMtl->GetName());
  742.                 return false;
  743.         }
  744.  
  745.         // mask generation for base material shader
  746.         uint32 nMaskGenLayer = 0;
  747.         SShaderGen* pShaderGenLayer = pNewShader->GetGenerationParams();
  748.         if (pShaderGenBase && pShaderGenLayer)
  749.         {
  750.                 for (unsigned nLayerBit(0); nLayerBit < pShaderGenLayer->m_BitMask.size(); ++nLayerBit)
  751.                 {
  752.                         SShaderGenBit* pLayerBit = pShaderGenLayer->m_BitMask[nLayerBit];
  753.  
  754.                         for (unsigned nBaseBit(0); nBaseBit < pShaderGenBase->m_BitMask.size(); ++nBaseBit)
  755.                         {
  756.                                 SShaderGenBit* pBaseBit = pShaderGenBase->m_BitMask[nBaseBit];
  757.  
  758.                                 // Need to check if flag name is common to both shaders (since flags values can be different), if so activate it on this layer
  759.                                 if (nMaskGenBase & pBaseBit->m_Mask)
  760.                                 {
  761.                                         if (!pLayerBit->m_ParamName.empty() && !pBaseBit->m_ParamName.empty())
  762.                                         {
  763.                                                 if (pLayerBit->m_ParamName == pBaseBit->m_ParamName)
  764.                                                 {
  765.                                                         nMaskGenLayer |= pLayerBit->m_Mask;
  766.                                                         break;
  767.                                                 }
  768.                                         }
  769.                                 }
  770.                         }
  771.                 }
  772.         }
  773.  
  774.         // Reload with proper flags
  775.         IShader* pShader = gEnv->pRenderer->EF_LoadShader(szShaderName, 0, nMaskGenLayer);
  776.         if (!pShader)
  777.         {
  778.                 Warning("Failed to load material layer shader %s in Material %s", szShaderName, pMtl->GetName());
  779.                 SAFE_RELEASE(pNewShader);
  780.                 return false;
  781.         }
  782.         SAFE_RELEASE(pNewShader);
  783.  
  784.         // Copy public params from the shader.
  785.         //pInputResources->m_ShaderParams = pShaderItem.m_pShader->GetPublicParams();
  786.  
  787.         // Copy resources from base material
  788.         SShaderItem ShaderItem(pShader, pShaderItemBase.m_pShaderResources->Clone());
  789.  
  790.         ParsePublicParams(*pInputResources, pPublicsNode);
  791.  
  792.         // Parse public parameters, and assign them to source shader resources.
  793.         ShaderItem.m_pShaderResources->SetShaderParams(pInputResources, ShaderItem.m_pShader);
  794.  
  795.         IMaterialLayer* pCurrMtlLayer = pMtl->CreateLayer();
  796.  
  797.         pCurrMtlLayer->SetFlags(nLayerFlags);
  798.         pCurrMtlLayer->SetShaderItem(pMtl, ShaderItem);
  799.  
  800.         // Clone returns an instance with a refcount of 1, and SetShaderItem increments it, so
  801.         // we need to release the cloned ref.
  802.         SAFE_RELEASE(ShaderItem.m_pShaderResources);
  803.         SAFE_RELEASE(ShaderItem.m_pShader);
  804.  
  805.         pMtl->SetLayer(nSlot, pCurrMtlLayer);
  806.  
  807.         return true;
  808. }
  809.  
  810. //////////////////////////////////////////////////////////////////////////
  811.  
  812. static void shGetVector4(const char* buf, float v[4])
  813. {
  814.         if (!buf)
  815.                 return;
  816.         int res = sscanf(buf, "%f,%f,%f,%f", &v[0], &v[1], &v[2], &v[3]);
  817.         assert(res);
  818. }
  819.  
  820. void CMatMan::ParsePublicParams(SInputShaderResources& sr, XmlNodeRef paramsNode)
  821. {
  822.         sr.m_ShaderParams.clear();
  823.  
  824.         int nA = paramsNode->getNumAttributes();
  825.         if (!nA)
  826.                 return;
  827.  
  828.         for (int i = 0; i < nA; i++)
  829.         {
  830.                 const char* key = NULL, * val = NULL;
  831.                 paramsNode->getAttributeByIndex(i, &key, &val);
  832.                 SShaderParam Param;
  833.                 assert(val && key);
  834.                 cry_strcpy(Param.m_Name, key);
  835.                 Param.m_Value.m_Color[0] = Param.m_Value.m_Color[1] = Param.m_Value.m_Color[2] = Param.m_Value.m_Color[3] = 0;
  836.                 shGetVector4(val, Param.m_Value.m_Color);
  837.                 sr.m_ShaderParams.push_back(Param);
  838.         }
  839. }
  840.  
  841. //////////////////////////////////////////////////////////////////////////
  842. ISurfaceType* CMatMan::GetSurfaceTypeByName(const char* sSurfaceTypeName, const char* sWhy)
  843. {
  844.         return m_pSurfaceTypeManager->GetSurfaceTypeByName(sSurfaceTypeName, sWhy);
  845. };
  846.  
  847. //////////////////////////////////////////////////////////////////////////
  848. int CMatMan::GetSurfaceTypeIdByName(const char* sSurfaceTypeName, const char* sWhy)
  849. {
  850.         ISurfaceType* pSurfaceType = m_pSurfaceTypeManager->GetSurfaceTypeByName(sSurfaceTypeName, sWhy);
  851.         if (pSurfaceType)
  852.                 return pSurfaceType->GetId();
  853.         return 0;
  854. };
  855.  
  856. //////////////////////////////////////////////////////////////////////////
  857. IMaterial* CMatMan::GetDefaultLayersMaterial()
  858. {
  859.         if (!m_bInitialized)
  860.                 InitDefaults();
  861.  
  862.         return m_pDefaultLayersMtl;
  863. }
  864.  
  865. //////////////////////////////////////////////////////////////////////////
  866. IMaterial* CMatMan::GetDefaultHelperMaterial()
  867. {
  868.         if (!m_bInitialized)
  869.                 InitDefaults();
  870.  
  871.         return m_pDefaultHelperMtl;
  872. }
  873.  
  874. //////////////////////////////////////////////////////////////////////////
  875. void CMatMan::GetLoadedMaterials(IMaterial** pData, uint32& nObjCount) const
  876. {
  877.         nObjCount = m_mtlNameMap.size();
  878.  
  879.         if (!pData)
  880.                 return;
  881.  
  882.         MtlNameMap::const_iterator it, end = m_mtlNameMap.end();
  883.  
  884.         for (it = m_mtlNameMap.begin(); it != end; ++it)
  885.         {
  886.                 IMaterial* pMat = it->second;
  887.  
  888.                 *pData++ = pMat;
  889.         }
  890. }
  891.  
  892. //////////////////////////////////////////////////////////////////////////
  893. void CMatMan::SetAltMaterialSuffix(const char* pSuffix)
  894. {
  895.         if (!pSuffix)
  896.                 m_altSuffix.clear();
  897.         else
  898.                 m_altSuffix = pSuffix;
  899. }
  900.  
  901. //////////////////////////////////////////////////////////////////////////
  902. IMaterial* CMatMan::CloneMaterial(IMaterial* pSrcMtl, int nSubMtl)
  903. {
  904.         if (pSrcMtl->GetFlags() & MTL_FLAG_MULTI_SUBMTL)
  905.         {
  906.                 IMaterial* pMultiMat = new CMatInfo;
  907.  
  908.                 //m_mtlSet.insert( pMat );
  909.                 pMultiMat->SetName(pSrcMtl->GetName());
  910.                 pMultiMat->SetFlags(pMultiMat->GetFlags() | MTL_FLAG_MULTI_SUBMTL);
  911.  
  912.                 bool bCloneAllSubMtls = nSubMtl < 0;
  913.  
  914.                 int nSubMtls = pSrcMtl->GetSubMtlCount();
  915.                 pMultiMat->SetSubMtlCount(nSubMtls);
  916.                 for (int i = 0; i < nSubMtls; i++)
  917.                 {
  918.                         CMatInfo* pChildSrcMtl = (CMatInfo*)pSrcMtl->GetSubMtl(i);
  919.                         if (!pChildSrcMtl)
  920.                                 continue;
  921.                         if (bCloneAllSubMtls)
  922.                         {
  923.                                 pMultiMat->SetSubMtl(i, pChildSrcMtl->Clone((CMatInfo*)pMultiMat));
  924.                         }
  925.                         else
  926.                         {
  927.                                 pMultiMat->SetSubMtl(i, pChildSrcMtl);
  928.                                 if (i == nSubMtls)
  929.                                 {
  930.                                         // Clone this slot.
  931.                                         pMultiMat->SetSubMtl(i, pChildSrcMtl->Clone((CMatInfo*)pMultiMat));
  932.                                 }
  933.                         }
  934.                 }
  935.                 return pMultiMat;
  936.         }
  937.         else
  938.         {
  939.                 return ((CMatInfo*)pSrcMtl)->Clone(0);
  940.         }
  941. }
  942.  
  943. void CMatMan::CopyMaterial(IMaterial* pMtlSrc, IMaterial* pMtlDest, EMaterialCopyFlags flags)
  944. {
  945.         return ((CMatInfo*)pMtlSrc)->Copy(pMtlDest, flags);
  946. }
  947.  
  948. //////////////////////////////////////////////////////////////////////////
  949. IMaterial* CMatMan::CloneMultiMaterial(IMaterial* pSrcMtl, const char* sSubMtlName)
  950. {
  951.         if (pSrcMtl->GetFlags() & MTL_FLAG_MULTI_SUBMTL)
  952.         {
  953.                 IMaterial* pMultiMat = new CMatInfo;
  954.  
  955.                 //m_mtlSet.insert( pMat );
  956.                 pMultiMat->SetName(pSrcMtl->GetName());
  957.                 pMultiMat->SetFlags(pMultiMat->GetFlags() | MTL_FLAG_MULTI_SUBMTL);
  958.  
  959.                 bool bCloneAllSubMtls = sSubMtlName == 0;
  960.  
  961.                 int nSubMtls = pSrcMtl->GetSubMtlCount();
  962.                 pMultiMat->SetSubMtlCount(nSubMtls);
  963.                 for (int i = 0; i < nSubMtls; i++)
  964.                 {
  965.                         CMatInfo* pChildSrcMtl = (CMatInfo*)pSrcMtl->GetSubMtl(i);
  966.                         if (!pChildSrcMtl)
  967.                                 continue;
  968.                         if (bCloneAllSubMtls)
  969.                         {
  970.                                 pMultiMat->SetSubMtl(i, pChildSrcMtl->Clone((CMatInfo*)pMultiMat));
  971.                         }
  972.                         else
  973.                         {
  974.                                 pMultiMat->SetSubMtl(i, pChildSrcMtl);
  975.                                 if (stricmp(pChildSrcMtl->GetName(), sSubMtlName) == 0)
  976.                                 {
  977.                                         // Clone this slot.
  978.                                         pMultiMat->SetSubMtl(i, pChildSrcMtl->Clone((CMatInfo*)pMultiMat));
  979.                                 }
  980.                         }
  981.                 }
  982.                 return pMultiMat;
  983.         }
  984.         else
  985.         {
  986.                 return ((CMatInfo*)pSrcMtl)->Clone(0);
  987.         }
  988. }
  989.  
  990. //////////////////////////////////////////////////////////////////////////
  991. void CMatMan::DoLoadSurfaceTypesInInit(bool doLoadSurfaceTypesInInit)
  992. {
  993.         m_bLoadSurfaceTypesInInit = doLoadSurfaceTypesInInit;
  994. }
  995.  
  996. //////////////////////////////////////////////////////////////////////////
  997. void CMatMan::InitDefaults()
  998. {
  999.         if (m_bInitialized)
  1000.                 return;
  1001.         m_bInitialized = true;
  1002.  
  1003.         LOADING_TIME_PROFILE_SECTION;
  1004.  
  1005.         SYNCHRONOUS_LOADING_TICK();
  1006.  
  1007.         if (m_bLoadSurfaceTypesInInit)
  1008.         {
  1009.                 m_pSurfaceTypeManager->LoadSurfaceTypes();
  1010.         }
  1011.  
  1012.         auto CreateDefaultMaterialWithShader = [](const char* mat_name, const char* shader_name)
  1013.         {
  1014.                 _smart_ptr<CMatInfo> mi = new CMatInfo();
  1015.                 mi->SetName(mat_name);
  1016.                 if (GetRenderer())
  1017.                 {
  1018.                         SInputShaderResourcesPtr pIsr = GetRenderer()->EF_CreateInputShaderResource();
  1019.                         pIsr->m_LMaterial.m_Opacity = 1;
  1020.                         pIsr->m_LMaterial.m_Diffuse.set(1, 1, 1, 1);
  1021.                         pIsr->m_Textures[EFTT_DIFFUSE].m_Name = szReplaceMe;
  1022.                         SShaderItem si = GetRenderer()->EF_LoadShaderItem(shader_name, true, 0, pIsr);
  1023.                         if (si.m_pShaderResources)
  1024.                                 si.m_pShaderResources->SetMaterialName(mat_name);
  1025.                         mi->AssignShaderItem(si);
  1026.                 }
  1027.                 return mi;
  1028.         };
  1029.  
  1030.         if (!m_pDefaultMtl)
  1031.         {
  1032.                 // This line is REQUIRED by the buildbot testing framework to determine when tests have formally started. Please inform WillW or Morgan before changing this.
  1033.                 CryLogAlways("Initializing default materials...");
  1034.                 m_pDefaultMtl = CreateDefaultMaterialWithShader("Default", "Illum");
  1035.         }
  1036.  
  1037.         if (!m_pDefaultTerrainLayersMtl)
  1038.         {
  1039.                 m_pDefaultTerrainLayersMtl = CreateDefaultMaterialWithShader("DefaultTerrainLayer", "Terrain.Layer");
  1040.         }
  1041.  
  1042.         if (!m_pDefaultLayersMtl)
  1043.         {
  1044.                 m_pDefaultLayersMtl = LoadMaterial("Materials/material_layers_default", false);
  1045.         }
  1046.  
  1047.         if (!m_pNoDrawMtl)
  1048.         {
  1049.                 m_pNoDrawMtl = new CMatInfo;
  1050.                 m_pNoDrawMtl->SetFlags(MTL_FLAG_NODRAW);
  1051.                 m_pNoDrawMtl->SetName(MATERIAL_NODRAW);
  1052.                 if (GetRenderer())
  1053.                 {
  1054.                         SShaderItem si;
  1055.                         si.m_pShader = GetRenderer()->EF_LoadShader(MATERIAL_NODRAW, 0);
  1056.                         m_pNoDrawMtl->AssignShaderItem(si);
  1057.                 }
  1058.                 m_mtlNameMap[UnifyName(m_pNoDrawMtl->GetName())] = m_pNoDrawMtl;
  1059.         }
  1060.  
  1061.         if (!m_pDefaultHelperMtl)
  1062.         {
  1063.                 m_pDefaultHelperMtl = CreateDefaultMaterialWithShader("DefaultHelper", "Helper");
  1064.         }
  1065.  
  1066.         SLICE_AND_SLEEP();
  1067. }
  1068.  
  1069. //////////////////////////////////////////////////////////////////////////
  1070. IMaterial* CMatMan::LoadCGFMaterial(const char* szMaterialName, const char* szCgfFilename, unsigned long nLoadingFlags)
  1071. {
  1072.         FUNCTION_PROFILER_3DENGINE;
  1073.  
  1074.         CryPathString sMtlName = szMaterialName;
  1075.         if (sMtlName.find('/') == stack_string::npos)
  1076.         {
  1077.                 // If no slashes in the name assume it is in same folder as a cgf.
  1078.                 sMtlName = PathUtil::AddSlash(PathUtil::GetPathWithoutFilename(stack_string(szCgfFilename))) + sMtlName;
  1079.         }
  1080.         else
  1081.         {
  1082.                 sMtlName = PathUtil::MakeGamePath(sMtlName);
  1083.         }
  1084.         return LoadMaterial(sMtlName.c_str(), true, false, nLoadingFlags);
  1085. }
  1086.  
  1087. //////////////////////////////////////////////////////////////////////////
  1088. void CMatMan::SetSketchMode(int mode)
  1089. {
  1090.         if (mode != 0)
  1091.         {
  1092.                 gEnv->pConsole->ExecuteString("exec sketch_on");
  1093.         }
  1094.         else
  1095.         {
  1096.                 gEnv->pConsole->ExecuteString("exec sketch_off");
  1097.         }
  1098.  
  1099.         for (MtlNameMap::iterator it = m_mtlNameMap.begin(); it != m_mtlNameMap.end(); ++it)
  1100.         {
  1101.                 CMatInfo* pMtl = (CMatInfo*)it->second;
  1102.                 pMtl->SetSketchMode(mode);
  1103.         }
  1104. }
  1105.  
  1106. //////////////////////////////////////////////////////////////////////////
  1107. void CMatMan::SetTexelDensityDebug(int mode)
  1108. {
  1109.         for (MtlNameMap::iterator it = m_mtlNameMap.begin(); it != m_mtlNameMap.end(); ++it)
  1110.         {
  1111.                 CMatInfo* pMtl = (CMatInfo*)it->second;
  1112.                 pMtl->SetTexelDensityDebug(mode);
  1113.         }
  1114. }
  1115.  
  1116. namespace
  1117. {
  1118. static bool IsPureChild(IMaterial* pMtl)
  1119. {
  1120.         return (pMtl->GetFlags() & MTL_FLAG_PURE_CHILD) ? true : false;
  1121. }
  1122. static bool IsMultiSubMaterial(IMaterial* pMtl)
  1123. {
  1124.         return (pMtl->GetFlags() & MTL_FLAG_MULTI_SUBMTL) ? true : false;
  1125. };
  1126. }
  1127.  
  1128. //////////////////////////////////////////////////////////////////////////
  1129. IMaterial* CMatMan::LoadMaterialFromXml(const char* sMtlName, XmlNodeRef mtlNode)
  1130. {
  1131.         const char* name = UnifyName(sMtlName);
  1132.  
  1133.         MtlNameMap::const_iterator it = m_mtlNameMap.find(CONST_TEMP_STRING(name));
  1134.  
  1135.         IMaterial* pMtl = 0;
  1136.  
  1137.         if (it != m_mtlNameMap.end())
  1138.         {
  1139.                 pMtl = it->second;
  1140.                 pMtl = MakeMaterialFromXml(name, name, mtlNode, false, 0, pMtl);
  1141.                 return pMtl;
  1142.         }
  1143.  
  1144.         if (!pMtl)
  1145.         {
  1146.                 pMtl = MakeMaterialFromXml(name, name, mtlNode, false);
  1147.         }
  1148.  
  1149.         return pMtl;
  1150. }
  1151.  
  1152. //////////////////////////////////////////////////////////////////////////
  1153. void CMatMan::PreloadLevelMaterials()
  1154. {
  1155.         LOADING_TIME_PROFILE_SECTION;
  1156.  
  1157.         //bool bMtlfCacheExist = GetISystem()->GetIResourceManager()->LoadLevelCachePak( MTL_LEVEL_CACHE_PAK,"" );
  1158.         //if (!bMtlfCacheExist)
  1159.         //return;
  1160.  
  1161.         PrintMessage("==== Starting Loading Level Materials ====");
  1162.         float fStartTime = GetCurAsyncTimeSec();
  1163.  
  1164.         IResourceList* pResList = GetISystem()->GetIResourceManager()->GetLevelResourceList();
  1165.  
  1166.         if (!pResList)
  1167.         {
  1168.                 Error("Error loading level Materials: resource list is NULL");
  1169.                 return;
  1170.         }
  1171.  
  1172.         int nCounter = 0;
  1173.         int nInLevelCacheCount = 0;
  1174.  
  1175.         _smart_ptr<IXmlParser> pXmlParser = GetISystem()->GetXmlUtils()->CreateXmlParser();
  1176.  
  1177.         // Request objects loading from Streaming System.
  1178.         CryPathString mtlName;
  1179.         CryPathString mtlFilename;
  1180.         CryPathString mtlCacheFilename;
  1181.         for (const char* sName = pResList->GetFirst(); sName != NULL; sName = pResList->GetNext())
  1182.         {
  1183.                 if (strstr(sName, ".mtl") == 0 && strstr(sName, ".binmtl") == 0)
  1184.                         continue;
  1185.  
  1186.                 mtlFilename = sName;
  1187.  
  1188.                 mtlName = sName;
  1189.                 PathUtil::RemoveExtension(mtlName);
  1190.  
  1191.                 if (FindMaterial(mtlName))
  1192.                         continue;
  1193.  
  1194.                 // Load this material as un-removable.
  1195.                 IMaterial* pMtl = LoadMaterial(mtlName, false, true);
  1196.                 if (pMtl)
  1197.                 {
  1198.                         nCounter++;
  1199.                 }
  1200.  
  1201.                 //This loop can take a few seconds, so we should refresh the loading screen and call the loading tick functions to ensure that no big gaps in coverage occur.
  1202.                 SYNCHRONOUS_LOADING_TICK();
  1203.         }
  1204.  
  1205.         //GetISystem()->GetIResourceManager()->UnloadLevelCachePak( MTL_LEVEL_CACHE_PAK );
  1206.         PrintMessage("==== Finished loading level Materials: %d  mtls loaded (%d from LevelCache) in %.1f sec ====", nCounter, nInLevelCacheCount, GetCurAsyncTimeSec() - fStartTime);
  1207. }
  1208.  
  1209. //////////////////////////////////////////////////////////////////////////
  1210. void CMatMan::PreloadDecalMaterials()
  1211. {
  1212.         LOADING_TIME_PROFILE_SECTION;
  1213.  
  1214.         float fStartTime = GetCurAsyncTimeSec();
  1215.  
  1216.         bool bVerboseLogging = GetCVars()->e_StatObjPreload > 1;
  1217.         int nCounter = 0;
  1218.  
  1219.         // Wildcards load.
  1220.         CryPathString sPath = PathUtil::Make(CryPathString(MATERIAL_DECALS_FOLDER), CryPathString(MATERIAL_DECALS_SEARCH_WILDCARD));
  1221.         PrintMessage("===== Loading all Decal materials from a folder: %s =====", sPath.c_str());
  1222.  
  1223.         std::vector<string> mtlFiles;
  1224.         SDirectoryEnumeratorHelper dirHelper;
  1225.         dirHelper.ScanDirectoryRecursive("", MATERIAL_DECALS_FOLDER, MATERIAL_DECALS_SEARCH_WILDCARD, mtlFiles);
  1226.  
  1227.         for (int i = 0, num = (int)mtlFiles.size(); i < num; i++)
  1228.         {
  1229.                 CryPathString sMtlName = mtlFiles[i];
  1230.                 PathUtil::RemoveExtension(sMtlName);
  1231.  
  1232.                 if (bVerboseLogging)
  1233.                 {
  1234.                         CryLog("Preloading Decal Material: %s", sMtlName.c_str());
  1235.                 }
  1236.  
  1237.                 IMaterial* pMtl = LoadMaterial(sMtlName.c_str(), false, true); // Load material as non-removable
  1238.                 if (pMtl)
  1239.                 {
  1240.                         nCounter++;
  1241.                 }
  1242.         }
  1243.         PrintMessage("==== Finished Loading Decal Materials: %d  mtls loaded in %.1f sec ====", nCounter, GetCurAsyncTimeSec() - fStartTime);
  1244. }
  1245.  
  1246. //////////////////////////////////////////////////////////////////////////
  1247. void CMatMan::ShutDown()
  1248. {
  1249.         m_pXmlParser = 0;
  1250.         stl::free_container(m_nonRemovables);
  1251.         m_mtlNameMap.clear();
  1252.  
  1253.         // Free default materials
  1254.         if (m_pDefaultMtl)
  1255.         {
  1256.                 m_pDefaultMtl->ShutDown();
  1257.                 m_pDefaultMtl = 0;
  1258.         }
  1259.  
  1260.         if (m_pDefaultTerrainLayersMtl)
  1261.         {
  1262.                 m_pDefaultTerrainLayersMtl->ShutDown();
  1263.                 m_pDefaultTerrainLayersMtl = 0;
  1264.         }
  1265.  
  1266.         if (m_pNoDrawMtl)
  1267.         {
  1268.                 m_pNoDrawMtl->ShutDown();
  1269.                 m_pNoDrawMtl = 0;
  1270.         }
  1271.  
  1272.         if (m_pDefaultHelperMtl)
  1273.         {
  1274.                 m_pDefaultHelperMtl->ShutDown();
  1275.                 m_pDefaultHelperMtl = 0;
  1276.         }
  1277.  
  1278.         m_pDefaultLayersMtl = 0; // Created using LoadMaterial func, so will be freed in FreeAllMaterials
  1279.  
  1280.         FreeAllMaterials();
  1281.  
  1282.         m_pSurfaceTypeManager->RemoveAll();
  1283.         m_bInitialized = false;
  1284. }
  1285.  
  1286. //////////////////////////////////////////////////////////////////////////
  1287. void CMatMan::FreeAllMaterials()
  1288. {
  1289. #ifndef _RELEASE
  1290.         {
  1291.                 std::vector<IMaterial*> Materials;
  1292.                 uint32 nObjCount = 0;
  1293.                 GetLoadedMaterials(0, nObjCount);
  1294.                 Materials.resize(nObjCount);
  1295.                 if (nObjCount > 0)
  1296.                 {
  1297.                         GetLoadedMaterials(&Materials[0], nObjCount);
  1298.                         Warning("CObjManager::CheckMaterialLeaks: %d materials(s) found in memory", nObjCount);
  1299.                         for (uint32 i = 0; i < nObjCount; i++)
  1300.                         {
  1301.                                 Warning("Material not deleted: %s (RefCount: %d)", Materials[i]->GetName(), Materials[i]->GetNumRefs());
  1302.         #ifdef TRACE_MATERIAL_LEAKS
  1303.                                 Warning("      RefCount: %d, callstack : %s,", Materials[i]->GetNumRefs(), Materials[i]->GetLoadingCallstack());
  1304.         #endif
  1305.                         }
  1306.                 }
  1307.         }
  1308. #endif //_RELEASE
  1309.  
  1310.         //////////////////////////////////////////////////////////////////////////
  1311.  
  1312.         ForceDelayedMaterialDeletion();
  1313.         CMatInfo* pMtl = CMatInfo::get_intrusive_list_root();
  1314.  
  1315.         // Shut down all materials
  1316.         pMtl = CMatInfo::get_intrusive_list_root();
  1317.         while (pMtl)
  1318.         {
  1319.                 pMtl->ShutDown();
  1320.                 pMtl = pMtl->get_next_intrusive();
  1321.         }
  1322. }
  1323.  
  1324. void CMatMan::GetMemoryUsage(ICrySizer* pSizer) const
  1325. {
  1326.         pSizer->AddObject(this, sizeof(*this));
  1327.         pSizer->AddObject(m_pDefaultMtl);
  1328.         pSizer->AddObject(m_pDefaultLayersMtl);
  1329.         pSizer->AddObject(m_pDefaultTerrainLayersMtl);
  1330.         pSizer->AddObject(m_pNoDrawMtl);
  1331.         pSizer->AddObject(m_pDefaultHelperMtl);
  1332.         pSizer->AddObject(m_pSurfaceTypeManager);
  1333.         pSizer->AddObject(m_pXmlParser);
  1334.  
  1335.         pSizer->AddObject(m_mtlNameMap);
  1336.         pSizer->AddObject(m_nonRemovables);
  1337. }
  1338.  
  1339. void CMatMan::UpdateShaderItems()
  1340. {
  1341.         for (MtlNameMap::iterator iter = m_mtlNameMap.begin(); iter != m_mtlNameMap.end(); ++iter)
  1342.         {
  1343.                 CMatInfo* pMaterial = static_cast<CMatInfo*>(iter->second);
  1344.                 pMaterial->UpdateShaderItems();
  1345.         }
  1346. }
  1347.  
  1348. void CMatMan::RefreshMaterialRuntime()
  1349. {
  1350.         RefreshShaderResourceConstants();
  1351. }
  1352.  
  1353. void CMatMan::RefreshShaderResourceConstants()
  1354. {
  1355.         for (MtlNameMap::iterator iter = m_mtlNameMap.begin(); iter != m_mtlNameMap.end(); ++iter)
  1356.         {
  1357.                 CMatInfo* pMaterial = static_cast<CMatInfo*>(iter->second);
  1358.                 pMaterial->RefreshShaderResourceConstants();
  1359.         }
  1360. }
  1361.  
downloadMatMan.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top