BVB Source Codes

CRYENGINE Show FlowSystem.cpp Source code

Return Download CRYENGINE: download FlowSystem.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4.  
  5. #include "FlowSystem.h"
  6.  
  7. #include <CryAction.h>
  8. #include <CryFlowGraph/IFlowBaseNode.h>
  9.  
  10. #include "FlowGraph.h"
  11. #include "Nodes/FlowLogNode.h"
  12. #include "Nodes/FlowStartNode.h"
  13. #include "Nodes/FlowTrackEventNode.h"
  14. #include "Nodes/FlowDelayNode.h"
  15.  
  16. #include "Nodes/FlowScriptedNode.h"
  17. #include "Nodes/FlowCompositeNode.h"
  18. #include "Nodes/FlowEntityNode.h"
  19.  
  20. #include "Inspectors/FlowInspectorDefault.h"
  21. #include "Modules/ModuleManager.h"
  22.  
  23. #include "PersistantDebug.h"
  24. #include "AnimationGraph/DebugHistory.h"
  25. #include <CrySystem/ITimer.h>
  26. #include "TimeOfDayScheduler.h"
  27.  
  28. #include <CryString/CryPath.h>
  29.  
  30. #define BLACKLIST_FILE_PATH     "Libs/FlowNodes/FlownodeBlacklist.xml"
  31.  
  32. #define GRAPH_RESERVED_CAPACITY 8
  33.  
  34. #ifndef _RELEASE
  35.         #define SHOW_FG_CRITICAL_LOADING_ERROR_ON_SCREEN
  36. #endif
  37.  
  38. #ifndef _RELEASE
  39. CFlowSystem::TSFGProfile CFlowSystem::FGProfile;
  40. #endif //_RELEASE
  41.  
  42. //////////////////////////////////////////////////////////////////////////
  43. // CAutoFlowNodeFactoryBase
  44. //////////////////////////////////////////////////////////////////////////
  45. CAutoRegFlowNodeBase* CAutoRegFlowNodeBase::m_pFirst = nullptr;
  46. CAutoRegFlowNodeBase* CAutoRegFlowNodeBase::m_pLast = nullptr;
  47. //////////////////////////////////////////////////////////////////////////
  48.  
  49. template<class T>
  50. class CAutoFlowFactory : public IFlowNodeFactory
  51. {
  52. public:
  53.         CAutoFlowFactory() : m_refs(0) {}
  54.         void         AddRef()                                     { m_refs++; }
  55.         void         Release()                                    { if (0 == --m_refs) delete this; }
  56.         IFlowNodePtr Create(IFlowNode::SActivationInfo* pActInfo) { return new T(pActInfo); }
  57.         void         GetMemoryUsage(ICrySizer* s) const
  58.         {
  59.                 SIZER_SUBCOMPONENT_NAME(s, "CAutoFlowFactory");
  60.                 s->Add(*this);
  61.         }
  62.  
  63.         void Reset() {}
  64.  
  65. private:
  66.         int m_refs;
  67. };
  68.  
  69. template<class T>
  70. class CSingletonFlowFactory : public IFlowNodeFactory
  71. {
  72. public:
  73.         CSingletonFlowFactory() : m_refs(0) { m_pInstance = new T(); }
  74.         void AddRef()  { m_refs++; }
  75.         void Release() { if (0 == --m_refs) delete this; }
  76.         void GetMemoryUsage(ICrySizer* s) const
  77.         {
  78.                 SIZER_SUBCOMPONENT_NAME(s, "CSingletonFlowFactory");
  79.                 s->Add(*this);
  80.                 s->AddObject(m_pInstance);
  81.         }
  82.         IFlowNodePtr Create(IFlowNode::SActivationInfo* pActInfo)
  83.         {
  84.                 return m_pInstance;
  85.         }
  86.  
  87.         void Reset() {}
  88.  
  89. private:
  90.         IFlowNodePtr m_pInstance;
  91.         int          m_refs;
  92. };
  93.  
  94. // FlowSystem Container
  95. void CFlowSystemContainer::AddItem(TFlowInputData item)
  96. {
  97.         m_container.push_back(item);
  98. }
  99.  
  100. void CFlowSystemContainer::AddItemUnique(TFlowInputData item)
  101. {
  102.         if (std::find(m_container.begin(), m_container.end(), item) != m_container.end())
  103.         {
  104.                 m_container.push_back(item);
  105.         }
  106. }
  107.  
  108. void CFlowSystemContainer::RemoveItem(TFlowInputData item)
  109. {
  110.         m_container.erase(std::remove(m_container.begin(), m_container.end(), item), m_container.end());
  111. }
  112.  
  113. TFlowInputData CFlowSystemContainer::GetItem(int i)
  114. {
  115.         return m_container[i];
  116. }
  117.  
  118. void CFlowSystemContainer::RemoveItemAt(int i)
  119. {
  120.         m_container.erase(m_container.begin() + i);
  121. }
  122.  
  123. void CFlowSystemContainer::Clear()
  124. {
  125.         m_container.clear();
  126. }
  127.  
  128. int CFlowSystemContainer::GetItemCount() const
  129. {
  130.         return m_container.size();
  131. }
  132.  
  133. void CFlowSystemContainer::GetMemoryUsage(ICrySizer* s) const
  134. {
  135.         if (GetItemCount() > 0)
  136.                 s->Add(&m_container[0], m_container.capacity());
  137.  
  138.         s->Add(m_container);
  139. }
  140.  
  141. void CFlowSystemContainer::Serialize(TSerialize ser)
  142. {
  143.         int count = m_container.size();
  144.  
  145.         ser.Value("count", count);
  146.  
  147.         if (ser.IsWriting())
  148.         {
  149.                 for (int i = 0; i < count; i++)
  150.                 {
  151.                         ser.BeginGroup("ContainerInfo");
  152.                         m_container[i].Serialize(ser);
  153.                         ser.EndGroup();
  154.                 }
  155.         }
  156.         else
  157.         {
  158.                 for (int i = 0; i < count; i++)
  159.                 {
  160.                         ser.BeginGroup("ContainerInfo");
  161.                         TFlowInputData data;
  162.                         data.Serialize(ser);
  163.                         m_container.push_back(data);
  164.                         ser.EndGroup();
  165.                 }
  166.         }
  167. }
  168.  
  169. CFlowSystem::CFlowSystem()
  170.         : m_bInspectingEnabled(false)
  171.         , m_needToUpdateForwardings(false)
  172.         , m_criticalLoadingErrorHappened(false)
  173.         , m_graphs(GRAPH_RESERVED_CAPACITY)
  174.         , m_nextFlowGraphId(0)
  175.         , m_pModuleManager(NULL)
  176.         , m_blacklistNode(NULL)
  177.         , m_nextNodeTypeID(InvalidFlowNodeTypeId)
  178.         , m_bRegisteredDefaultNodes(false)
  179. {
  180.         LoadBlacklistedFlownodeXML();
  181. }
  182.  
  183. void CFlowSystem::PreInit()
  184. {
  185.         m_pModuleManager = new CFlowGraphModuleManager();
  186.         RegisterAllNodeTypes();
  187.  
  188.         m_pDefaultInspector = new CFlowInspectorDefault(this);
  189.         RegisterInspector(m_pDefaultInspector, 0);
  190.         EnableInspecting(false);
  191. }
  192.  
  193. CFlowSystem::~CFlowSystem()
  194. {
  195.         for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  196.         {
  197.                 itGraph->NotifyFlowSystemDestroyed();
  198.         }
  199. }
  200.  
  201. void CFlowSystem::Release()
  202. {
  203.         UnregisterInspector(m_pDefaultInspector, 0);
  204.         delete this;
  205. }
  206.  
  207. IFlowGraphPtr CFlowSystem::CreateFlowGraph()
  208. {
  209.         return new CFlowGraph(this);
  210. }
  211.  
  212. //////////////////////////////////////////////////////////////////////////
  213. void CFlowSystem::ReloadAllNodeTypes()
  214. {
  215.         if (gEnv->IsEditor())
  216.         {
  217.                 RegisterAllNodeTypes();
  218.         }
  219. }
  220.  
  221. //////////////////////////////////////////////////////////////////////////
  222. void CFlowSystem::RegisterAllNodeTypes()
  223. {
  224.         // clear node types
  225.         m_typeNameToIdMap.clear();
  226.         m_typeRegistryVec.clear();
  227.  
  228.         // reset TypeIDs
  229.         m_freeNodeTypeIDs.clear();
  230.         m_nextNodeTypeID = InvalidFlowNodeTypeId;
  231.  
  232.         // register all types
  233.         TFlowNodeTypeId typeId = RegisterType("InvalidType", 0);
  234.         assert(typeId == InvalidFlowNodeTypeId);
  235.         RegisterType("Debug:Log", new CSingletonFlowFactory<CFlowLogNode>());
  236.         RegisterType("Game:Start", new CAutoFlowFactory<CFlowStartNode>());
  237.         RegisterType("TrackEvent", new CAutoFlowFactory<CFlowTrackEventNode>());
  238.  
  239.         RegisterAutoTypes();
  240.  
  241.         LoadExtensions("Libs/FlowNodes");
  242.  
  243.         gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_REGISTER_FLOWNODES, 0, 0);
  244.  
  245.         // register entity type flownodes after the game
  246.         RegisterEntityTypes();
  247.  
  248.         // this has to come after all other nodes are reloaded
  249.         // as it will trigger the editor to reload the fg classes!
  250.         GetModuleManager()->ScanForModules(); // reload all modules (since they need to register the start and end node types)
  251.  
  252.         m_bRegisteredDefaultNodes = true;
  253. }
  254.  
  255. void CFlowSystem::LoadExtensions(string path)
  256. {
  257.         ICryPak* pCryPak = gEnv->pCryPak;
  258.         _finddata_t fd;
  259.         char filename[_MAX_PATH];
  260.  
  261.         path.TrimRight("/\\");
  262.         string search = path + "/*.node";
  263.         intptr_t handle = pCryPak->FindFirst(search.c_str(), &fd);
  264.         if (handle != -1)
  265.         {
  266.                 int res = 0;
  267.  
  268.                 TPendingComposites pendingComposites;
  269.  
  270.                 do
  271.                 {
  272.                         cry_strcpy(filename, path.c_str());
  273.                         cry_strcat(filename, "/");
  274.                         cry_strcat(filename, fd.name);
  275.  
  276.                         XmlNodeRef root = GetISystem()->LoadXmlFromFile(filename);
  277.                         if (root)
  278.                                 LoadExtensionFromXml(root, &pendingComposites);
  279.  
  280.                         res = pCryPak->FindNext(handle, &fd);
  281.                 }
  282.                 while (res >= 0);
  283.  
  284.                 LoadComposites(&pendingComposites);
  285.  
  286.                 pCryPak->FindClose(handle);
  287.         }
  288. }
  289.  
  290. void CFlowSystem::LoadExtensionFromXml(XmlNodeRef nodeParent, TPendingComposites* pComposites)
  291. {
  292.         XmlNodeRef node;
  293.         int nChildren = nodeParent->getChildCount();
  294.         int iChild;
  295.  
  296.         // run for nodeParent, and any children it contains
  297.         for (iChild = -1, node = nodeParent;; )
  298.         {
  299.                 const char* tag = node->getTag();
  300.                 if (!tag || !*tag)
  301.                         return;
  302.  
  303.                 // Multiple components may be contained within a <NodeList> </NodeList> pair
  304.                 if ((0 == strcmp("NodeList", tag)) || (0 == strcmp("/NodeList", tag)))
  305.                 {
  306.                         // a list node, do nothing.
  307.                         // if root level, will advance to child below
  308.                 }
  309.                 else
  310.                 {
  311.                         const char* name = node->getAttr("name");
  312.                         if (!name || !*name)
  313.                                 return;
  314.  
  315.                         if (0 == strcmp("Script", tag))
  316.                         {
  317.                                 const char* path = node->getAttr("script");
  318.                                 if (!path || !*path)
  319.                                         return;
  320.                                 CFlowScriptedNodeFactoryPtr pFactory = new CFlowScriptedNodeFactory();
  321.                                 if (pFactory->Init(path, name))
  322.                                         RegisterType(name, &*pFactory);
  323.                         }
  324.                         else if (0 == strcmp("SimpleScript", tag))
  325.                         {
  326.                                 const char* path = node->getAttr("script");
  327.                                 if (!path || !*path)
  328.                                         return;
  329.                                 CFlowSimpleScriptedNodeFactoryPtr pFactory = new CFlowSimpleScriptedNodeFactory();
  330.                                 if (pFactory->Init(path, name))
  331.                                         RegisterType(name, &*pFactory);
  332.                         }
  333.                         else if (0 == strcmp("Composite", tag))
  334.                         {
  335.                                 pComposites->push(node);
  336.                         }
  337.                 }
  338.  
  339.                 if (++iChild >= nChildren)
  340.                         break;
  341.                 node = nodeParent->getChild(iChild);
  342.         }
  343. }
  344.  
  345. void CFlowSystem::LoadComposites(TPendingComposites* pComposites)
  346. {
  347.         size_t failCount = 0;
  348.         while (!pComposites->empty() && failCount < pComposites->size())
  349.         {
  350.                 CFlowCompositeNodeFactoryPtr pFactory = new CFlowCompositeNodeFactory();
  351.                 switch (pFactory->Init(pComposites->front(), this))
  352.                 {
  353.                 case CFlowCompositeNodeFactory::eIR_Failed:
  354.                         GameWarning("Failed to load composite due to invalid data: %s", pComposites->front()->getAttr("name"));
  355.                         pComposites->pop();
  356.                         failCount = 0;
  357.                         break;
  358.                 case CFlowCompositeNodeFactory::eIR_Ok:
  359.                         RegisterType(pComposites->front()->getAttr("name"), &*pFactory);
  360.                         pComposites->pop();
  361.                         failCount = 0;
  362.                         break;
  363.                 case CFlowCompositeNodeFactory::eIR_NotYet:
  364.                         pComposites->push(pComposites->front());
  365.                         pComposites->pop();
  366.                         failCount++;
  367.                         break;
  368.                 }
  369.         }
  370.  
  371.         while (!pComposites->empty())
  372.         {
  373.                 GameWarning("Failed to load composite due to failed dependency: %s", pComposites->front()->getAttr("name"));
  374.                 pComposites->pop();
  375.         }
  376. }
  377.  
  378. class CFlowSystem::CNodeTypeIterator : public IFlowNodeTypeIterator
  379. {
  380. public:
  381.         CNodeTypeIterator(CFlowSystem* pImpl) : m_nRefs(0), m_pImpl(pImpl), m_iter(pImpl->m_typeRegistryVec.begin())
  382.         {
  383.                 assert(m_iter != m_pImpl->m_typeRegistryVec.end());
  384.                 ++m_iter;
  385.                 m_id = InvalidFlowNodeTypeId;
  386.                 assert(m_id == 0);
  387.         }
  388.         void AddRef()
  389.         {
  390.                 ++m_nRefs;
  391.         }
  392.         void Release()
  393.         {
  394.                 if (0 == --m_nRefs)
  395.                         delete this;
  396.         }
  397.         bool Next(SNodeType& nodeType)
  398.         {
  399.                 while (m_iter != m_pImpl->m_typeRegistryVec.end() && !stricmp(m_iter->name, ""))
  400.                 {
  401.                         ++m_id;
  402.                         ++m_iter;
  403.                 }
  404.  
  405.                 if (m_iter == m_pImpl->m_typeRegistryVec.end())
  406.                         return false;
  407.  
  408.                 nodeType.typeId = ++m_id;
  409.                 nodeType.typeName = m_iter->name;
  410.                 ++m_iter;
  411.                 return true;
  412.         }
  413. private:
  414.         int                              m_nRefs;
  415.         TFlowNodeTypeId                  m_id;
  416.         CFlowSystem*                     m_pImpl;
  417.         std::vector<STypeInfo>::iterator m_iter;
  418. };
  419.  
  420. IFlowNodeTypeIteratorPtr CFlowSystem::CreateNodeTypeIterator()
  421. {
  422.         return new CNodeTypeIterator(this);
  423. }
  424.  
  425. TFlowNodeTypeId CFlowSystem::GenerateNodeTypeID()
  426. {
  427.         if (!m_freeNodeTypeIDs.empty())
  428.         {
  429.                 TFlowNodeTypeId typeID = m_freeNodeTypeIDs.back();
  430.                 m_freeNodeTypeIDs.pop_back();
  431.                 return typeID;
  432.         }
  433.  
  434.         if (m_nextNodeTypeID > CFlowData::TYPE_MAX_COUNT)
  435.         {
  436.                 CryWarning(VALIDATOR_MODULE_FLOWGRAPH, VALIDATOR_ERROR, "CFlowSystem::GenerateNodeTypeID: Reached maximum amount of NodeTypes: Limit=%d", CFlowData::TYPE_MAX_COUNT);
  437.                 return InvalidFlowNodeTypeId;
  438.         }
  439.  
  440.         return m_nextNodeTypeID++;
  441. }
  442.  
  443. TFlowNodeTypeId CFlowSystem::RegisterType(const char* type, IFlowNodeFactoryPtr factory)
  444. {
  445.         if (!BlacklistedFlownode(&type))
  446.                 return InvalidFlowNodeTypeId;
  447.  
  448.         string typeName = type;
  449.         const TTypeNameToIdMap::const_iterator iter = m_typeNameToIdMap.find(typeName);
  450.         if (iter == m_typeNameToIdMap.end())
  451.         {
  452.                 const TFlowNodeTypeId nTypeId = GenerateNodeTypeID();
  453.                 if ((nTypeId == InvalidFlowNodeTypeId) && typeName.compareNoCase("InvalidType"))
  454.                         return nTypeId;
  455.  
  456.                 m_typeNameToIdMap[typeName] = nTypeId;
  457.                 STypeInfo typeInfo(typeName, factory);
  458.  
  459.                 if (nTypeId >= m_typeRegistryVec.size())
  460.                         m_typeRegistryVec.push_back(typeInfo);
  461.                 else
  462.                         m_typeRegistryVec[nTypeId] = typeInfo;
  463.  
  464.                 return nTypeId;
  465.         }
  466.         else
  467.         {
  468.                 // overriding
  469.                 TFlowNodeTypeId nTypeId = iter->second;
  470.  
  471.                 if (!factory->AllowOverride())
  472.                 {
  473.                         CryFatalError("CFlowSystem::RegisterType: Type '%s' Id=%u already registered. Overriding not allowed by node factory.", type, nTypeId);
  474.                 }
  475.  
  476.                 assert(nTypeId < m_typeRegistryVec.size());
  477.                 STypeInfo& typeInfo = m_typeRegistryVec[nTypeId];
  478.                 typeInfo.factory = factory;
  479.                 return nTypeId;
  480.         }
  481. }
  482.  
  483. bool CFlowSystem::UnregisterType(const char* typeName)
  484. {
  485.         const TTypeNameToIdMap::iterator iter = m_typeNameToIdMap.find(typeName);
  486.  
  487.         if (iter != m_typeNameToIdMap.end())
  488.         {
  489.                 const TFlowNodeTypeId typeID = iter->second;
  490.                 m_freeNodeTypeIDs.push_back(typeID);
  491.                 m_typeRegistryVec[typeID] = STypeInfo();
  492.                 m_typeNameToIdMap.erase(iter);
  493.  
  494.                 return true;
  495.         }
  496.  
  497.         return false;
  498. }
  499.  
  500. IFlowNodePtr CFlowSystem::CreateNodeOfType(IFlowNode::SActivationInfo* pActInfo, TFlowNodeTypeId typeId)
  501. {
  502.         assert(typeId < m_typeRegistryVec.size());
  503.         if (typeId >= m_typeRegistryVec.size())
  504.                 return 0;
  505.  
  506.         const STypeInfo& type = m_typeRegistryVec[typeId];
  507.         IFlowNodeFactory* pFactory = type.factory;
  508.         if (pFactory)
  509.                 return pFactory->Create(pActInfo);
  510.  
  511.         return 0;
  512. }
  513.  
  514. //////////////////////////////////////////////////////////////////////////
  515. void CFlowSystem::Update()
  516. {
  517. #ifdef SHOW_FG_CRITICAL_LOADING_ERROR_ON_SCREEN
  518.         if (m_criticalLoadingErrorHappened && !gEnv->IsEditor() && gEnv->pRenderer)
  519.         {
  520.                 IRenderAuxText::Draw2dLabel(10, 30, 2, Col_Red, false, "CRITICAL ERROR. SOME FLOWGRAPHS HAVE BEEN DISCARDED");
  521.                 IRenderAuxText::Draw2dLabel(10, 50, 2, Col_Red, false, "LEVEL LOGIC COULD BE DAMAGED. check log for more info.");
  522.         }
  523. #endif
  524.  
  525.         {
  526.                 FRAME_PROFILER("CFlowSystem::ForeignSystemUpdate", gEnv->pSystem, PROFILE_ACTION);
  527.                 // These things need to be updated in game mode and ai/physics mode
  528.                 CCryAction::GetCryAction()->GetPersistantDebug()->Update(gEnv->pTimer->GetFrameTime());
  529.                 CDebugHistoryManager::RenderAll();
  530.                 CCryAction::GetCryAction()->GetTimeOfDayScheduler()->Update();
  531.         }
  532.  
  533.         {
  534.                 FRAME_PROFILER("CFlowSystem::Update()", gEnv->pSystem, PROFILE_ACTION);
  535.                 if (m_cVars.m_enableUpdates == 0)
  536.                 {
  537.                         /*
  538.                            IRenderer * pRend = gEnv->pRenderer;
  539.                            float white[4] = {1,1,1,1};
  540.                            pRend->Draw2dLabel( 10, 100, 2, white, false, "FlowGraphSystem Disabled");
  541.                          */
  542.                         return;
  543.                 }
  544.  
  545.                 if (m_bInspectingEnabled)
  546.                 {
  547.                         // call pre updates
  548.  
  549.                         // 1. system inspectors
  550.                         std::for_each(m_systemInspectors.begin(), m_systemInspectors.end(), std::bind2nd(std::mem_fun(&IFlowGraphInspector::PreUpdate), (IFlowGraph*) 0));
  551.  
  552.                         // 2. graph inspectors TODO: optimize not to go over all graphs ;-)
  553.                         for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  554.                         {
  555.                                 const std::vector<IFlowGraphInspectorPtr>& graphInspectors(itGraph->GetInspectors());
  556.                                 std::for_each(graphInspectors.begin(), graphInspectors.end(), std::bind2nd(std::mem_fun(&IFlowGraphInspector::PreUpdate), *itGraph));
  557.                         }
  558.                 }
  559.  
  560.                 UpdateGraphs();
  561.  
  562.                 if (m_bInspectingEnabled)
  563.                 {
  564.                         // call post updates
  565.  
  566.                         // 1. system inspectors
  567.                         std::for_each(m_systemInspectors.begin(), m_systemInspectors.end(), std::bind2nd(std::mem_fun(&IFlowGraphInspector::PostUpdate), (IFlowGraph*) 0));
  568.  
  569.                         // 2. graph inspectors TODO: optimize not to go over all graphs ;-)
  570.                         for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  571.                         {
  572.                                 const std::vector<IFlowGraphInspectorPtr>& graphInspectors(itGraph->GetInspectors());
  573.                                 std::for_each(graphInspectors.begin(), graphInspectors.end(), std::bind2nd(std::mem_fun(&IFlowGraphInspector::PostUpdate), *itGraph));
  574.                         }
  575.                 }
  576.         }
  577.  
  578.         // end of flow system update: remove module instances which are no longer needed
  579.         m_pModuleManager->RemoveCompletedModuleInstances();
  580. }
  581.  
  582. //////////////////////////////////////////////////////////////////////////
  583. void CFlowSystem::UpdateGraphs()
  584. {
  585.         // Determine if graphs should be updated (Debug control)
  586.         bool bUpdateGraphs = true;
  587.         PREFAST_SUPPRESS_WARNING(6237);
  588.         if (gEnv->IsEditing() && CCryAction::GetCryAction()->IsGameStarted())
  589.         {
  590.                 if (m_cVars.m_enableFlowgraphNodeDebugging == 2)
  591.                 {
  592.                         if (m_cVars.m_debugNextStep == 0)
  593.                                 bUpdateGraphs = false;
  594.                         else
  595.                                 m_cVars.m_debugNextStep = 0;
  596.                 }
  597.         }
  598.  
  599.         if (bUpdateGraphs)
  600.         {
  601.                 if (m_needToUpdateForwardings)
  602.                 {
  603.                         for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  604.                         {
  605.                                 itGraph->UpdateForwardings();
  606.                         }
  607.                         m_needToUpdateForwardings = false;
  608.                 }
  609.  
  610.                 for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  611.                 {
  612.                         itGraph->Update();
  613.                 }
  614.         }
  615.  
  616. #ifndef _RELEASE
  617.         if (m_cVars.m_profile != 0)
  618.         {
  619.                 float white[4] = { 1, 1, 1, 1 };
  620.                 IRenderAuxText::Draw2dLabel(10, 100, 2, white, false, "Number of Flow Graphs Updated: %d", FGProfile.graphsUpdated);
  621.                 IRenderAuxText::Draw2dLabel(10, 120, 2, white, false, "Number of Flow Graph Nodes Updated: %d", FGProfile.nodeUpdates);
  622.                 IRenderAuxText::Draw2dLabel(10, 140, 2, white, false, "Number of Flow Graph Nodes Activated: %d", FGProfile.nodeActivations);
  623.         }
  624.         FGProfile.Reset();
  625. #endif //_RELEASE
  626. }
  627.  
  628. //////////////////////////////////////////////////////////////////////////
  629. void CFlowSystem::Reset(bool unload)
  630. {
  631.         m_needToUpdateForwardings = true; // does not hurt, and it prevents a potentially bad situation in save/load.
  632.         if (!unload)
  633.         {
  634.                 for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  635.                 {
  636.                         itGraph->InitializeValues();
  637.                 }
  638.         }
  639.         else
  640.         {
  641.                 assert(m_graphs.Empty());
  642.                 m_graphs.Clear(true);
  643.                 for (std::vector<STypeInfo>::iterator it = m_typeRegistryVec.begin(), itEnd = m_typeRegistryVec.end(); it != itEnd; ++it)
  644.                 {
  645.                         if (it->factory.get())
  646.                         {
  647.                                 it->factory->Reset();
  648.                         }
  649.                 }
  650.         }
  651.  
  652.         // Clean up the containers
  653.         m_FlowSystemContainers.clear();
  654. }
  655.  
  656. //////////////////////////////////////////////////////////////////////////
  657. void CFlowSystem::Init()
  658. {
  659.         if (gEnv->pEntitySystem)
  660.                 gEnv->pEntitySystem->AddSink(this, IEntitySystem::OnReused | IEntitySystem::OnSpawn, 0);
  661. }
  662.  
  663. //////////////////////////////////////////////////////////////////////////
  664. void CFlowSystem::Shutdown()
  665. {
  666.         if (gEnv->pEntitySystem)
  667.         {
  668.                 gEnv->pEntitySystem->RemoveSink(this);
  669.         }
  670.  
  671.         if (m_pModuleManager != nullptr)
  672.         {
  673.                 m_pModuleManager->Shutdown();
  674.                 delete m_pModuleManager;
  675.                 m_pModuleManager = nullptr;
  676.         }
  677.  
  678.         m_typeRegistryVec.clear();
  679.         m_typeNameToIdMap.clear();
  680.         m_systemInspectors.clear();
  681.         m_freeNodeTypeIDs.clear();
  682.         m_FlowSystemContainers.clear();
  683. }
  684.  
  685. //////////////////////////////////////////////////////////////////////////
  686. TFlowGraphId CFlowSystem::RegisterGraph(CFlowGraphBase* pGraph, const char* debugName)
  687. {
  688.         m_graphs.Add(pGraph, debugName);
  689.         return m_nextFlowGraphId++;
  690. }
  691.  
  692. //////////////////////////////////////////////////////////////////////////
  693. void CFlowSystem::UnregisterGraph(CFlowGraphBase* pGraph)
  694. {
  695.         m_graphs.Remove(pGraph);
  696. }
  697.  
  698. //////////////////////////////////////////////////////////////////////////
  699. void CFlowSystem::LoadBlacklistedFlownodeXML()
  700. {
  701.         if (!m_blacklistNode)
  702.         {
  703.                 const string filename = BLACKLIST_FILE_PATH;
  704.                 if (gEnv->pCryPak->IsFileExist(BLACKLIST_FILE_PATH))
  705.                 {
  706.                         m_blacklistNode = gEnv->pSystem->LoadXmlFromFile(filename);
  707.                 }
  708.         }
  709. }
  710.  
  711. //////////////////////////////////////////////////////////////////////////
  712. bool CFlowSystem::BlacklistedFlownode(const char** nodeName)
  713. {
  714.         if (m_blacklistNode)
  715.         {
  716.                 int childCount = m_blacklistNode->getChildCount();
  717.                 const char* attrKey;
  718.                 const char* attrValue;
  719.                 for (int n = 0; n < childCount; ++n)
  720.                 {
  721.                         XmlNodeRef child = m_blacklistNode->getChild(n);
  722.  
  723.                         if (!child->getAttributeByIndex(0, &attrKey, &attrValue))
  724.                                 continue;
  725.  
  726.                         if (!stricmp(attrValue, *nodeName))
  727.                         {
  728.                                 //replace name
  729.                                 int numAttr = child->getNumAttributes();
  730.                                 if (numAttr == 2 && child->getAttributeByIndex(1, &attrKey, &attrValue))
  731.                                 {
  732.                                         *nodeName = attrValue;
  733.                                         break;
  734.                                 }
  735.  
  736.                                 //remove class
  737.                                 return false;
  738.                         }
  739.                 }
  740.         }
  741.  
  742.         return true;
  743. }
  744.  
  745. //////////////////////////////////////////////////////////////////////////
  746. void CFlowSystem::RegisterAutoTypes()
  747. {
  748.         //////////////////////////////////////////////////////////////////////////
  749.         CAutoRegFlowNodeBase* pFactory = CAutoRegFlowNodeBase::m_pFirst;
  750.         while (pFactory)
  751.         {
  752.                 RegisterType(pFactory->m_sClassName, pFactory);
  753.                 pFactory = pFactory->m_pNext;
  754.         }
  755. }
  756.  
  757. //////////////////////////////////////////////////////////////////////////
  758. void CFlowSystem::RegisterEntityTypes()
  759. {
  760.         // Register all entity class from entities registry.
  761.         // Each entity class is registered as a flow type entity:ClassName, ex: entity:ProximityTrigger
  762.         IEntityClassRegistry* pClassRegistry = gEnv->pEntitySystem->GetClassRegistry();
  763.         IEntityClass* pEntityClass = 0;
  764.         pClassRegistry->IteratorMoveFirst();
  765.         string entityPrefixStr = "entity:";
  766.         while (pEntityClass = pClassRegistry->IteratorNext())
  767.         {
  768.                 string classname = entityPrefixStr + pEntityClass->GetName();
  769.  
  770.                 INDENT_LOG_DURING_SCOPE(true, "Flow system is registering entity type '%s'", classname.c_str());
  771.  
  772.                 // if the entity lua script does not have input/outputs defined, and there is already an FG node defined for that entity in c++, do not register the empty lua one
  773.                 if (pEntityClass->GetEventCount() == 0 && GetTypeId(classname) != InvalidFlowNodeTypeId)
  774.                         continue;
  775.  
  776.                 RegisterType(classname, new CFlowEntityClass(pEntityClass));
  777.         }
  778. }
  779.  
  780. //////////////////////////////////////////////////////////////////////////
  781. const CFlowSystem::STypeInfo& CFlowSystem::GetTypeInfo(TFlowNodeTypeId typeId) const
  782. {
  783.         assert(typeId < m_typeRegistryVec.size());
  784.         if (typeId < m_typeRegistryVec.size())
  785.                 return m_typeRegistryVec[typeId];
  786.         return m_typeRegistryVec[InvalidFlowNodeTypeId];
  787. }
  788.  
  789. //////////////////////////////////////////////////////////////////////////
  790. const char* CFlowSystem::GetTypeName(TFlowNodeTypeId typeId)
  791. {
  792.         assert(typeId < m_typeRegistryVec.size());
  793.         if (typeId < m_typeRegistryVec.size())
  794.                 return m_typeRegistryVec[typeId].name.c_str();
  795.         return "";
  796. }
  797.  
  798. //////////////////////////////////////////////////////////////////////////
  799. TFlowNodeTypeId CFlowSystem::GetTypeId(const char* typeName)
  800. {
  801.         return stl::find_in_map(m_typeNameToIdMap, CONST_TEMP_STRING(typeName), InvalidFlowNodeTypeId);
  802. }
  803.  
  804. //////////////////////////////////////////////////////////////////////////
  805. void CFlowSystem::RegisterInspector(IFlowGraphInspectorPtr pInspector, IFlowGraphPtr pGraph)
  806. {
  807.         if (pGraph == 0)
  808.         {
  809.                 stl::push_back_unique(m_systemInspectors, pInspector);
  810.         }
  811.         else
  812.         {
  813.                 CFlowGraphBase* pCGraph = (CFlowGraphBase*)pGraph.get();
  814.                 if (pCGraph && m_graphs.Contains(pCGraph))
  815.                         pCGraph->RegisterInspector(pInspector);
  816.                 else
  817.                         GameWarning("CFlowSystem::RegisterInspector: Unknown graph 0x%p", (IFlowGraph*)pGraph);
  818.         }
  819. }
  820.  
  821. //////////////////////////////////////////////////////////////////////////
  822. void CFlowSystem::UnregisterInspector(IFlowGraphInspectorPtr pInspector, IFlowGraphPtr pGraph)
  823. {
  824.         if (pGraph == 0)
  825.         {
  826.                 stl::find_and_erase(m_systemInspectors, pInspector);
  827.         }
  828.         else
  829.         {
  830.                 CFlowGraphBase* pCGraph = (CFlowGraphBase*)pGraph.get();
  831.                 if (pCGraph && m_graphs.Contains(pCGraph))
  832.                         pCGraph->UnregisterInspector(pInspector);
  833.                 else
  834.                         GameWarning("CFlowSystem::UnregisterInspector: Unknown graph 0x%p", (IFlowGraph*)pGraph);
  835.         }
  836. }
  837.  
  838. //////////////////////////////////////////////////////////////////////////
  839. void CFlowSystem::NotifyFlow(CFlowGraphBase* pGraph, const SFlowAddress from, const SFlowAddress to)
  840. {
  841.         if (!m_bInspectingEnabled) return;
  842.  
  843.         if (!m_systemInspectors.empty())
  844.         {
  845.                 std::vector<IFlowGraphInspectorPtr>::iterator iter(m_systemInspectors.begin());
  846.                 while (iter != m_systemInspectors.end())
  847.                 {
  848.                         (*iter)->NotifyFlow(pGraph, from, to);
  849.                         ++iter;
  850.                 }
  851.         }
  852.         const std::vector<IFlowGraphInspectorPtr>& graphInspectors(pGraph->GetInspectors());
  853.         if (!graphInspectors.empty())
  854.         {
  855.                 std::vector<IFlowGraphInspectorPtr>::const_iterator iter(graphInspectors.begin());
  856.                 while (iter != graphInspectors.end())
  857.                 {
  858.                         (*iter)->NotifyFlow(pGraph, from, to);
  859.                         ++iter;
  860.                 }
  861.         }
  862. }
  863.  
  864. //////////////////////////////////////////////////////////////////////////
  865. void CFlowSystem::NotifyProcessEvent(CFlowGraphBase* pGraph, IFlowNode::EFlowEvent event, IFlowNode::SActivationInfo* pActInfo, IFlowNode* pImpl)
  866. {
  867.         if (!m_bInspectingEnabled) return;
  868. }
  869.  
  870. //////////////////////////////////////////////////////////////////////////
  871. IFlowGraph* CFlowSystem::GetGraphById(TFlowGraphId graphId)
  872. {
  873.         for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  874.         {
  875.                 CFlowGraphBase* pFlowGraph = *itGraph;
  876.  
  877.                 if (pFlowGraph->GetGraphId() == graphId)
  878.                 {
  879.                         return pFlowGraph;
  880.                 }
  881.         }
  882.  
  883.         return NULL;
  884. }
  885.  
  886. //////////////////////////////////////////////////////////////////////////
  887. void CFlowSystem::GetMemoryUsage(ICrySizer* pSizer) const
  888. {
  889.         SIZER_SUBCOMPONENT_NAME(pSizer, "FlowSystem");
  890.         pSizer->AddObject(this, sizeof(*this));
  891.  
  892.         {
  893.                 SIZER_SUBCOMPONENT_NAME(pSizer, "Factories");
  894.                 {
  895.                         SIZER_SUBCOMPONENT_NAME(pSizer, "FactoriesLookup");
  896.                         pSizer->AddObject(m_typeNameToIdMap);
  897.                         pSizer->AddObject(m_typeRegistryVec);
  898.                 }
  899.         }
  900.  
  901.         {
  902.                 SIZER_SUBCOMPONENT_NAME(pSizer, "Inspectors");
  903.                 pSizer->AddObject(m_systemInspectors);
  904.         }
  905.  
  906.         if (!m_graphs.Empty())
  907.         {
  908.                 SIZER_SUBCOMPONENT_NAME(pSizer, "Graphs");
  909.                 pSizer->AddObject(&m_graphs, m_graphs.MemSize());
  910.         }
  911.  
  912.         if (!m_FlowSystemContainers.empty())
  913.         {
  914.                 SIZER_SUBCOMPONENT_NAME(pSizer, "Containers");
  915.                 for (TFlowSystemContainerMap::const_iterator it = m_FlowSystemContainers.begin(); it != m_FlowSystemContainers.end(); ++it)
  916.                 {
  917.                         (*it).second->GetMemoryUsage(pSizer);
  918.                 }
  919.  
  920.                 pSizer->AddObject(&(*m_FlowSystemContainers.begin()), m_FlowSystemContainers.size() * (sizeof(CFlowSystemContainer) + sizeof(TFlowSystemContainerId)));
  921.         }
  922. }
  923.  
  924. //////////////////////////////////////////////////////////////////////////
  925. void CFlowSystem::OnReused(IEntity* pEntity, SEntitySpawnParams& params)
  926. {
  927.         for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  928.         {
  929.                 itGraph->OnEntityReused(pEntity, params);
  930.         }
  931. }
  932.  
  933. //////////////////////////////////////////////////////////////////////////
  934. void CFlowSystem::OnEntityIdChanged(EntityId oldId, EntityId newId)
  935. {
  936.         for (TGraphs::Notifier itGraph(m_graphs); itGraph.IsValid(); itGraph.Next())
  937.         {
  938.                 itGraph->OnEntityIdChanged(oldId, newId);
  939.         }
  940. }
  941.  
  942. //////////////////////////////////////////////////////////////////////////
  943. bool CFlowSystem::CreateContainer(TFlowSystemContainerId id)
  944. {
  945.         if (m_FlowSystemContainers.find(id) != m_FlowSystemContainers.end())
  946.         {
  947.                 return false;
  948.         }
  949.  
  950.         IFlowSystemContainerPtr container(new CFlowSystemContainer);
  951.         m_FlowSystemContainers.insert(std::make_pair(id, container));
  952.         return true;
  953. }
  954.  
  955. //////////////////////////////////////////////////////////////////////////
  956. void CFlowSystem::DeleteContainer(TFlowSystemContainerId id)
  957. {
  958.         std::map<TFlowSystemContainerId, IFlowSystemContainerPtr>::iterator it = m_FlowSystemContainers.find(id);
  959.         if (it != m_FlowSystemContainers.end())
  960.         {
  961.                 m_FlowSystemContainers.erase(it);
  962.         }
  963. }
  964.  
  965. //////////////////////////////////////////////////////////////////////////
  966. IFlowSystemContainerPtr CFlowSystem::GetContainer(TFlowSystemContainerId id)
  967. {
  968.         return m_FlowSystemContainers[id];
  969. }
  970.  
  971. //////////////////////////////////////////////////////////////////////////
  972. void CFlowSystem::OnSpawn(IEntity* pEntity, SEntitySpawnParams& params)
  973. {
  974.         // this should be a more generic test: maybe an entity flag "CAN_FORWARD_FLOWGRAPHS", or something similar
  975.         if ((pEntity->GetFlags() & ENTITY_FLAG_HAS_AI) != 0)
  976.         {
  977.                 m_needToUpdateForwardings = true;
  978.         }
  979. }
  980.  
  981. //////////////////////////////////////////////////////////////////////////
  982. IFlowGraphModuleManager* CFlowSystem::GetIModuleManager()
  983. {
  984.         return m_pModuleManager;
  985. }
  986.  
  987. //////////////////////////////////////////////////////////////////////////
  988. void CFlowSystem::Serialize(TSerialize ser)
  989. {
  990.         int count = m_FlowSystemContainers.size();
  991.         ser.Value("ContainerCount", count);
  992.  
  993.         if (ser.IsWriting())
  994.         {
  995.                 TFlowSystemContainerMap::iterator it = m_FlowSystemContainers.begin();
  996.                 while (it != m_FlowSystemContainers.end())
  997.                 {
  998.                         ser.BeginGroup("Containers");
  999.                         TFlowSystemContainerId id = (*it).first;
  1000.                         ser.Value("key", id);
  1001.                         (*it).second->Serialize(ser);
  1002.                         ser.EndGroup();
  1003.                         ++it;
  1004.                 }
  1005.         }
  1006.         else
  1007.         {
  1008.                 int id;
  1009.                 for (int i = 0; i < count; i++)
  1010.                 {
  1011.                         ser.BeginGroup("Containers");
  1012.                         ser.Value("key", id);
  1013.                         if (CreateContainer(id))
  1014.                         {
  1015.                                 IFlowSystemContainerPtr container = GetContainer(id);
  1016.                                 if (container)
  1017.                                 {
  1018.                                         container->Serialize(ser);
  1019.                                 }
  1020.                                 else
  1021.                                 {
  1022.                                         CryWarning(VALIDATOR_MODULE_FLOWGRAPH, VALIDATOR_ERROR, "CFlowSystem::Serialize: Could not create or get container with ID from save file - container not restored");
  1023.                                 }
  1024.                         }
  1025.                         ser.EndGroup();
  1026.                 }
  1027.         }
  1028. }
  1029.  
downloadFlowSystem.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