BVB Source Codes

CRYENGINE Show MaterialEffects.cpp Source code

Return Download CRYENGINE: download MaterialEffects.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH. All rights reserved.
  2. #include "StdAfx.h"
  3. #include <limits.h>
  4. #include <CryString/CryPath.h>
  5. #include "MaterialEffectsCVars.h"
  6. #include "MaterialEffects.h"
  7. #include "MFXRandomEffect.h"
  8. #include "MFXParticleEffect.h"
  9. #include "MFXDecalEffect.h"
  10. #include "MFXRandomEffect.h"
  11. #include "MaterialFGManager.h"
  12. #include "MaterialEffectsDebug.h"
  13. #include <CryMemory/PoolAllocator.h>
  14.  
  15. #define MATERIAL_EFFECTS_SPREADSHEET_FILE     "libs/materialeffects/materialeffects.xml"
  16. #define MATERIAL_EFFECTS_LIBRARIES_FOLDER     "libs/materialeffects/fxlibs"
  17.  
  18. #define MATERIAL_EFFECTS_SURFACE_TYPE_DEFAULT "mat_default"
  19. #define MATERIAL_EFFECTS_SURFACE_TYPE_CANOPY  "mat_canopy"
  20.  
  21. //////////////////////////////////////////////////////////////////////////
  22. //////////////////////////////////////////////////////////////////////////
  23.  
  24. #define IMPL_POOL_RETURNING(type, rtype)                       \
  25.   static stl::PoolAllocatorNoMT<sizeof(type)> m_pool_ ## type; \
  26.   rtype type::Create()                                         \
  27.   {                                                            \
  28.     return new(m_pool_ ## type.Allocate())type();              \
  29.   }                                                            \
  30.   void type::Destroy()                                         \
  31.   {                                                            \
  32.     this->~type();                                             \
  33.     m_pool_ ## type.Deallocate(this);                          \
  34.   }                                                            \
  35.   void type::FreePool()                                        \
  36.   {                                                            \
  37.     m_pool_ ## type.FreeMemory();                              \
  38.   }
  39. #define IMPL_POOL(type) IMPL_POOL_RETURNING(type, type*)
  40.  
  41. IMPL_POOL_RETURNING(SMFXResourceList, SMFXResourceListPtr);
  42. IMPL_POOL(SMFXFlowGraphListNode);
  43. IMPL_POOL(SMFXDecalListNode);
  44. IMPL_POOL(SMFXParticleListNode);
  45. IMPL_POOL(SMFXAudioListNode);
  46. IMPL_POOL(SMFXForceFeedbackListNode);
  47.  
  48. namespace MaterialEffectsUtils
  49. {
  50. int FindSurfaceIdByName(const char* surfaceTypeName)
  51. {
  52.         CRY_ASSERT(surfaceTypeName != NULL);
  53.  
  54.         ISurfaceType* pSurfaceType = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager()->GetSurfaceTypeByName(surfaceTypeName);
  55.         if (pSurfaceType != NULL)
  56.         {
  57.                 return (int)pSurfaceType->GetId();
  58.         }
  59.  
  60.         return -1;
  61. }
  62. }
  63.  
  64. CMaterialEffects::CMaterialEffects()
  65.         : m_bDataInitialized(false)
  66.         , m_listeners(4)
  67.         , m_pAnimFXEvents(nullptr)
  68. {
  69.         m_bUpdateMode = false;
  70.         m_defaultSurfaceId = MaterialEffectsUtils::FindSurfaceIdByName(MATERIAL_EFFECTS_SURFACE_TYPE_DEFAULT);
  71.         m_canopySurfaceId = m_defaultSurfaceId;
  72.         m_pMaterialFGManager = new CMaterialFGManager();
  73.  
  74. #ifdef MATERIAL_EFFECTS_DEBUG
  75.         m_pVisualDebug = new MaterialEffectsUtils::CVisualDebug();
  76. #endif
  77. }
  78.  
  79. CMaterialEffects::~CMaterialEffects()
  80. {
  81.         // smart pointers will automatically release.
  82.         // the clears will immediately delete all effects while CMaterialEffects is still exisiting
  83.         m_mfxLibraries.clear();
  84.         m_delayedEffects.clear();
  85.         m_effectContainers.clear();
  86.         SAFE_DELETE(m_pMaterialFGManager);
  87.  
  88. #ifdef MATERIAL_EFFECTS_DEBUG
  89.         SAFE_DELETE(m_pVisualDebug);
  90. #endif
  91. }
  92.  
  93. void CMaterialEffects::LoadFXLibraries()
  94. {
  95.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "MaterialEffects");
  96.  
  97.         m_mfxLibraries.clear();
  98.         m_effectContainers.clear();
  99.         m_effectContainers.push_back(0); // 0 -> invalid effect id
  100.  
  101.         ICryPak* pak = gEnv->pCryPak;
  102.         _finddata_t fd;
  103.  
  104.         stack_string searchPath;
  105.         searchPath.Format("%s/*.xml", MATERIAL_EFFECTS_LIBRARIES_FOLDER);
  106.         intptr_t handle = pak->FindFirst(searchPath.c_str(), &fd);
  107.         int res = 0;
  108.         if (handle != -1)
  109.         {
  110.                 do
  111.                 {
  112.                         LoadFXLibrary(fd.name);
  113.                         res = pak->FindNext(handle, &fd);
  114.                         SLICE_AND_SLEEP();
  115.                 }
  116.                 while (res >= 0);
  117.                 pak->FindClose(handle);
  118.         }
  119.  
  120.         m_canopySurfaceId = MaterialEffectsUtils::FindSurfaceIdByName(MATERIAL_EFFECTS_SURFACE_TYPE_CANOPY);
  121.  
  122.         // Notify external systems
  123.         for (TEffectsListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next())
  124.         {
  125.                 notifier->OnPostLoadFXLibraries();
  126.         }
  127. }
  128.  
  129. void CMaterialEffects::LoadFXLibrary(const char* name)
  130. {
  131.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Other, 0, "FX Library XML (%s)", name);
  132.  
  133.         string path = PathUtil::Make(MATERIAL_EFFECTS_LIBRARIES_FOLDER, name);
  134.         string fileName = name;
  135.  
  136.         int period = fileName.find(".");
  137.         string libName = fileName.substr(0, period);
  138.  
  139.         XmlNodeRef libraryRootNode = gEnv->pSystem->LoadXmlFromFile(path);
  140.         if (libraryRootNode != 0)
  141.         {
  142.                 TFXLibrariesMap::iterator libIter = m_mfxLibraries.find(libName);
  143.                 if (libIter != m_mfxLibraries.end())
  144.                 {
  145.                         GameWarning("[MatFX]: Library '%s' already exists, skipping library file loading '%s'", libName.c_str(), path.c_str());
  146.                         return;
  147.                 }
  148.  
  149.                 std::pair<TFXLibrariesMap::iterator, bool> iterPair = m_mfxLibraries.insert(TFXLibrariesMap::value_type(libName, CMFXLibrary()));
  150.                 assert(iterPair.second == true);
  151.                 libIter = iterPair.first;
  152.                 assert(libIter != m_mfxLibraries.end());
  153.  
  154.                 const TMFXNameId& libraryNameId = libIter->first; // uses CryString's ref-count feature
  155.                 CMFXLibrary& mfxLibrary = libIter->second;
  156.  
  157.                 CMFXLibrary::SLoadingEnvironment libraryLoadingEnvironment(libraryNameId, libraryRootNode, m_effectContainers);
  158.                 mfxLibrary.LoadFromXml(libraryLoadingEnvironment);
  159.         }
  160.         else
  161.         {
  162.                 GameWarning("[MatFX]: Failed to load library %s", path.c_str());
  163.         }
  164.  
  165. }
  166.  
  167. bool CMaterialEffects::ExecuteEffect(TMFXEffectId effectId, SMFXRunTimeEffectParams& params)
  168. {
  169.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
  170.  
  171.         if (!CMaterialEffectsCVars::Get().mfx_Enable)
  172.                 return false;
  173.  
  174.         bool success = false;
  175.         TMFXContainerPtr pEffectContainer = InternalGetEffect(effectId);
  176.         if (pEffectContainer)
  177.         {
  178.                 const float delay = pEffectContainer->GetParams().delay;
  179.                 if ((delay > 0.0f) && !(params.playflags & eMFXPF_Disable_Delay))
  180.                 {
  181.                         TimedEffect(pEffectContainer, params);
  182.                 }
  183.                 else
  184.                 {
  185.                         pEffectContainer->Execute(params);
  186.                 }
  187.                 success = true;
  188.  
  189. #ifdef MATERIAL_EFFECTS_DEBUG
  190.                 if (CMaterialEffectsCVars::Get().mfx_DebugVisual)
  191.                 {
  192.                         if (effectId != InvalidEffectId)
  193.                         {
  194.                                 m_pVisualDebug->AddEffectDebugVisual(effectId, params);
  195.                         }
  196.                 }
  197. #endif
  198.  
  199.         }
  200.  
  201.         return success;
  202. }
  203.  
  204. void CMaterialEffects::StopEffect(TMFXEffectId effectId)
  205. {
  206.         TMFXContainerPtr pEffectContainer = InternalGetEffect(effectId);
  207.         if (pEffectContainer)
  208.         {
  209.                 SMFXResourceListPtr resources = SMFXResourceList::Create();
  210.                 pEffectContainer->GetResources(*resources);
  211.  
  212.                 SMFXFlowGraphListNode* pNext = resources->m_flowGraphList;
  213.                 while (pNext)
  214.                 {
  215.                         GetFGManager()->EndFGEffect(pNext->m_flowGraphParams.name);
  216.                         pNext = pNext->pNext;
  217.                 }
  218.         }
  219. }
  220.  
  221. void CMaterialEffects::SetCustomParameter(TMFXEffectId effectId, const char* customParameter, const SMFXCustomParamValue& customParameterValue)
  222. {
  223.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
  224.  
  225.         if (!CMaterialEffectsCVars::Get().mfx_Enable)
  226.                 return;
  227.  
  228.         TMFXContainerPtr pEffect = InternalGetEffect(effectId);
  229.         if (pEffect)
  230.         {
  231.                 pEffect->SetCustomParameter(customParameter, customParameterValue);
  232.         }
  233. }
  234.  
  235. namespace
  236. {
  237. struct CConstCharArray
  238. {
  239.         const char* ptr;
  240.         size_t      count;
  241.         CConstCharArray()
  242.                 : ptr("")
  243.                 , count(0)
  244.         {
  245.         }
  246. };
  247.  
  248. struct less_CConstCharArray
  249. {
  250.         bool operator()(const CConstCharArray& s0, const CConstCharArray& s1) const
  251.         {
  252.                 const size_t minCount = (s0.count < s1.count) ? s0.count : s1.count;
  253.                 const int result = memicmp(s0.ptr, s1.ptr, minCount);
  254.                 return result ? (result < 0) : (s0.count < s1.count);
  255.         }
  256. };
  257.  
  258. void ToEffectString(const string& effectString, string& libName, string& effectName)
  259. {
  260.         size_t colon = effectString.find(':');
  261.         if (colon != string::npos)
  262.         {
  263.                 libName = effectString.substr(0, colon);
  264.                 effectName = effectString.substr(colon + 1, effectString.length() - colon - 1);
  265.         }
  266.         else
  267.         {
  268.                 libName = effectString;
  269.                 effectName = effectString;
  270.         }
  271. }
  272. }
  273.  
  274. void CMaterialEffects::LoadSpreadSheet()
  275. {
  276.         m_bDataInitialized = true;
  277.  
  278.         Reset(false);
  279.  
  280.         CryComment("[MFX] Init");
  281.  
  282.         IXmlTableReader* const pXmlTableReader = gEnv->pSystem->GetXmlUtils()->CreateXmlTableReader();
  283.         if (!pXmlTableReader)
  284.         {
  285.                 GameWarning("[MFX] XML system failure");
  286.                 return;
  287.         }
  288.  
  289.         // The root node.
  290.         XmlNodeRef root = gEnv->pSystem->LoadXmlFromFile(MATERIAL_EFFECTS_SPREADSHEET_FILE);
  291.         if (!root)
  292.         {
  293.                 // The file wasn't found, or the wrong file format was used
  294.                 GameWarning("[MFX] File not found or wrong file type: %s", MATERIAL_EFFECTS_SPREADSHEET_FILE);
  295.                 pXmlTableReader->Release();
  296.                 return;
  297.         }
  298.  
  299.         CryComment("[MFX] Loaded: %s", MATERIAL_EFFECTS_SPREADSHEET_FILE);
  300.  
  301.         if (!pXmlTableReader->Begin(root))
  302.         {
  303.                 GameWarning("[MFX] Table not found");
  304.                 pXmlTableReader->Release();
  305.                 return;
  306.         }
  307.  
  308.         // temporary multimap: we store effectstring -> [TIndexPairs]+ there
  309.         typedef std::vector<TIndexPair>                                        TIndexPairVec;
  310.         typedef std::map<CConstCharArray, TIndexPairVec, less_CConstCharArray> TEffectStringToIndexPairVecMap;
  311.         TEffectStringToIndexPairVecMap tmpEffectStringToIndexPairVecMap;
  312.  
  313.         int rowCount = 0;
  314.         int warningCount = 0;
  315.  
  316.         CConstCharArray cell;
  317.         string cellString; // temporary string
  318.  
  319.         // When we've gone down more rows than we have columns, we've entered special object space
  320.         int maxCol = 0;
  321.         std::vector<CConstCharArray> colOrder;
  322.         std::vector<CConstCharArray> rowOrder;
  323.  
  324.         m_surfaceIdToMatrixEntry.resize(0);
  325.         m_surfaceIdToMatrixEntry.resize(kMaxSurfaceCount, TIndex(0));
  326.         m_ptrToMatrixEntryMap.clear();
  327.         m_customConvert.clear();
  328.  
  329.         // Iterate through the table's rows
  330.         for (;; )
  331.         {
  332.                 int nRowIndex = -1;
  333.                 if (!pXmlTableReader->ReadRow(nRowIndex))
  334.                         break;
  335.  
  336.                 // Iterate through the row's columns
  337.                 for (;; )
  338.                 {
  339.                         int colIndex = -1;
  340.                         if (!pXmlTableReader->ReadCell(colIndex, cell.ptr, cell.count))
  341.                                 break;
  342.  
  343.                         if (cell.count <= 0)
  344.                                 continue;
  345.  
  346.                         cellString.assign(cell.ptr, cell.count);
  347.  
  348.                         if (rowCount == 0 && colIndex > 0)
  349.                         {
  350.                                 const int matId = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager()->GetSurfaceTypeByName(cellString.c_str(), "MFX", true)->GetId();
  351.                                 if (matId != 0 || /* matId == 0 && */ stricmp(cellString.c_str(), "mat_default") == 0) // if matId != 0 or it's the mat_default name
  352.                                 {
  353.                                         // CryLogAlways("[MFX] Material found: %s [ID=%d] [mapping to row/col=%d]", cellString.c_str(), matId, colCount);
  354.                                         if (m_surfaceIdToMatrixEntry.size() < matId)
  355.                                         {
  356.                                                 m_surfaceIdToMatrixEntry.resize(matId + 1);
  357.                                                 if (matId >= kMaxSurfaceCount)
  358.                                                 {
  359.                                                         assert(false && "MaterialEffects.cpp: SurfaceTypes exceeds 256. Reconsider implementation.");
  360.                                                         CryLogAlways("MaterialEffects.cpp: SurfaceTypes exceeds %d. Reconsider implementation.", kMaxSurfaceCount);
  361.                                                 }
  362.                                         }
  363.                                         m_surfaceIdToMatrixEntry[matId] = colIndex;
  364.                                 }
  365.                                 else
  366.                                 {
  367.                                         GameWarning("MFX WARNING: Material not found: %s", cellString.c_str());
  368.                                         ++warningCount;
  369.                                 }
  370.                                 colOrder.push_back(cell);
  371.                         }
  372.                         else if (rowCount > 0 && colIndex > 0)
  373.                         {
  374.                                 //CryLog("[MFX] Event found: %s", cellString.c_str());
  375.                                 tmpEffectStringToIndexPairVecMap[cell].push_back(TIndexPair(rowCount, colIndex));
  376.                         }
  377.                         else if (rowCount > maxCol && colIndex == 0)
  378.                         {
  379.                                 IEntityClass* pEntityClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(cellString.c_str());
  380.                                 //CryLog("[MFX] Object class ID: %d", (int)pEntityClass);
  381.                                 if (pEntityClass)
  382.                                 {
  383.                                         // CryComment("[MFX] Found EntityClass based entry: %s [mapping to row/col=%d]", cellString.c_str(), rowCount);
  384.                                         m_ptrToMatrixEntryMap[pEntityClass] = rowCount;
  385.                                 }
  386.                                 else
  387.                                 {
  388.                                         // CryComment("[MFX] Found Custom entry: %s [mapping to row/col=%d]", cellString.c_str(), rowCount);
  389.                                         cellString.MakeLower();
  390.                                         m_customConvert[cellString] = rowCount;
  391.                                         ++warningCount;
  392.                                 }
  393.                         }
  394.                         else if (rowCount > 0 && colIndex == 0)
  395.                         {
  396.                                 rowOrder.push_back(cell);
  397.                         }
  398.                         // Heavy-duty debug info
  399.                         //CryLog("[MFX] celldata = %s at (%d, %d) rowCount=%d colIndex=%d maxCol=%d", curCellData->getContent(), i, j, rowCount, colIndex, maxCol);
  400.  
  401.                         // Check if this is the furthest column we've seen thus far
  402.                         if (colIndex > maxCol)
  403.                                 maxCol = colIndex;
  404.  
  405.                         SLICE_AND_SLEEP();
  406.                 }
  407.                 // Increment row counter
  408.                 ++rowCount;
  409.         }
  410.  
  411.         // now postprocess the tmpEffectStringIndexPairVecMap and generate the m_matmatArray
  412.         {
  413.                 // create the matmat array.
  414.                 // +1, because index pairs are in range [1..rowCount][1..maxCol]
  415.                 m_surfacesLookupTable.Create(rowCount + 1, maxCol + 1);
  416.                 TEffectStringToIndexPairVecMap::const_iterator iter = tmpEffectStringToIndexPairVecMap.begin();
  417.                 TEffectStringToIndexPairVecMap::const_iterator iterEnd = tmpEffectStringToIndexPairVecMap.end();
  418.                 string libName;
  419.                 string effectName;
  420.                 string tmpString;
  421.                 while (iter != iterEnd)
  422.                 {
  423.                         // lookup effect
  424.                         tmpString.assign(iter->first.ptr, iter->first.count);
  425.                         ToEffectString(tmpString, libName, effectName);
  426.                         TMFXContainerPtr pEffectContainer = InternalGetEffect(libName, effectName);
  427.                         TMFXEffectId effectId = pEffectContainer ? pEffectContainer->GetParams().effectId : InvalidEffectId;
  428.                         TIndexPairVec::const_iterator vecIter = iter->second.begin();
  429.                         TIndexPairVec::const_iterator vecIterEnd = iter->second.end();
  430.                         while (vecIter != vecIterEnd)
  431.                         {
  432.                                 const TIndexPair& indexPair = *vecIter;
  433.                                 // CryLogAlways("[%d,%d]->%d '%s'", indexPair.first, indexPair.second, effectId, tmpString.c_str());
  434.                                 m_surfacesLookupTable(indexPair.first, indexPair.second) = effectId;
  435.                                 ++vecIter;
  436.                         }
  437.                         ++iter;
  438.                 }
  439.         }
  440.  
  441.         if (CMaterialEffectsCVars::Get().mfx_Debug > 0)
  442.         {
  443.                 CryLogAlways("[MFX] RowCount=%d MaxCol=%d (*=%d)", rowCount, maxCol, rowCount * maxCol);
  444.                 for (int y = 0; y < m_surfacesLookupTable.m_nRows; ++y)
  445.                 {
  446.                         for (int x = 0; x < m_surfacesLookupTable.m_nCols; ++x)
  447.                         {
  448.                                 TMFXEffectId idRowCol = m_surfacesLookupTable.GetValue(y, x, USHRT_MAX);
  449.                                 assert(idRowCol != USHRT_MAX);
  450.                                 TMFXContainerPtr pEffectRowCol = InternalGetEffect(idRowCol);
  451.                                 if (pEffectRowCol)
  452.                                 {
  453.                                         CryLogAlways("[%d,%d] -> %u '%s:%s'", y, x, idRowCol, pEffectRowCol->GetParams().libraryName.c_str(), pEffectRowCol->GetParams().name.c_str());
  454.                                         if (y < m_surfacesLookupTable.m_nCols)
  455.                                         {
  456.                                                 TMFXEffectId idColRow = m_surfacesLookupTable.GetValue(x, y, USHRT_MAX);
  457.                                                 assert(idColRow != USHRT_MAX);
  458.                                                 TMFXContainerPtr pEffectColRow = InternalGetEffect(idColRow);
  459.                                                 if (idRowCol != idColRow)
  460.                                                 {
  461.                                                         if (pEffectColRow)
  462.                                                         {
  463.                                                                 GameWarning("[MFX] Identity mismatch: ExcelRowCol %d:%d: %s:%s != %s:%s", y + 1, x + 1,
  464.                                                                             pEffectRowCol->GetParams().libraryName.c_str(), pEffectRowCol->GetParams().name.c_str(),
  465.                                                                             pEffectColRow->GetParams().libraryName.c_str(), pEffectColRow->GetParams().name.c_str());
  466.                                                         }
  467.                                                         else
  468.                                                         {
  469.                                                                 GameWarning("[MFX] Identity mismatch: ExcelRowCol %d:%d: %s:%s != [not found]", y + 1, x + 1,
  470.                                                                             pEffectRowCol->GetParams().libraryName.c_str(), pEffectRowCol->GetParams().name.c_str());
  471.                                                         }
  472.                                                 }
  473.                                         }
  474.                                 }
  475.                         }
  476.                 }
  477.         }
  478.  
  479.         // check that we have the same number of columns and rows
  480.         if (colOrder.size() > rowOrder.size())
  481.         {
  482.                 GameWarning("[MFX] Found %d Columns, but not enough rows specified (%d)", (int32)colOrder.size(), (int32)rowOrder.size());
  483.         }
  484.  
  485.         // check that column order matches row order
  486.         if (CMaterialEffectsCVars::Get().mfx_Debug > 0)
  487.         {
  488.                 string colName;
  489.                 string rowName;
  490.                 for (int i = 0; i < colOrder.size(); ++i)
  491.                 {
  492.                         colName.assign(colOrder[i].ptr, colOrder[i].count);
  493.                         if (i < rowOrder.size())
  494.                         {
  495.                                 rowName.assign(rowOrder[i].ptr, rowOrder[i].count);
  496.                         }
  497.                         else
  498.                         {
  499.                                 rowName.clear();
  500.                         }
  501.                         // CryLogAlways("ExcelColRow=%d col=%s row=%s", i+2, colName.c_str(), rowName.c_str());
  502.                         if (colName != rowName)
  503.                         {
  504.                                 GameWarning("ExcelColRow=%d: %s != %s", i + 2, colName.c_str(), rowName.c_str());
  505.                         }
  506.                 }
  507.         }
  508.  
  509.         pXmlTableReader->Release();
  510. }
  511.  
  512. void CMaterialEffects::PreLoadAssets()
  513. {
  514.         LOADING_TIME_PROFILE_SECTION;
  515.  
  516.         for (TMFXEffectId id = 0; id < m_effectContainers.size(); ++id)
  517.                 if (m_effectContainers[id])
  518.                         m_effectContainers[id]->PreLoadAssets();
  519.  
  520.         if (m_pMaterialFGManager)
  521.                 return m_pMaterialFGManager->PreLoad();
  522. }
  523.  
  524. bool CMaterialEffects::LoadFlowGraphLibs()
  525. {
  526.         if (m_pMaterialFGManager)
  527.                 return m_pMaterialFGManager->LoadLibs();
  528.         return false;
  529. }
  530.  
  531. TMFXEffectId CMaterialEffects::GetEffectIdByName(const char* libName, const char* effectName)
  532. {
  533.         if (!CMaterialEffectsCVars::Get().mfx_Enable)
  534.                 return InvalidEffectId;
  535.  
  536.         const TMFXContainerPtr pEffectContainer = InternalGetEffect(libName, effectName);
  537.         if (pEffectContainer)
  538.         {
  539.                 return pEffectContainer->GetParams().effectId;
  540.         }
  541.  
  542.         return InvalidEffectId;
  543. }
  544.  
  545. TMFXEffectId CMaterialEffects::GetEffectId(int surfaceIndex1, int surfaceIndex2)
  546. {
  547.         if (!CMaterialEffectsCVars::Get().mfx_Enable)
  548.                 return InvalidEffectId;
  549.  
  550.         // Map surface IDs to internal matmat indices
  551.         const TIndex idx1 = SurfaceIdToMatrixEntry(surfaceIndex1);
  552.         const TIndex idx2 = SurfaceIdToMatrixEntry(surfaceIndex2);
  553.  
  554. #ifdef MATERIAL_EFFECTS_DEBUG
  555.         TMFXEffectId effectId = InternalGetEffectId(idx1, idx2);
  556.  
  557.         if (CMaterialEffectsCVars::Get().mfx_DebugVisual)
  558.         {
  559.                 if (effectId != InvalidEffectId)
  560.                 {
  561.                         m_pVisualDebug->AddLastSearchHint(effectId, surfaceIndex1, surfaceIndex2);
  562.                 }
  563.         }
  564.  
  565.         return effectId;
  566. #else
  567.         return InternalGetEffectId(idx1, idx2);
  568. #endif
  569.  
  570. }
  571.  
  572. TMFXEffectId CMaterialEffects::GetEffectId(const char* customName, int surfaceIndex2)
  573. {
  574.         if (!CMaterialEffectsCVars::Get().mfx_Enable)
  575.                 return InvalidEffectId;
  576.  
  577.         const TIndex idx1 = stl::find_in_map(m_customConvert, CONST_TEMP_STRING(customName), 0);
  578.         const TIndex idx2 = SurfaceIdToMatrixEntry(surfaceIndex2);
  579.  
  580. #ifdef MATERIAL_EFFECTS_DEBUG
  581.         TMFXEffectId effectId = InternalGetEffectId(idx1, idx2);
  582.  
  583.         if (CMaterialEffectsCVars::Get().mfx_DebugVisual)
  584.         {
  585.                 if (effectId != InvalidEffectId)
  586.                 {
  587.                         m_pVisualDebug->AddLastSearchHint(effectId, customName, surfaceIndex2);
  588.                 }
  589.         }
  590.  
  591.         return effectId;
  592. #else
  593.         return InternalGetEffectId(idx1, idx2);
  594. #endif
  595.  
  596. }
  597.  
  598. // Get the cell contents that these parameters equate to
  599. TMFXEffectId CMaterialEffects::GetEffectId(IEntityClass* pEntityClass, int surfaceIndex2)
  600. {
  601.         if (!CMaterialEffectsCVars::Get().mfx_Enable)
  602.                 return InvalidEffectId;
  603.  
  604.         // Map material IDs to effect indexes
  605.         const TIndex idx1 = stl::find_in_map(m_ptrToMatrixEntryMap, pEntityClass, 0);
  606.         const TIndex idx2 = SurfaceIdToMatrixEntry(surfaceIndex2);
  607.  
  608. #ifdef MATERIAL_EFFECTS_DEBUG
  609.         TMFXEffectId effectId = InternalGetEffectId(idx1, idx2);
  610.  
  611.         if (CMaterialEffectsCVars::Get().mfx_DebugVisual)
  612.         {
  613.                 if (effectId != InvalidEffectId)
  614.                 {
  615.                         m_pVisualDebug->AddLastSearchHint(effectId, pEntityClass, surfaceIndex2);
  616.                 }
  617.         }
  618.  
  619.         return effectId;
  620. #else
  621.         return InternalGetEffectId(idx1, idx2);
  622. #endif
  623.  
  624. }
  625.  
  626. SMFXResourceListPtr CMaterialEffects::GetResources(TMFXEffectId effectId) const
  627. {
  628.         SMFXResourceListPtr pResourceList = SMFXResourceList::Create();
  629.  
  630.         TMFXContainerPtr pEffectContainer = InternalGetEffect(effectId);
  631.         if (pEffectContainer)
  632.         {
  633.                 pEffectContainer->GetResources(*pResourceList);
  634.         }
  635.  
  636.         return pResourceList;
  637. }
  638.  
  639. void CMaterialEffects::TimedEffect(TMFXContainerPtr pEffectContainer, const SMFXRunTimeEffectParams& params)
  640. {
  641.         if (!m_bUpdateMode)
  642.                 return;
  643.  
  644.         m_delayedEffects.push_back(SDelayedEffect(pEffectContainer, params));
  645. }
  646.  
  647. void CMaterialEffects::SetUpdateMode(bool bUpdate)
  648. {
  649.         if (!bUpdate)
  650.         {
  651.                 m_delayedEffects.clear();
  652.                 m_pMaterialFGManager->Reset(false);
  653.         }
  654.  
  655.         m_bUpdateMode = bUpdate;
  656. }
  657.  
  658. void CMaterialEffects::FullReload()
  659. {
  660.         Reset(true);
  661.  
  662.         LoadFXLibraries();
  663.         LoadSpreadSheet();
  664.         LoadFlowGraphLibs();
  665. }
  666.  
  667. void CMaterialEffects::Update(float frameTime)
  668. {
  669.         SetUpdateMode(true);
  670.         std::vector<SDelayedEffect>::iterator it = m_delayedEffects.begin();
  671.         std::vector<SDelayedEffect>::iterator next = it;
  672.         while (it != m_delayedEffects.end())
  673.         {
  674.                 ++next;
  675.                 SDelayedEffect& cur = *it;
  676.                 cur.m_delay -= frameTime;
  677.                 if (cur.m_delay <= 0.0f)
  678.                 {
  679.                         cur.m_pEffectContainer->Execute(cur.m_effectRuntimeParams);
  680.                         next = m_delayedEffects.erase(it);
  681.                 }
  682.                 it = next;
  683.         }
  684.  
  685. #ifdef MATERIAL_EFFECTS_DEBUG
  686.         if (CMaterialEffectsCVars::Get().mfx_DebugVisual)
  687.         {
  688.                 m_pVisualDebug->Update(*this, frameTime);
  689.         }
  690. #endif
  691. }
  692.  
  693. void CMaterialEffects::NotifyFGHudEffectEnd(IFlowGraphPtr pFG)
  694. {
  695.         if (m_pMaterialFGManager)
  696.                 m_pMaterialFGManager->EndFGEffect(pFG);
  697. }
  698.  
  699. void CMaterialEffects::Reset(bool bCleanup)
  700. {
  701.         // make sure all pre load data has been propperly released to not have any
  702.         // dangling pointers are for example the materials itself have been flushed
  703.         for (TMFXEffectId id = 0; id < m_effectContainers.size(); ++id)
  704.         {
  705.                 if (m_effectContainers[id])
  706.                 {
  707.                         m_effectContainers[id]->ReleasePreLoadAssets();
  708.                 }
  709.         }
  710.  
  711.         if (m_pMaterialFGManager)
  712.                 m_pMaterialFGManager->Reset(bCleanup);
  713.  
  714.         if (bCleanup)
  715.         {
  716.                 stl::free_container(m_mfxLibraries);
  717.                 stl::free_container(m_delayedEffects);
  718.                 stl::free_container(m_effectContainers);
  719.                 stl::free_container(m_customConvert);
  720.                 stl::free_container(m_surfaceIdToMatrixEntry);
  721.                 stl::free_container(m_ptrToMatrixEntryMap);
  722.                 m_surfacesLookupTable.Free();
  723.                 m_bDataInitialized = false;
  724.  
  725.                 SMFXResourceList::FreePool();
  726.                 SMFXFlowGraphListNode::FreePool();
  727.                 SMFXDecalListNode::FreePool();
  728.                 SMFXParticleListNode::FreePool();
  729.                 SMFXAudioListNode::FreePool();
  730.                 SMFXForceFeedbackListNode::FreePool();
  731.         }
  732. }
  733.  
  734. void CMaterialEffects::ClearDelayedEffects()
  735. {
  736.         m_delayedEffects.resize(0);
  737. }
  738.  
  739. void CMaterialEffects::Serialize(TSerialize ser)
  740. {
  741.         if (m_pMaterialFGManager && CMaterialEffectsCVars::Get().mfx_SerializeFGEffects != 0)
  742.                 m_pMaterialFGManager->Serialize(ser);
  743. }
  744.  
  745. void CMaterialEffects::GetMemoryUsage(ICrySizer* s) const
  746. {
  747.         SIZER_SUBCOMPONENT_NAME(s, "MaterialEffects");
  748.         s->AddObject(this, sizeof(*this));
  749.         s->AddObject(m_pMaterialFGManager);
  750.  
  751.         {
  752.                 SIZER_SUBCOMPONENT_NAME(s, "libs");
  753.                 s->AddObject(m_mfxLibraries);
  754.         }
  755.         {
  756.                 SIZER_SUBCOMPONENT_NAME(s, "convert");
  757.                 s->AddObject(m_customConvert);
  758.                 s->AddObject(m_surfaceIdToMatrixEntry);
  759.                 s->AddObject(m_ptrToMatrixEntryMap);
  760.         }
  761.         {
  762.                 SIZER_SUBCOMPONENT_NAME(s, "lookup");
  763.                 s->AddObject(m_effectContainers); // the effects themselves already accounted in "libs"
  764.                 s->AddObject(m_surfacesLookupTable);
  765.         }
  766.         {
  767.                 SIZER_SUBCOMPONENT_NAME(s, "playing");
  768.                 s->AddObject(m_delayedEffects); // the effects themselves already accounted in "libs"
  769.                 //s->AddObject((const void*)&CMFXRandomEffect::GetMemoryUsage, CMFXRandomEffect::GetMemoryUsage());
  770.         }
  771. }
  772.  
  773. static float NormalizeMass(float fMass)
  774. {
  775.         float massMin = 0.0f;
  776.         float massMax = 500.0f;
  777.         float paramMin = 0.0f;
  778.         float paramMax = 1.0f / 3.0f;
  779.  
  780.         // tiny - bullets
  781.         if (fMass <= 0.1f)
  782.         {
  783.                 // small
  784.                 massMin = 0.0f;
  785.                 massMax = 0.1f;
  786.                 paramMin = 0.0f;
  787.                 paramMax = 1.0f;
  788.         }
  789.         else if (fMass < 20.0f)
  790.         {
  791.                 // small
  792.                 massMin = 0.0f;
  793.                 massMax = 20.0f;
  794.                 paramMin = 0.0f;
  795.                 paramMax = 1.0f / 3.0f;
  796.         }
  797.         else if (fMass < 200.0f)
  798.         {
  799.                 // medium
  800.                 massMin = 20.0f;
  801.                 massMax = 200.0f;
  802.                 paramMin = 1.0f / 3.0f;
  803.                 paramMax = 2.0f / 3.0f;
  804.         }
  805.         else
  806.         {
  807.                 // ultra large
  808.                 massMin = 200.0f;
  809.                 massMax = 2000.0f;
  810.                 paramMin = 2.0f / 3.0f;
  811.                 paramMax = 1.0f;
  812.         }
  813.  
  814.         const float p = min(1.0f, (fMass - massMin) / (massMax - massMin));
  815.         const float finalParam = paramMin + (p * (paramMax - paramMin));
  816.         return finalParam;
  817. }
  818.  
  819. bool CMaterialEffects::PlayBreakageEffect(ISurfaceType* pSurfaceType, const char* breakageType, const SMFXBreakageParams& breakageParams)
  820. {
  821.         if (pSurfaceType == 0)
  822.                 return false;
  823.  
  824.         CryFixedStringT<128> fxName("Breakage:");
  825.         fxName += breakageType;
  826.         TMFXEffectId effectId = this->GetEffectId(fxName.c_str(), pSurfaceType->GetId());
  827.         if (effectId == InvalidEffectId)
  828.                 return false;
  829.  
  830.         // only play sound at the moment
  831.         SMFXRunTimeEffectParams params;
  832.         params.playflags = eMFXPF_Audio;
  833.  
  834.         // if hitpos is set, use it
  835.         // otherwise use matrix (hopefully been set or 0,0,0)
  836.         if (breakageParams.CheckFlag(SMFXBreakageParams::eBRF_HitPos) && breakageParams.GetHitPos().IsZero() == false)
  837.                 params.pos = breakageParams.GetHitPos();
  838.         else
  839.                 params.pos = breakageParams.GetMatrix().GetTranslation();
  840.  
  841.         //params.soundSemantic = eSoundSemantic_Physics_General;
  842.  
  843.         const Vec3& hitImpulse = breakageParams.GetHitImpulse();
  844.         const float strength = hitImpulse.GetLengthFast();
  845.         params.AddAudioRtpc("strength", strength);
  846.         const float mass = NormalizeMass(breakageParams.GetMass());
  847.         params.AddAudioRtpc("mass", mass);
  848.  
  849.         if (CMaterialEffectsCVars::Get().mfx_Debug & 2)
  850.         {
  851.                 TMFXContainerPtr pEffectContainer = InternalGetEffect(effectId);
  852.                 if (pEffectContainer != NULL)
  853.                 {
  854.                         CryLogAlways("[MFX]: %s:%s FX=%s:%s Pos=%f,%f,%f NormMass=%f  F=%f Imp=%f,%f,%f  RealMass=%f Vel=%f,%f,%f",
  855.                                      breakageType, pSurfaceType->GetName(), pEffectContainer->GetParams().libraryName.c_str(), pEffectContainer->GetParams().name.c_str(),
  856.                                      params.pos[0], params.pos[1], params.pos[2],
  857.                                      mass,
  858.                                      strength,
  859.                                      breakageParams.GetHitImpulse()[0],
  860.                                      breakageParams.GetHitImpulse()[1],
  861.                                      breakageParams.GetHitImpulse()[2],
  862.                                      breakageParams.GetMass(),
  863.                                      breakageParams.GetVelocity()[0],
  864.                                      breakageParams.GetVelocity()[1],
  865.                                      breakageParams.GetVelocity()[2]
  866.                                      );
  867.                 }
  868.         }
  869.  
  870.         /*
  871.            if (breakageParams.GetMass() == 0.0f)
  872.            {
  873.            int a = 0;
  874.            }
  875.          */
  876.  
  877.         const bool bSuccess = ExecuteEffect(effectId, params);
  878.  
  879.         return bSuccess;
  880. }
  881.  
  882. void CMaterialEffects::CompleteInit()
  883. {
  884.         if (m_bDataInitialized)
  885.                 return;
  886.  
  887.         LoadFXLibraries();
  888.         LoadSpreadSheet();
  889.         LoadFlowGraphLibs();
  890. }
  891.  
  892. int CMaterialEffects::GetDefaultCanopyIndex()
  893. {
  894. #ifdef MATERIAL_EFFECTS_DEBUG
  895.         if (m_defaultSurfaceId == m_canopySurfaceId)
  896.         {
  897.                 GameWarning("[MFX] CMaterialEffects::GetDefaultCanopyIndex returning default - called before MFX loaded");
  898.         }
  899. #endif
  900.  
  901.         return m_canopySurfaceId;
  902. }
  903.  
  904. void CMaterialEffects::ReloadMatFXFlowGraphs()
  905. {
  906.         m_pMaterialFGManager->ReloadFlowGraphs();
  907. }
  908.  
  909. int CMaterialEffects::GetMatFXFlowGraphCount() const
  910. {
  911.         return m_pMaterialFGManager->GetFlowGraphCount();
  912. }
  913.  
  914. IFlowGraphPtr CMaterialEffects::GetMatFXFlowGraph(int index, string* pFileName /*= NULL*/) const
  915. {
  916.         return m_pMaterialFGManager->GetFlowGraph(index, pFileName);
  917. }
  918.  
  919. IFlowGraphPtr CMaterialEffects::LoadNewMatFXFlowGraph(const string& filename)
  920. {
  921.         IFlowGraphPtr res;
  922.         m_pMaterialFGManager->LoadFG(filename, &res);
  923.         return res;
  924. }
  925.  
  926. void CMaterialEffects::EnumerateEffectNames(EnumerateMaterialEffectsDataCallback& callback, const char* szLibraryName) const
  927. {
  928.         TFXLibrariesMap::const_iterator pLibraryIter = m_mfxLibraries.find(szLibraryName);
  929.         if (pLibraryIter != m_mfxLibraries.end())
  930.         {
  931.                 CMFXLibrary::TEffectNames effectNames;
  932.                 pLibraryIter->second.GetEffectNames(effectNames);
  933.                 for (const string& curEntry : effectNames)
  934.                 {
  935.                         callback(curEntry);
  936.                 }
  937.         }
  938. }
  939.  
  940. void CMaterialEffects::EnumerateLibraryNames(EnumerateMaterialEffectsDataCallback& callback) const
  941. {
  942.         for (const auto& entry : m_mfxLibraries)
  943.         {
  944.                 callback(entry.first.c_str());
  945.         }
  946. }
  947. void CMaterialEffects::UnloadFXLibrariesWithPrefix(const char* szName)
  948. {
  949.         for (TFXLibrariesMap::iterator library = m_mfxLibraries.begin(); library != m_mfxLibraries.end(); )
  950.         {
  951.                 if (library->first.find(szName) != string::npos)
  952.                 {
  953.                         library = m_mfxLibraries.erase(library);
  954.                 }
  955.                 else
  956.                 {
  957.                         ++library;
  958.                 }
  959.         }
  960. }
  961.  
  962. void CMaterialEffects::LoadFXLibraryFromXMLInMemory(const char* szName, XmlNodeRef root)
  963. {
  964.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Other, 0, "FX Library XML (%s)", szName);
  965.  
  966.         const string libName = szName;
  967.  
  968.         XmlNodeRef libraryRootNode = root;
  969.         if (libraryRootNode != 0)
  970.         {
  971.                 TFXLibrariesMap::iterator libIter = m_mfxLibraries.find(libName);
  972.                 if (libIter != m_mfxLibraries.end())
  973.                 {
  974.                         m_mfxLibraries.erase(libIter);
  975.                 }
  976.  
  977.                 std::pair<TFXLibrariesMap::iterator, bool> iterPair = m_mfxLibraries.insert(TFXLibrariesMap::value_type(libName, CMFXLibrary()));
  978.                 assert(iterPair.second == true);
  979.                 libIter = iterPair.first;
  980.                 assert(libIter != m_mfxLibraries.end());
  981.  
  982.                 const TMFXNameId& libraryNameId = libIter->first; // uses CryString's ref-count feature
  983.                 CMFXLibrary& mfxLibrary = libIter->second;
  984.  
  985.                 CMFXLibrary::SLoadingEnvironment libraryLoadingEnvironment(libraryNameId, libraryRootNode, m_effectContainers);
  986.                 mfxLibrary.LoadFromXml(libraryLoadingEnvironment);
  987.         }
  988.         else
  989.         {
  990.                 GameWarning("[MatFX]: Failed to load library %s", libName.c_str());
  991.         }
  992. }
  993.  
downloadMaterialEffects.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