BVB Source Codes

CRYENGINE Show FlowGraph.cpp Source code

Return Download CRYENGINE: download FlowGraph.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. #include <CryAISystem/IAIAction.h>
  5.  
  6. #include "FlowGraph.h"
  7. #include "FlowSystem.h"
  8. #include <CryString/StringUtils.h>
  9. #include <CryGame/IGameTokens.h>
  10. #include "Modules/ModuleManager.h"
  11.  
  12. // Debug disabled edges in FlowGraphs
  13. #define FLOW_DEBUG_DISABLED_EDGES
  14. #undef FLOW_DEBUG_DISABLED_EDGES
  15.  
  16. // Debug mapping from NodeIDs (==char* Name) to internal IDs (index in std::vector)
  17. #define FLOW_DEBUG_ID_MAPPING
  18. #undef FLOW_DEBUG_ID_MAPPING
  19.  
  20. // #define FLOW_DEBUG_PENDING_UPDATES is defined in header file FlowGraph.h
  21.  
  22. #define NODE_NAME_ATTR "ID"
  23. #define NODE_TYPE_ATTR "Class"
  24.  
  25. class CFlowGraphBase::CNodeIterator : public IFlowNodeIterator
  26. {
  27. public:
  28.         CNodeIterator(CFlowGraphBase* pParent) :
  29.                 m_refs(0),
  30.                 m_pParent(pParent)
  31.         {
  32.                 m_begin = pParent->m_nodeNameToId.begin();
  33.                 m_iter = m_begin;
  34.                 m_pParent->AddRef();
  35.         }
  36.         ~CNodeIterator()
  37.         {
  38.                 m_pParent->Release();
  39.         }
  40.  
  41.         void AddRef()
  42.         {
  43.                 ++m_refs;
  44.         }
  45.  
  46.         void Release()
  47.         {
  48.                 if (0 == --m_refs)
  49.                         delete this;
  50.         }
  51.  
  52.         IFlowNodeData* Next(TFlowNodeId& id)
  53.         {
  54.                 IFlowNodeData* out = NULL;
  55.                 if (m_iter != m_pParent->m_nodeNameToId.end())
  56.                 {
  57.                         id = m_iter->second;
  58.                         out = &m_pParent->m_flowData[id];
  59.                         ++m_iter;
  60.                 }
  61.                 return out;
  62.         }
  63.  
  64. private:
  65.         int                                     m_refs;
  66.         CFlowGraphBase*                         m_pParent;
  67.         std::map<string, TFlowNodeId>::iterator m_begin;
  68.         std::map<string, TFlowNodeId>::iterator m_iter;
  69. };
  70.  
  71. class CFlowGraphBase::CEdgeIterator : public IFlowEdgeIterator
  72. {
  73. public:
  74.         CEdgeIterator(CFlowGraphBase* pParent) :
  75.                 m_refs(0),
  76.                 m_pParent(pParent),
  77.                 m_iter(pParent->m_edges.begin())
  78.         {
  79.                 m_pParent->AddRef();
  80.         }
  81.         ~CEdgeIterator()
  82.         {
  83.                 m_pParent->Release();
  84.         }
  85.  
  86.         void AddRef()
  87.         {
  88.                 ++m_refs;
  89.         }
  90.  
  91.         void Release()
  92.         {
  93.                 if (0 == --m_refs)
  94.                         delete this;
  95.         }
  96.  
  97.         bool Next(Edge& edge)
  98.         {
  99.                 if (m_iter == m_pParent->m_edges.end())
  100.                         return false;
  101.                 edge.fromNodeId = m_iter->fromNode;
  102.                 edge.toNodeId = m_iter->toNode;
  103.                 edge.fromPortId = m_iter->fromPort;
  104.                 edge.toPortId = m_iter->toPort;
  105.                 ++m_iter;
  106.                 return true;
  107.         }
  108.  
  109. private:
  110.         int                                m_refs;
  111.         CFlowGraphBase*                    m_pParent;
  112.         std::vector<SEdge>::const_iterator m_iter;
  113. };
  114.  
  115. class CFlowGraphBase::SEdgeHasNode
  116. {
  117. public:
  118.         ILINE SEdgeHasNode(TFlowNodeId id) : m_id(id) {}
  119.         ILINE bool operator()(const SEdge& edge) const
  120.         {
  121.                 return edge.fromNode == m_id || edge.toNode == m_id;
  122.         }
  123.  
  124. private:
  125.         TFlowNodeId m_id;
  126. };
  127.  
  128. CFlowGraphBase::CFlowGraphBase(CFlowSystem* pSys)
  129.         : m_firstModifiedNode(END_OF_MODIFIED_LIST)
  130.         , m_firstActivatingNode(END_OF_MODIFIED_LIST)
  131.         , m_bInUpdate(false)
  132.         , m_firstFinalActivatingNode(END_OF_MODIFIED_LIST)
  133.         , m_bEnabled(true)
  134.         , m_bActive(true)
  135.         , m_bEdgesSorted(true)
  136.         , m_bNeedsInitialize(true)
  137.         , m_bNeedsUpdating(false)
  138.         , m_pSys(pSys)
  139.         , m_nRefs(0)
  140.         , m_bSuspended(false)
  141.         , m_bIsAIAction(false)
  142.         , m_pAIAction(NULL)
  143.         , m_bIsCustomAction(false)
  144.         , m_pCustomAction(NULL)
  145.         , m_pClonedFlowGraph(NULL)
  146.         , m_graphId(InvalidFlowGraphId)
  147.         , m_Type(IFlowGraph::eFGT_Default)
  148. {
  149.         m_pEntitySystem = gEnv->pEntitySystem;
  150.  
  151.         for (int i = 0; i < MAX_GRAPH_ENTITIES; i++)
  152.                 m_graphEntityId[i] = 0;
  153.  
  154. #if defined (FLOW_DEBUG_PENDING_UPDATES)
  155.         CreateDebugName();
  156. #endif
  157.  
  158.         m_graphId = m_pSys->RegisterGraph(this, InternalGetDebugName());
  159.         m_bRegistered = true;
  160.         m_pFlowGraphDebugger = GetIFlowGraphDebuggerPtr();
  161. }
  162.  
  163. void CFlowGraphBase::SetEnabled(bool bEnable)
  164. {
  165.         if (m_bEnabled != bEnable)
  166.         {
  167.                 m_bEnabled = bEnable;
  168.                 if (bEnable) NeedUpdate();
  169.         }
  170. }
  171.  
  172. void CFlowGraphBase::SetActive(bool bActive)
  173. {
  174.         if (m_bActive != bActive)
  175.         {
  176.                 m_bActive = bActive;
  177.                 if (bActive) NeedUpdate();
  178.         }
  179. }
  180.  
  181. void CFlowGraphBase::RegisterFlowNodeActivationListener(SFlowNodeActivationListener* listener)
  182. {
  183.         if (!stl::find(m_flowNodeActivationListeners, listener))
  184.                 m_flowNodeActivationListeners.push_back(listener);
  185. }
  186.  
  187. void CFlowGraphBase::RemoveFlowNodeActivationListener(SFlowNodeActivationListener* listener)
  188. {
  189.         stl::find_and_erase(m_flowNodeActivationListeners, listener);
  190. }
  191.  
  192. bool CFlowGraphBase::NotifyFlowNodeActivationListeners(TFlowNodeId srcNode, TFlowPortId srcPort, TFlowNodeId toNode, TFlowPortId toPort, const char* value)
  193. {
  194.         if (m_pClonedFlowGraph)
  195.         {
  196.                 // [3/24/2011 evgeny] Allow AI Action FG to be debugged as well
  197.                 m_pClonedFlowGraph->NotifyFlowNodeActivationListeners(srcNode, srcPort, toNode, toPort, value);
  198.                 return false;
  199.         }
  200.         else
  201.         {
  202.                 // Modules should notify via their root graph, so that all module activations are debugged on the
  203.                 //      graph visible in the editor.
  204.                 if (GetType() == IFlowGraph::eFGT_Module)
  205.                 {
  206.                         IFlowGraphModule* pModule = gEnv->pFlowSystem->GetIModuleManager()->GetModule(this);
  207.  
  208.                         if (pModule)
  209.                         {
  210.                                 IFlowGraphPtr pGraph = pModule->GetRootGraph();
  211.                                 return pGraph->NotifyFlowNodeActivationListeners(srcNode, srcPort, toNode, toPort, value);
  212.                         }
  213.                 }
  214.  
  215.                 std::vector<SFlowNodeActivationListener*>::iterator it = m_flowNodeActivationListeners.begin();
  216.                 std::vector<SFlowNodeActivationListener*>::iterator end = m_flowNodeActivationListeners.end();
  217.                 bool stopUpdate = false;
  218.                 for (; it != end; ++it)
  219.                 {
  220.                         bool stop = (*it)->OnFlowNodeActivation(this, srcNode, srcPort, toNode, toPort, value);
  221.  
  222.                         if (stop)
  223.                                 stopUpdate = true;
  224.                 }
  225.  
  226.                 return stopUpdate;
  227.         }
  228. }
  229.  
  230. void CFlowGraphBase::SetSuspended(bool suspend)
  231. {
  232.         if (m_bSuspended != suspend)
  233.         {
  234.                 m_bSuspended = false;
  235.  
  236.                 IFlowNode::SActivationInfo activationInfo(this, 0);
  237.                 for (std::vector<CFlowData>::iterator it = m_flowData.begin(); it != m_flowData.end(); ++it)
  238.                 {
  239.                         if (!it->IsValid())
  240.                                 continue;
  241.  
  242.                         activationInfo.myID = (TFlowNodeId)(it - m_flowData.begin());
  243.                         activationInfo.pEntity = GetIEntityForNode(activationInfo.myID);
  244.                         it->SetSuspended(&activationInfo, suspend);
  245.                 }
  246.  
  247.                 if (suspend)
  248.                         m_bSuspended = true;
  249.                 else
  250.                         NeedUpdate();
  251.         }
  252. }
  253.  
  254. bool CFlowGraphBase::IsSuspended() const
  255. {
  256.         return m_bSuspended;
  257. }
  258.  
  259. void CFlowGraphBase::SetAIAction(IAIAction* pAIAction)
  260. {
  261. #if !defined(FLOW_DEBUG_PENDING_UPDATES)
  262.         m_pAIAction = pAIAction;
  263.         if (pAIAction)
  264.                 m_bIsAIAction = true; // once an AIAction, always an AIAction
  265. #else
  266.         if (pAIAction)
  267.         {
  268.                 m_bIsAIAction = true; // once an AIAction, always an AIAction
  269.                 m_pAIAction = pAIAction;
  270.                 CreateDebugName();
  271.         }
  272.         else
  273.                 m_pAIAction = 0;
  274. #endif
  275.  
  276.         if (m_bIsAIAction)
  277.                 m_Type = eFGT_AIAction;
  278.         else
  279.                 m_Type = eFGT_Default;
  280. }
  281.  
  282. IAIAction* CFlowGraphBase::GetAIAction() const
  283. {
  284.         return m_pAIAction;
  285. }
  286.  
  287. void CFlowGraphBase::SetCustomAction(ICustomAction* pCustomAction)
  288. {
  289. #if !defined(FLOW_DEBUG_PENDING_UPDATES)
  290.         m_pCustomAction = pCustomAction;
  291.         if (pCustomAction)
  292.                 m_bIsCustomAction = true; // once an CustomAction, always an CustomAction
  293. #else
  294.         if (pCustomAction)
  295.         {
  296.                 m_bIsCustomAction = true; // once an CustomAction, always an CustomAction
  297.                 m_pCustomAction = pCustomAction;
  298.                 CreateDebugName();
  299.         }
  300.         else
  301.                 m_pCustomAction = 0;
  302. #endif
  303. }
  304.  
  305. ICustomAction* CFlowGraphBase::GetCustomAction() const
  306. {
  307.         return m_pCustomAction;
  308. }
  309.  
  310. void CFlowGraphBase::UnregisterFromFlowSystem()
  311. {
  312.         assert(m_bRegistered);
  313.         if (m_pSys && m_bRegistered)
  314.                 m_pSys->UnregisterGraph(this);
  315.  
  316.         m_graphId = InvalidFlowGraphId;
  317.         m_bRegistered = false;
  318. }
  319.  
  320. void CFlowGraphBase::Cleanup()
  321. {
  322.         m_firstModifiedNode = END_OF_MODIFIED_LIST;
  323.         m_firstActivatingNode = END_OF_MODIFIED_LIST;
  324.         m_firstFinalActivatingNode = END_OF_MODIFIED_LIST;
  325.         m_bEdgesSorted = true; // no edges => sorted :)
  326.         stl::free_container(m_modifiedNodes);
  327.         stl::free_container(m_activatingNodes);
  328.         stl::free_container(m_finalActivatingNodes);
  329.         stl::free_container(m_flowData);
  330.         stl::free_container(m_deallocatedIds);
  331.         stl::free_container(m_edges);
  332.         m_nodeNameToId.clear();
  333.         stl::free_container(m_regularUpdates);
  334.         stl::free_container(m_activatingUpdates);
  335.         stl::free_container(m_inspectors);
  336. }
  337.  
  338. CFlowGraphBase::~CFlowGraphBase()
  339. {
  340.         //      FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  341.  
  342.         RemoveGraphTokens();
  343.  
  344.         if (m_pSys && m_graphId != InvalidFlowGraphId && m_bRegistered)
  345.                 m_pSys->UnregisterGraph(this);
  346.  
  347.         Cleanup();
  348. }
  349.  
  350. #if defined (FLOW_DEBUG_PENDING_UPDATES)
  351.  
  352. namespace {
  353. string GetPrettyNodeName(IFlowGraph* pGraph, TFlowNodeId id)
  354. {
  355.         const char* typeName = pGraph->GetNodeTypeName(id);
  356.         const char* nodeName = pGraph->GetNodeName(id);
  357.         string human;
  358.         human += typeName;
  359.         human += " Node:";
  360.  
  361.         if (nodeName == 0)
  362.         {
  363.                 IEntity* pEntity = ((CFlowGraph*)pGraph)->GetIEntityForNode(id);
  364.                 if (pEntity)
  365.                         human += pEntity->GetName();
  366.         }
  367.         else
  368.                 human += nodeName;
  369.         return human;
  370. }
  371. };
  372.  
  373. const char* CFlowGraphBase::InternalGetDebugName()
  374. {
  375.         static char buf[128];
  376.         bool bFit;
  377.  
  378.         if (m_pAIAction != 0)
  379.                 bFit = cry_sprintf(buf, "FG-0x%p-AIAction '%s'", this, m_pAIAction->GetName());
  380.         else
  381.         {
  382.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(GetGraphEntity(0));
  383.                 if (pEntity != 0)
  384.                         bFit = cry_sprintf(buf, "FG-0x%p-Entity '%s'", this, pEntity->GetName());
  385.                 else
  386.                         bFit = cry_sprintf(buf, "FG-0x%p", this);
  387.         }
  388.  
  389.         if (!bFit)
  390.         {
  391.                 buf[sizeof(buf) - 4] = '\0';
  392.                 cry_strcat(buf, "...");
  393.         }
  394.  
  395.         return buf;
  396. }
  397.  
  398. void CFlowGraphBase::CreateDebugName()
  399. {
  400.         m_debugName = InternalGetDebugName();
  401. }
  402.  
  403. void CFlowGraphBase::DebugPendingActivations()
  404. {
  405.         if (m_bIsAIAction == true)
  406.                 return;
  407.  
  408.         GameWarning("[flow] %s was destroyed with pending updates/activations. Report follows...", m_debugName.c_str());
  409.  
  410.         if (m_pSys == 0)
  411.         {
  412.                 GameWarning("[flow] FlowSystem already shutdown.");
  413.                 return;
  414.         }
  415.  
  416.         GameWarning("[flow] Pending nodes:");
  417.  
  418.         TFlowNodeId id = m_firstModifiedNode;
  419.         // traverse the list of modified nodes
  420.         while (id != END_OF_MODIFIED_LIST)
  421.         {
  422.                 assert(ValidateNode(id) == true);
  423.                 bool bIsReg(std::find(m_regularUpdates.begin(), m_regularUpdates.end(), id) != m_regularUpdates.end());
  424.                 GameWarning("[flow] %s regular=%d", GetPrettyNodeName(this, id).c_str(), bIsReg);
  425.                 TFlowNodeId nextId = m_modifiedNodes[id];
  426.                 m_modifiedNodes[id] = NOT_MODIFIED;
  427.                 id = nextId;
  428.         }
  429.  
  430.         id = m_firstFinalActivatingNode;
  431.  
  432.         if (id != m_firstFinalActivatingNode)
  433.                 GameWarning("[flow] Pending nodes [final activations]:");
  434.  
  435.         while (id != END_OF_MODIFIED_LIST)
  436.         {
  437.                 assert(ValidateNode(id) == true);
  438.                 bool bIsReg(std::find(m_regularUpdates.begin(), m_regularUpdates.end(), id) != m_regularUpdates.end());
  439.                 GameWarning("[flow] %s regular=%d", GetPrettyNodeName(this, id).c_str(), bIsReg);
  440.                 TFlowNodeId nextId = m_finalActivatingNodes[id];
  441.                 m_finalActivatingNodes[id] = NOT_MODIFIED;
  442.                 id = nextId;
  443.         }
  444. }
  445. #else
  446. const char* CFlowGraphBase::InternalGetDebugName()
  447. {
  448.         return "";
  449. }
  450. #endif
  451.  
  452. void CFlowGraphBase::AddRef()
  453. {
  454.         m_nRefs++;
  455. }
  456.  
  457. void CFlowGraphBase::Release()
  458. {
  459.         CRY_ASSERT(m_nRefs > 0);
  460.         if (0 == --m_nRefs)
  461.                 delete this;
  462. }
  463.  
  464. //////////////////////////////////////////////////////////////////////////
  465. void CFlowGraphBase::RegisterHook(IFlowGraphHookPtr p)
  466. {
  467.         stl::push_back_unique(m_hooks, p);
  468. }
  469.  
  470. //////////////////////////////////////////////////////////////////////////
  471. void CFlowGraphBase::UnregisterHook(IFlowGraphHookPtr p)
  472. {
  473.         stl::find_and_erase(m_hooks, p);
  474. }
  475.  
  476. //////////////////////////////////////////////////////////////////////////
  477. void CFlowGraphBase::SetGraphEntity(EntityId id, int nIndex)
  478. {
  479.         if (nIndex >= 0 && nIndex < MAX_GRAPH_ENTITIES)
  480.                 m_graphEntityId[nIndex] = id;
  481. #if defined (FLOW_DEBUG_PENDING_UPDATES)
  482.         CreateDebugName();
  483. #endif
  484. }
  485.  
  486. //////////////////////////////////////////////////////////////////////////
  487. EntityId CFlowGraphBase::GetGraphEntity(int nIndex) const
  488. {
  489.         if (nIndex >= 0 && nIndex < MAX_GRAPH_ENTITIES)
  490.                 return m_graphEntityId[nIndex];
  491.         return 0;
  492. }
  493.  
  494. //////////////////////////////////////////////////////////////////////////
  495. IFlowGraphPtr CFlowGraphBase::Clone()
  496. {
  497.         CFlowGraphBase* pClone = new CFlowGraph(m_pSys);
  498.         CloneInner(pClone);
  499.  
  500.         return pClone;
  501. }
  502.  
  503. //////////////////////////////////////////////////////////////////////////
  504. void CFlowGraphBase::CloneInner(CFlowGraphBase* pClone)
  505. {
  506.         pClone->m_activatingNodes = m_activatingNodes;
  507.         pClone->m_activatingUpdates = m_activatingUpdates;
  508.         pClone->m_bEdgesSorted = m_bEdgesSorted;
  509.         pClone->m_deallocatedIds = m_deallocatedIds;
  510.         pClone->m_edges = m_edges;
  511.         pClone->m_firstActivatingNode = m_firstActivatingNode;
  512.         pClone->m_firstModifiedNode = m_firstModifiedNode;
  513.         pClone->m_firstFinalActivatingNode = m_firstFinalActivatingNode;
  514.         pClone->m_flowData = m_flowData;
  515.         pClone->m_modifiedNodes = m_modifiedNodes;
  516.         pClone->m_finalActivatingNodes = m_finalActivatingNodes;
  517.         pClone->m_nodeNameToId = m_nodeNameToId;
  518.         pClone->m_regularUpdates = m_regularUpdates;
  519.         pClone->m_hooks = m_hooks;
  520.         pClone->m_bEnabled = m_bEnabled;
  521.         pClone->m_pClonedFlowGraph = this;
  522.         pClone->m_Type = m_Type;
  523.         // pClone->m_bActive = m_bActive;
  524.         // pClone->m_bSuspended = m_bSuspended;
  525. #if defined (FLOW_DEBUG_PENDING_UPDATES)
  526.         pClone->CreateDebugName();
  527. #endif
  528.  
  529.         // clone graph tokens
  530.         for (size_t i = 0; i < GetGraphTokenCount(); ++i)
  531.         {
  532.                 const IFlowGraph::SGraphToken* pToken = GetGraphToken(i);
  533.                 pClone->AddGraphToken(*pToken);
  534.         }
  535.  
  536.         IFlowNode::SActivationInfo info;
  537.         info.pGraph = pClone;
  538.         for (std::vector<CFlowData>::iterator iter = pClone->m_flowData.begin(); iter != pClone->m_flowData.end(); ++iter)
  539.         {
  540.                 info.myID = (TFlowNodeId)(iter - pClone->m_flowData.begin());
  541.                 if (iter->IsValid())
  542.                         iter->CloneImpl(&info);
  543.         }
  544.  
  545.         //
  546.         /*
  547.            std::vector<SEdge>::const_iterator itEdges, itEdgesEnd = m_edges.end();
  548.            for ( itEdges = m_edges.begin(); itEdges != itEdgesEnd; ++itEdges )
  549.            {
  550.            IFlowNode::SActivationInfo info(this);
  551.            info.myID = itEdges->fromNode;
  552.            info.connectPort = itEdges->fromPort;
  553.            m_flowData[itEdges->fromNode].GetNode()->ProcessEvent( IFlowNode::eFE_ConnectOutputPort, &info );
  554.            info.myID = itEdges->toNode;
  555.            info.connectPort = itEdges->toPort;
  556.            m_flowData[itEdges->toNode].GetNode()->ProcessEvent( IFlowNode::eFE_ConnectInputPort, &info );
  557.            }
  558.          */
  559. }
  560.  
  561. //////////////////////////////////////////////////////////////////////////
  562. void CFlowGraphBase::Clear()
  563. {
  564.         Cleanup();
  565. }
  566.  
  567. //////////////////////////////////////////////////////////////////////////
  568. SFlowAddress CFlowGraphBase::ResolveAddress(const char* addr, bool isOutput)
  569. {
  570.         SFlowAddress flowAddr;
  571.         const char* colonPos = strchr(addr, ':');
  572.         if (colonPos)
  573.         {
  574.                 PREFAST_SUPPRESS_WARNING(6255)
  575.                 char* prefix = (char*)alloca(colonPos - addr + 1);
  576.                 memcpy(prefix, addr, colonPos - addr);
  577.                 prefix[colonPos - addr] = 0;
  578.                 flowAddr = ResolveAddress(prefix, colonPos + 1, isOutput);
  579.         }
  580.         return flowAddr;
  581. }
  582.  
  583. SFlowAddress CFlowGraphBase::ResolveAddress(const char* node, const char* port, bool isOutput)
  584. {
  585.         SFlowAddress flowAddr;
  586.         flowAddr.node = stl::find_in_map(m_nodeNameToId, node, InvalidFlowNodeId);
  587.         if (flowAddr.node == InvalidFlowNodeId)
  588.                 return SFlowAddress();
  589.         if (!m_flowData[flowAddr.node].ResolvePort(port, flowAddr.port, isOutput))
  590.                 return SFlowAddress();
  591.         flowAddr.isOutput = isOutput;
  592.         return flowAddr;
  593. }
  594.  
  595. TFlowNodeId CFlowGraphBase::ResolveNode(const char* name)
  596. {
  597.         return stl::find_in_map(m_nodeNameToId, name, InvalidFlowNodeId);
  598. }
  599.  
  600. void CFlowGraphBase::GetNodeConfiguration(TFlowNodeId id, SFlowNodeConfig& config)
  601. {
  602.         CRY_ASSERT(ValidateNode(id));
  603.         m_flowData[id].GetConfiguration(config);
  604. }
  605.  
  606. EntityId CFlowGraphBase::GetEntityId(TFlowNodeId id)
  607. {
  608.         CRY_ASSERT(ValidateNode(id));
  609.         return m_flowData[id].GetEntityId();
  610. }
  611.  
  612. void CFlowGraphBase::SetEntityId(TFlowNodeId nodeId, EntityId entityId)
  613. {
  614.         CRY_ASSERT(ValidateNode(nodeId));
  615.         if (m_flowData[nodeId].SetEntityId(entityId))
  616.                 ActivateNodeInt(nodeId);
  617. }
  618.  
  619. string CFlowGraphBase::PrettyAddress(SFlowAddress addr)
  620. {
  621.         CFlowData& data = m_flowData[addr.node];
  622.         return data.GetName() + ':' + data.GetPortName(addr.port, addr.isOutput);
  623. }
  624.  
  625. bool CFlowGraphBase::ValidateNode(TFlowNodeId id) const
  626. {
  627.         if (id == InvalidFlowNodeId)
  628.                 return false;
  629.         if (id >= m_flowData.size())
  630.                 return false;
  631.         return m_flowData[id].IsValid();
  632. }
  633.  
  634. bool CFlowGraphBase::ValidateAddress(const SFlowAddress from)
  635. {
  636.         if (!ValidateNode(from.node))
  637.                 return false;
  638.         if (!m_flowData[from.node].ValidatePort(from.port, from.isOutput))
  639.                 return false;
  640.         return true;
  641. }
  642.  
  643. bool CFlowGraphBase::ValidateLink(SFlowAddress& from, SFlowAddress& to)
  644. {
  645.         // can't link output->output, or input->input
  646.         if (from.isOutput == to.isOutput)
  647.         {
  648.                 const char* type = from.isOutput ? "output" : "input";
  649.                 GameWarning("[flow] Attempt to link an %s node to an %s node", type, type);
  650.                 return false;
  651.         }
  652.         // check order is correct, and fix it up if not
  653.         if (!from.isOutput)
  654.         {
  655.                 GameWarning("[flow] Attempt to link from an input node to an output node: reversing");
  656.                 std::swap(from, to);
  657.         }
  658.         // validate that the addresses are correct
  659.         if (!ValidateAddress(from) || !ValidateAddress(to))
  660.         {
  661.                 GameWarning("[flow] Trying to link an invalid node");
  662.                 return false;
  663.         }
  664.  
  665.         return true;
  666. }
  667.  
  668. bool CFlowGraphBase::LinkNodes(SFlowAddress from, SFlowAddress to)
  669. {
  670.         if (!ValidateLink(from, to))
  671.                 return false;
  672.  
  673.         // add this link to the edges collection
  674.         m_edges.push_back(SEdge(from, to));
  675.         // and make sure that we re-sort soon
  676.         m_bEdgesSorted = false;
  677.  
  678.         IFlowNode::SActivationInfo info(this);
  679.         info.myID = from.node;
  680.         info.connectPort = from.port;
  681.         m_flowData[from.node].GetNode()->ProcessEvent(IFlowNode::eFE_ConnectOutputPort, &info);
  682.         info.myID = to.node;
  683.         info.connectPort = to.port;
  684.         m_flowData[to.node].GetNode()->ProcessEvent(IFlowNode::eFE_ConnectInputPort, &info);
  685.  
  686.         NeedInitialize();
  687.  
  688.         return true;
  689. }
  690.  
  691. void CFlowGraphBase::UnlinkNodes(SFlowAddress from, SFlowAddress to)
  692. {
  693.         if (!ValidateLink(from, to))
  694.                 return;
  695.  
  696.         EnsureSortedEdges();
  697.  
  698.         SEdge findEdge(from, to);
  699.         std::vector<SEdge>::iterator iter = std::lower_bound(m_edges.begin(), m_edges.end(), findEdge);
  700.         if (iter != m_edges.end() && *iter == findEdge)
  701.         {
  702.                 IFlowNode::SActivationInfo info(this);
  703.                 info.myID = from.node;
  704.                 info.connectPort = from.port;
  705.                 m_flowData[from.node].GetNode()->ProcessEvent(IFlowNode::eFE_DisconnectOutputPort, &info);
  706.                 info.myID = to.node;
  707.                 info.connectPort = to.port;
  708.                 m_flowData[to.node].GetNode()->ProcessEvent(IFlowNode::eFE_DisconnectInputPort, &info);
  709.  
  710.                 m_edges.erase(iter);
  711.                 m_bEdgesSorted = false;
  712.         }
  713.         else
  714.         {
  715.                 GameWarning("[flow] Link not found");
  716.         }
  717. }
  718.  
  719. //////////////////////////////////////////////////////////////////////////
  720. TFlowNodeId CFlowGraphBase::CreateNode(TFlowNodeTypeId typeId, const char* name, void* pUserData)
  721. {
  722.         std::pair<CFlowData*, TFlowNodeId> nd = CreateNodeInt(typeId, name, pUserData);
  723.         return nd.second;
  724. }
  725.  
  726. //////////////////////////////////////////////////////////////////////////
  727. TFlowNodeId CFlowGraphBase::CreateNode(const char* typeName, const char* name, void* pUserData)
  728. {
  729.         std::pair<CFlowData*, TFlowNodeId> nd = CreateNodeInt(m_pSys->GetTypeId(typeName), name, pUserData);
  730.         return nd.second;
  731. }
  732.  
  733. //////////////////////////////////////////////////////////////////////////
  734. IFlowNodeData* CFlowGraphBase::GetNodeData(TFlowNodeId id)
  735. {
  736.         CRY_ASSERT(ValidateNode(id));
  737.         if (id < m_flowData.size())
  738.         {
  739.                 return &m_flowData[id];
  740.         }
  741.         return 0;
  742. }
  743.  
  744. //////////////////////////////////////////////////////////////////////////
  745. std::pair<CFlowData*, TFlowNodeId> CFlowGraphBase::CreateNodeInt(TFlowNodeTypeId typeId, const char* name, void* pUserData)
  746. {
  747.         typedef std::pair<CFlowData*, TFlowNodeId> R;
  748.  
  749.         // make sure we only allocate for the name and type once...
  750.         string sName = name;
  751.  
  752.         if (m_nodeNameToId.find(sName) != m_nodeNameToId.end())
  753.         {
  754.                 GameWarning("[flow] Trying to create a node with the same name as an existing name: %s", sName.c_str());
  755.                 return R((CFlowData*)NULL, InvalidFlowNodeId);
  756.         }
  757.  
  758.         // allocate a node id
  759.         TFlowNodeId id = AllocateId();
  760.         if (id == InvalidFlowNodeId)
  761.         {
  762.                 GameWarning("[flow] Unable to create node id for node named %s", sName.c_str());
  763.                 return R((CFlowData*)NULL, InvalidFlowNodeId);
  764.         }
  765.  
  766.         // create the actual node
  767.         IFlowNode::SActivationInfo activationInfo(this, id, pUserData);
  768.         IFlowNodePtr pNode = CreateNodeOfType(&activationInfo, typeId);
  769.         if (!pNode)
  770.         {
  771.                 const char* typeName = m_pSys->GetTypeName(typeId);
  772.                 GameWarning("[flow] Couldn't create node of type: %s (node was to be %s)", typeName, sName.c_str());
  773.                 DeallocateId(id);
  774.                 return R((CFlowData*)NULL, InvalidFlowNodeId);
  775.         }
  776.  
  777.         for (size_t i = 0; i != m_hooks.size(); ++i)
  778.         {
  779.                 if (!m_hooks[i]->CreatedNode(id, sName.c_str(), typeId, pNode))
  780.                 {
  781.                         for (size_t j = 0; j < i; j++)
  782.                                 m_hooks[j]->CancelCreatedNode(id, sName.c_str(), typeId, pNode);
  783.  
  784.                         DeallocateId(id);
  785.                         return R((CFlowData*)NULL, InvalidFlowNodeId);
  786.                 }
  787.         }
  788.  
  789.         m_nodeNameToId.insert(std::make_pair(sName, id));
  790.         m_flowData[id] = CFlowData(pNode, sName, typeId);
  791.         m_bEdgesSorted = false; // need to regenerate link data
  792.  
  793.         return R(&m_flowData[id], id);
  794. }
  795.  
  796. void CFlowGraphBase::RemoveNode(const char* name)
  797. {
  798.         std::map<string, TFlowNodeId>::iterator iter = m_nodeNameToId.find(name);
  799.         if (iter == m_nodeNameToId.end())
  800.         {
  801.                 GameWarning("[flow] No node named %s", name);
  802.                 return;
  803.         }
  804.         RemoveNode(iter->second);
  805. }
  806.  
  807. void CFlowGraphBase::RemoveNode(TFlowNodeId id)
  808. {
  809.         if (!ValidateNode(id))
  810.         {
  811.                 GameWarning("[flow] Trying to remove non-existant flow node %d", id);
  812.                 return;
  813.         }
  814.  
  815.         // remove any referring edges
  816.         EnsureSortedEdges();
  817.         std::vector<SEdge>::iterator firstRemoveIter = std::remove_if(m_edges.begin(), m_edges.end(), SEdgeHasNode(id));
  818.         for (std::vector<SEdge>::iterator iter = firstRemoveIter; iter != m_edges.end(); ++iter)
  819.         {
  820.                 IFlowNode::SActivationInfo info(this);
  821.                 info.myID = iter->fromNode;
  822.                 info.connectPort = iter->fromPort;
  823.                 m_flowData[iter->fromNode].GetNode()->ProcessEvent(IFlowNode::eFE_DisconnectOutputPort, &info);
  824.                 info.myID = iter->toNode;
  825.                 info.connectPort = iter->toPort;
  826.                 m_flowData[iter->toNode].GetNode()->ProcessEvent(IFlowNode::eFE_DisconnectInputPort, &info);
  827.         }
  828.         m_edges.erase(firstRemoveIter, m_edges.end());
  829.  
  830.         DeallocateId(id);
  831.  
  832.         RemoveNodeFromActivationArray(id, m_firstModifiedNode, m_modifiedNodes);
  833.         RemoveNodeFromActivationArray(id, m_firstActivatingNode, m_activatingNodes);
  834.         RemoveNodeFromActivationArray(id, m_firstFinalActivatingNode, m_finalActivatingNodes);
  835.         SetRegularlyUpdated(id, false);
  836.         m_bEdgesSorted = false;
  837. }
  838.  
  839. //////////////////////////////////////////////////////////////////////////
  840. bool CFlowGraphBase::SetNodeName(TFlowNodeId id, const char* sName)
  841. {
  842.         if (id < m_flowData.size())
  843.         {
  844.                 // avoid duplicate names
  845.                 for (size_t i = 0; i < m_flowData.size(); ++i)
  846.                 {
  847.                         if (m_flowData[i].GetName() == sName)
  848.                         {
  849.                                 GameWarning("Can't rename flownode: name %s already in use", sName);
  850.                                 return false;
  851.                         }
  852.                 }
  853.  
  854.                 m_flowData[id].SetName(sName);
  855.                 return true;
  856.         }
  857.  
  858.         return false;
  859. }
  860.  
  861. //////////////////////////////////////////////////////////////////////////
  862. const char* CFlowGraphBase::GetNodeName(TFlowNodeId id)
  863. {
  864.         if (id < m_flowData.size())
  865.         {
  866.                 return m_flowData[id].GetName().c_str();
  867.         }
  868.         return "";
  869. }
  870.  
  871. //////////////////////////////////////////////////////////////////////////
  872. TFlowNodeTypeId CFlowGraphBase::GetNodeTypeId(TFlowNodeId id)
  873. {
  874.         if (id < m_flowData.size())
  875.         {
  876.                 return m_flowData[id].GetTypeId();
  877.         }
  878.         return InvalidFlowNodeTypeId;
  879. }
  880.  
  881. //////////////////////////////////////////////////////////////////////////
  882. const char* CFlowGraphBase::GetNodeTypeName(TFlowNodeId id)
  883. {
  884.         if (id < m_flowData.size())
  885.         {
  886.                 TFlowNodeTypeId typeId = m_flowData[id].GetTypeId();
  887.                 return m_pSys->GetTypeInfo(typeId).name.c_str();
  888.         }
  889.         return "";
  890. }
  891.  
  892. //////////////////////////////////////////////////////////////////////////
  893. TFlowNodeId CFlowGraphBase::AllocateId()
  894. {
  895.         TFlowNodeId id = InvalidFlowNodeId;
  896.  
  897.         if (m_deallocatedIds.empty())
  898.         {
  899.                 if (m_flowData.size() < InvalidFlowNodeId)
  900.                 {
  901.                         id = TFlowNodeId(m_flowData.size());
  902.                         m_flowData.resize(m_flowData.size() + 1);
  903.                         m_activatingNodes.resize(m_flowData.size(), NOT_MODIFIED);
  904.                         m_modifiedNodes.resize(m_flowData.size(), NOT_MODIFIED);
  905.                         m_finalActivatingNodes.resize(m_flowData.size(), NOT_MODIFIED);
  906.                 }
  907.         }
  908.         else
  909.         {
  910.                 id = m_deallocatedIds.back();
  911.                 m_deallocatedIds.pop_back();
  912.         }
  913.  
  914.         return id;
  915. }
  916.  
  917. void CFlowGraphBase::DeallocateId(TFlowNodeId id)
  918. {
  919.         if (!ValidateNode(id))
  920.                 return;
  921.  
  922.         m_nodeNameToId.erase(m_flowData[id].GetName());
  923.  
  924.         m_flowData[id] = CFlowData();
  925.         m_userData.erase(id);
  926.         m_deallocatedIds.push_back(id);
  927. }
  928.  
  929. void CFlowGraphBase::SetUserData(TFlowNodeId id, const XmlNodeRef& data)
  930. {
  931.         m_userData[id] = data;
  932. }
  933.  
  934. XmlNodeRef CFlowGraphBase::GetUserData(TFlowNodeId id)
  935. {
  936.         return m_userData[id];
  937. }
  938.  
  939. void CFlowGraphBase::Update()
  940. {
  941.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  942.  
  943.         // Disabled or Deactivated or Suspended flow graphs shouldn't be updated!
  944.         if (m_bEnabled == false || m_bActive == false || m_bSuspended || m_bNeedsUpdating == false)
  945.                 return;
  946.  
  947.         if (m_bNeedsInitialize)
  948.                 InitializeValues();
  949.  
  950. #ifndef _RELEASE
  951.         CFlowSystem::FGProfile.graphsUpdated++;
  952. #endif //_RELEASE
  953.  
  954.         m_bInUpdate = true;
  955.  
  956.         IFlowNode::SActivationInfo activationInfo(this, 0);
  957.  
  958.         // initially, we need to send an "Update yourself" event to anyone that
  959.         // has asked for it
  960.         // we explicitly check if empty to save STL the hassle of deallocating
  961.         // memory that we'll use again quite soon ;)
  962.         if (!m_regularUpdates.empty())
  963.         {
  964.                 m_activatingUpdates = m_regularUpdates;
  965.                 for (RegularUpdates::const_iterator iter = m_activatingUpdates.begin();
  966.                      iter != m_activatingUpdates.end(); ++iter)
  967.                 {
  968. #ifndef _RELEASE
  969.                         CFlowSystem::FGProfile.nodeUpdates++;
  970. #endif //_RELEASE
  971.  
  972.                         CRY_ASSERT(ValidateNode(*iter));
  973.                         activationInfo.myID = *iter;
  974.                         activationInfo.pEntity = GetIEntityForNode(activationInfo.myID);
  975.                         m_flowData[*iter].Update(&activationInfo);
  976.                 }
  977.         }
  978.  
  979.         DoUpdate(IFlowNode::eFE_Activate);
  980.  
  981.         m_bNeedsUpdating = false;
  982.         if (!m_regularUpdates.empty())
  983.                 NeedUpdate();
  984.  
  985.         m_bInUpdate = false;
  986. }
  987.  
  988. void CFlowGraphBase::InitializeValues()
  989. {
  990.         //      FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  991.  
  992.         // flush activation list
  993.         DoUpdate(IFlowNode::eFE_DontDoAnythingWithThisPlease);
  994.  
  995.         // reset graph tokens
  996.         for (TGraphTokens::const_iterator it = m_graphTokens.begin(), end = m_graphTokens.end(); it != end; ++it)
  997.         {
  998.                 SGraphToken token = *it;
  999.                 ResetGraphToken(token);
  1000.         }
  1001.  
  1002.         // Initially suspended flow graphs should never be initialized nor updated!
  1003.         if (m_bSuspended || m_bActive == false || m_bEnabled == false)
  1004.                 return;
  1005.  
  1006.         for (std::vector<CFlowData>::iterator iter = m_flowData.begin(); iter != m_flowData.end(); ++iter)
  1007.         {
  1008.                 if (!iter->IsValid())
  1009.                         continue;
  1010.  
  1011.                 iter->FlagInputPorts();
  1012.                 ActivateNodeInt((TFlowNodeId)(iter - m_flowData.begin()));
  1013.         }
  1014.  
  1015.         m_bNeedsInitialize = true;
  1016.  
  1017.         DoUpdate(IFlowNode::eFE_Initialize);
  1018.  
  1019.         m_bNeedsInitialize = false;
  1020. }
  1021.  
  1022. void CFlowGraphBase::DoUpdate(IFlowNode::EFlowEvent event)
  1023. {
  1024.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
  1025.  
  1026.         IFlowNode::SActivationInfo activationInfo(this, 0);
  1027.  
  1028.         CRY_ASSERT(m_firstFinalActivatingNode == END_OF_MODIFIED_LIST);
  1029.  
  1030.         // we repeat updating until there have been too many iterations (in which
  1031.         // case we emit a warning) or until all possible activations have
  1032.         // completed
  1033.         int numLoops = 0;
  1034.         static const int MAX_LOOPS = 256;
  1035.         while (m_firstModifiedNode != END_OF_MODIFIED_LIST && numLoops++ < MAX_LOOPS)
  1036.         {
  1037.                 // swap the two sets of modified nodes -- ensures that we are reentrant
  1038.                 // wrt being able to call PerformActivation in response to being
  1039.                 // activated
  1040.                 m_activatingNodes.swap(m_modifiedNodes);
  1041.                 CRY_ASSERT(m_firstActivatingNode == END_OF_MODIFIED_LIST);
  1042.                 m_firstActivatingNode = m_firstModifiedNode;
  1043.                 m_firstModifiedNode = END_OF_MODIFIED_LIST;
  1044.  
  1045.                 // traverse the list of modified nodes
  1046.                 while (m_firstActivatingNode != END_OF_MODIFIED_LIST)
  1047.                 {
  1048.                         activationInfo.myID = m_firstActivatingNode;
  1049.                         activationInfo.pEntity = GetIEntityForNode(activationInfo.myID);
  1050.                         m_flowData[m_firstActivatingNode].Activated(&activationInfo, event);
  1051. #if defined(ALLOW_MULTIPLE_PORT_ACTIVATIONS_PER_UPDATE)
  1052.                         TCachedActivations::iterator iter = m_cachedActivations.find(m_firstActivatingNode);
  1053.  
  1054.                         if (iter != m_cachedActivations.end())
  1055.                         {
  1056.                                 TCachedPortActivations::const_iterator iterPortActivation = iter->second.begin();
  1057.  
  1058.                                 for (; iterPortActivation != iter->second.end(); ++iterPortActivation)
  1059.                                 {
  1060.                                         if (iterPortActivation->portID != InvalidFlowPortId)
  1061.                                         {
  1062.                                                 m_flowData[m_firstActivatingNode].ActivateInputPort(iterPortActivation->portID, iterPortActivation->value);
  1063.                                                 ActivateNodeInt(m_firstActivatingNode);
  1064.                                         }
  1065.                                         else
  1066.                                         {
  1067.                                                 activationInfo.pEntity = GetIEntityForNode(activationInfo.myID);
  1068.                                                 m_flowData[m_firstActivatingNode].Activated(&activationInfo, event);
  1069.                                         }
  1070.                                 }
  1071.  
  1072.                                 m_cachedActivations.erase(iter);
  1073.                         }
  1074. #endif
  1075.                         TFlowNodeId nextId = m_activatingNodes[m_firstActivatingNode];
  1076.                         m_activatingNodes[m_firstActivatingNode] = NOT_MODIFIED;
  1077.                         m_firstActivatingNode = nextId;
  1078.  
  1079. #ifndef _RELEASE
  1080.                         CFlowSystem::FGProfile.nodeActivations++;
  1081. #endif //_RELEASE
  1082.                 }
  1083.         }
  1084.         if (numLoops >= MAX_LOOPS)
  1085.         {
  1086. #if defined (FLOW_DEBUG_PENDING_UPDATES)
  1087.                 CryLogAlways("[flow] CFlowGraphBase::DoUpdate: %s -> Reached maxLoops %d during event %d", m_debugName.c_str(), MAX_LOOPS, event);
  1088. #endif
  1089.                 if (event == IFlowNode::eFE_Initialize)
  1090.                 {
  1091.                         // flush pending activations when we exceed the number of maximum loops
  1092.                         // because then there are still nodes which have pending activations due to
  1093.                         // the Initialize event. So they would wrongly be activated during the next update
  1094.                         // round on a different event. That's why we flush
  1095.                         DoUpdate(IFlowNode::eFE_DontDoAnythingWithThisPlease);
  1096.                 }
  1097.         }
  1098.  
  1099.         while (m_firstFinalActivatingNode != END_OF_MODIFIED_LIST)
  1100.         {
  1101.                 activationInfo.myID = m_firstFinalActivatingNode;
  1102.                 activationInfo.pEntity = GetIEntityForNode(activationInfo.myID);
  1103.                 m_flowData[m_firstFinalActivatingNode].Activated(&activationInfo, (IFlowNode::EFlowEvent)(event + 1));
  1104.  
  1105.                 TFlowNodeId nextId = m_finalActivatingNodes[m_firstFinalActivatingNode];
  1106.                 m_finalActivatingNodes[m_firstFinalActivatingNode] = NOT_MODIFIED;
  1107.                 m_firstFinalActivatingNode = nextId;
  1108.  
  1109. #ifndef _RELEASE
  1110.                 CFlowSystem::FGProfile.nodeActivations++;
  1111. #endif //_RELEASE
  1112.         }
  1113.  
  1114.         // AlexL 02/06/06: When there are activations in a eFE_FinalActivate/eFE_FinalInitialize update
  1115.         // these activations are stored in the list, but the FlowGraph is not scheduled for a next update round
  1116.         // the normal update loop continues until all activations are handled or MAX_LOOPS is reached
  1117.         // the final activation update only runs once. this means, that activations from the final activation round
  1118.         // are delayed to the next frame!
  1119.         if (m_firstModifiedNode != END_OF_MODIFIED_LIST)
  1120.         {
  1121.                 NeedUpdate();
  1122.         }
  1123. }
  1124.  
  1125. //////////////////////////////////////////////////////////////////////////
  1126. void CFlowGraphBase::PrecacheResources()
  1127. {
  1128.         IFlowNode::SActivationInfo actInfo(this, 0);
  1129.         for (std::vector<CFlowData>::iterator it = m_flowData.begin(); it != m_flowData.end(); ++it)
  1130.         {
  1131.                 if (it->IsValid())
  1132.                 {
  1133.                         CFlowData& flowData = *it;
  1134.  
  1135.                         // Notify the Flowgraph to set its EntityId again so it can act on the entity now that it exists
  1136.                         actInfo.myID = (TFlowNodeId)(it - m_flowData.begin());
  1137.                         //actInfo.pEntity = GetIEntityForNode(actInfo.myID);
  1138.                         flowData.CompleteActivationInfo(&actInfo);
  1139.                         if (flowData.GetNode())
  1140.                                 flowData.GetNode()->ProcessEvent(IFlowNode::eFE_PrecacheResources, &actInfo);
  1141.                 }
  1142.         }
  1143. }
  1144.  
  1145. //////////////////////////////////////////////////////////////////////////
  1146.  
  1147. string CFlowGraphBase::GetGlobalNameForGraphToken(const string& tokenName) const
  1148. {
  1149.         // graph tokens are registered in the game token system using the format:
  1150.         //      'GraphToken.Graph<id>.<tokenName>'
  1151.         string globalName = "GraphToken.Graph";
  1152.  
  1153.         string temp;
  1154.         temp.Format("%u.", m_graphId);
  1155.         globalName += temp;
  1156.         globalName += tokenName;
  1157.  
  1158.         return globalName;
  1159. }
  1160.  
  1161. void CFlowGraphBase::RemoveGraphTokens()
  1162. {
  1163.         for (TGraphTokens::iterator it = m_graphTokens.begin(), end = m_graphTokens.end(); it != end; ++it)
  1164.         {
  1165.                 string globalName = GetGlobalNameForGraphToken(it->name);
  1166.  
  1167.                 IGameTokenSystem* pGTS = CCryAction::GetCryAction()->GetIGameTokenSystem();
  1168.                 if (pGTS)
  1169.                 {
  1170.                         IGameToken* pToken = pGTS->FindToken(globalName.c_str());
  1171.                         assert(pToken && ((pToken->GetFlags() & EGAME_TOKEN_GRAPHVARIABLE) != 0));
  1172.                         if (pToken)
  1173.                         {
  1174.                                 pGTS->DeleteToken(pToken);
  1175.                         }
  1176.                         else
  1177.                         {
  1178.                                 GameWarning("Attempted to remove nonexistent GraphToken: %s", globalName.c_str());
  1179.                         }
  1180.                 }
  1181.         }
  1182.  
  1183.         stl::free_container(m_graphTokens);
  1184. }
  1185.  
  1186. bool CFlowGraphBase::AddGraphToken(const IFlowGraph::SGraphToken& token)
  1187. {
  1188.         m_graphTokens.push_back(token);
  1189.  
  1190.         ResetGraphToken(token);
  1191.  
  1192.         return true;
  1193. }
  1194.  
  1195. size_t CFlowGraphBase::GetGraphTokenCount() const
  1196. {
  1197.         return m_graphTokens.size();
  1198. }
  1199.  
  1200. const IFlowGraph::SGraphToken* CFlowGraphBase::GetGraphToken(size_t index) const
  1201. {
  1202.         if (index < m_graphTokens.size())
  1203.         {
  1204.                 return &(m_graphTokens[index]);
  1205.         }
  1206.  
  1207.         return NULL;
  1208. }
  1209.  
  1210. void CFlowGraphBase::ResetGraphToken(const IFlowGraph::SGraphToken& token)
  1211. {
  1212.         string globalName = GetGlobalNameForGraphToken(token.name);
  1213.  
  1214.         IGameTokenSystem* pGTS = CCryAction::GetCryAction()->GetIGameTokenSystem();
  1215.         if (pGTS)
  1216.         {
  1217.                 TFlowInputData temp;
  1218.                 switch (token.type)
  1219.                 {
  1220.                 case eFDT_String:
  1221.                         {
  1222.                                 static string emptyString = "";
  1223.                                 temp.SetValueWithConversion(emptyString);
  1224.                                 break;
  1225.                         }
  1226.  
  1227.                 case eFDT_Bool:
  1228.                         temp.SetValueWithConversion(false);
  1229.                         break;
  1230.  
  1231.                 case eFDT_Int:
  1232.                         temp.SetValueWithConversion(0);
  1233.                         break;
  1234.  
  1235.                 case eFDT_EntityId:
  1236.                         temp.SetValueWithConversion(0);
  1237.                         break;
  1238.  
  1239.                 case eFDT_Float:
  1240.                         temp.SetValueWithConversion(0.0f);
  1241.                         break;
  1242.  
  1243.                 case eFDT_Vec3:
  1244.                         temp.SetValueWithConversion(Vec3(ZERO));
  1245.                         break;
  1246.                 }
  1247.                 IGameToken* pToken = pGTS->SetOrCreateToken(globalName.c_str(), temp);
  1248.                 if (pToken)
  1249.                         pToken->SetFlags(pToken->GetFlags() | EGAME_TOKEN_GRAPHVARIABLE);
  1250.         }
  1251. }
  1252.  
  1253. //////////////////////////////////////////////////////////////////////////
  1254.  
  1255. void CFlowGraphBase::RequestFinalActivation(TFlowNodeId id)
  1256. {
  1257.         CRY_ASSERT(m_bInUpdate);
  1258.         if (m_finalActivatingNodes[id] == NOT_MODIFIED)
  1259.         {
  1260.                 m_finalActivatingNodes[id] = m_firstFinalActivatingNode;
  1261.                 m_firstFinalActivatingNode = id;
  1262.         }
  1263. }
  1264.  
  1265. void CFlowGraphBase::SortEdges()
  1266. {
  1267.         std::sort(m_edges.begin(), m_edges.end());
  1268.         m_edges.erase(std::unique(m_edges.begin(), m_edges.end()), m_edges.end());
  1269.  
  1270.         for (std::vector<CFlowData>::iterator iter = m_flowData.begin(); iter != m_flowData.end(); ++iter)
  1271.         {
  1272.                 if (!iter->IsValid())
  1273.                         continue;
  1274.                 for (int i = 0; i < iter->GetNumOutputs(); i++)
  1275.                 {
  1276.                         SEdge firstEdge((TFlowNodeId)(iter - m_flowData.begin()), i, 0, 0);
  1277.                         std::vector<SEdge>::const_iterator iterEdge = std::lower_bound(m_edges.begin(), m_edges.end(), firstEdge);
  1278.                         iter->SetOutputFirstEdge(i, (TFlowNodeId)(iterEdge - m_edges.begin()));
  1279.                 }
  1280.         }
  1281.  
  1282.         m_bEdgesSorted = true;
  1283. }
  1284.  
  1285. void CFlowGraphBase::RemoveNodeFromActivationArray(TFlowNodeId id, TFlowNodeId& front, std::vector<TFlowNodeId>& array)
  1286. {
  1287.         if (front == id)
  1288.         {
  1289.                 front = array[id];
  1290.                 array[id] = NOT_MODIFIED;
  1291.         }
  1292.         else if (array[id] == NOT_MODIFIED)
  1293.         {
  1294.                 // nothing to do
  1295.         }
  1296.         else
  1297.         {
  1298.                 // the really tricky case... the node that was removed is midway through
  1299.                 // the activation list... so we'll need to remove it the hard way
  1300.                 TFlowNodeId current = front;
  1301.                 TFlowNodeId previous = NOT_MODIFIED;
  1302.                 while (current != id)
  1303.                 {
  1304.                         CRY_ASSERT(current != END_OF_MODIFIED_LIST);
  1305.                         CRY_ASSERT(current != NOT_MODIFIED);
  1306.                         previous = current;
  1307.                         current = array[current];
  1308.                 }
  1309.                 CRY_ASSERT(previous != NOT_MODIFIED);
  1310.                 CRY_ASSERT(current == id);
  1311.                 array[previous] = array[current];
  1312.                 array[current] = NOT_MODIFIED;
  1313.         }
  1314.  
  1315.         CRY_ASSERT(array[id] == NOT_MODIFIED);
  1316. }
  1317.  
  1318. void CFlowGraphBase::SetRegularlyUpdated(TFlowNodeId id, bool bUpdated)
  1319. {
  1320.         if (bUpdated)
  1321.         {
  1322.                 stl::push_back_unique(m_regularUpdates, id);
  1323.                 NeedUpdate();
  1324.         }
  1325.         else
  1326.                 stl::find_and_erase(m_regularUpdates, id);
  1327. }
  1328.  
  1329. void CFlowGraphBase::ActivatePortAny(SFlowAddress addr, const TFlowInputData& value)
  1330. {
  1331.         PerformActivation(addr, value);
  1332. }
  1333.  
  1334. void CFlowGraphBase::ActivatePortCString(SFlowAddress addr, const char* cstr)
  1335. {
  1336.         TFlowInputData value;
  1337.         value.Set(string(cstr));
  1338.         PerformActivation(addr, value);
  1339. }
  1340.  
  1341. //////////////////////////////////////////////////////////////////////////
  1342. bool CFlowGraphBase::SetInputValue(TFlowNodeId node, TFlowPortId port, const TFlowInputData& value)
  1343. {
  1344.         if (!ValidateNode(node))
  1345.                 return false;
  1346.         CFlowData& data = m_flowData[node];
  1347.         if (!data.ValidatePort(port, false))
  1348.                 return false;
  1349.         const bool bOk = data.SetInputPort(port, value);
  1350.         if(bOk)
  1351.         {
  1352.                 int entityOffset = (data.HasEntity() ? 1 : 0);
  1353.                 IFlowNode::SActivationInfo info(this, node);
  1354.                 info.connectPort = port - entityOffset;
  1355.                 info.pInputPorts = data.GetInputPort(entityOffset);
  1356.  
  1357.                 data.GetNode()->ProcessEvent(IFlowNode::eFE_EditorInputPortDataSet, &info);
  1358.         }
  1359.         return bOk;
  1360. }
  1361.  
  1362. //////////////////////////////////////////////////////////////////////////
  1363. const TFlowInputData* CFlowGraphBase::GetInputValue(TFlowNodeId node, TFlowPortId port)
  1364. {
  1365.         if (!ValidateNode(node))
  1366.                 return 0;
  1367.         CFlowData& data = m_flowData[node];
  1368.         if (!data.ValidatePort(port, false))
  1369.                 return 0;
  1370.         return data.GetInputPort(port);
  1371. }
  1372.  
  1373. bool CFlowGraphBase::GetActivationInfo(const char* nodeName, IFlowNode::SActivationInfo& actInfo)
  1374. {
  1375.         const TFlowNodeId nodeID = stl::find_in_map(m_nodeNameToId, nodeName, InvalidFlowNodeId);
  1376.  
  1377.         if (nodeID == InvalidFlowNodeId)
  1378.                 return false;
  1379.  
  1380.         actInfo.pGraph = this;
  1381.         actInfo.myID = nodeID;
  1382.         actInfo.pEntity = GetIEntityForNode(nodeID);
  1383.         m_flowData[nodeID].CompleteActivationInfo(&actInfo);
  1384.  
  1385.         return true;
  1386. }
  1387.  
  1388. //////////////////////////////////////////////////////////////////////////
  1389. bool CFlowGraphBase::SerializeXML(const XmlNodeRef& root, bool reading)
  1390. {
  1391.         if (reading)
  1392.         {
  1393.                 bool ok = ReadXML(root);
  1394.                 if (!ok)
  1395.                         m_pSys->NotifyCriticalLoadingError();
  1396.                 return ok;
  1397.         }
  1398.         else
  1399.                 return WriteXML(root);
  1400. }
  1401.  
  1402. void CFlowGraphBase::FlowLoadError(const char* format, ...)
  1403. {
  1404.         if (!format)
  1405.                 return;
  1406.         char buffer[MAX_WARNING_LENGTH];
  1407.         va_list args;
  1408.         va_start(args, format);
  1409.         cry_vsprintf(buffer, format, args);
  1410.         va_end(args);
  1411.         IEntity* pEnt = gEnv->pEntitySystem->GetEntity(GetGraphEntity(0));
  1412.  
  1413.         // fg_abortOnLoadError:
  1414.         // 2 --> abort
  1415.         // 1 [!=0 && !=2] --> dialog
  1416.         // 0 --> log only
  1417.         if (CFlowSystemCVars::Get().m_abortOnLoadError == 2 && gEnv->IsEditor() == false)
  1418.         {
  1419.                 if (m_pAIAction != 0)
  1420.                         CryFatalError("[flow] %s : %s", m_pAIAction->GetName(), buffer);
  1421.                 else
  1422.                         CryFatalError("[flow] %s : %s", pEnt ? pEnt->GetName() : "<noname>", buffer);
  1423.         }
  1424.         else
  1425.         {
  1426.                 if (m_pAIAction != 0)
  1427.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "[flow] %s : %s", m_pAIAction->GetName(), buffer);
  1428.                 else
  1429.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "[flow] %s : %s", pEnt ? pEnt->GetName() : "<noname>", buffer);
  1430.         }
  1431. }
  1432.  
  1433. bool CFlowGraphBase::ReadXML(const XmlNodeRef& root)
  1434. {
  1435.         Cleanup();
  1436.  
  1437.         if (!root)
  1438.                 return false;
  1439.  
  1440.         bool ok = false;
  1441.  
  1442.         while (true)
  1443.         {
  1444.                 int i;
  1445.  
  1446.                 XmlNodeRef nodes = root->findChild("Nodes");
  1447.                 if (!nodes)
  1448.                 {
  1449.                         FlowLoadError("No [Nodes] XML child");
  1450.                         break;
  1451.                 }
  1452.  
  1453. #ifdef FLOW_DEBUG_ID_MAPPING
  1454.                 {
  1455.                         IEntity* pEnt = gEnv->pEntitySystem->GetEntity(GetGraphEntity(0));
  1456.                         if (m_pAIAction != 0)
  1457.                                 CryLogAlways("[flow] %s 0x%p: Loading FG", m_pAIAction->GetName(), this);
  1458.                         else
  1459.                                 CryLogAlways("[flow] %s 0x%p: Loading FG", pEnt ? pEnt->GetName() : "<noname>", this);
  1460.                 }
  1461. #endif
  1462.  
  1463.                 int nNodes = nodes->getChildCount();
  1464.  
  1465.                 int nConcreteNodes = 0;
  1466.  
  1467.                 for (i = 0; i < nNodes; i++)
  1468.                 {
  1469.                         XmlNodeRef node = nodes->getChild(i);
  1470.                         const char* type = node->getAttr(NODE_TYPE_ATTR);
  1471.                         const char* name = node->getAttr(NODE_NAME_ATTR);
  1472.                         if (0 == strcmp(type, "_comment"))
  1473.                                 continue;
  1474.                         if (0 == strcmp(type, "_commentbox"))
  1475.                                 continue;
  1476.                         ++nConcreteNodes;
  1477.                 }
  1478.  
  1479.                 m_flowData.reserve(nConcreteNodes);
  1480.                 m_activatingNodes.reserve(nConcreteNodes);
  1481.                 m_modifiedNodes.reserve(nConcreteNodes);
  1482.                 m_finalActivatingNodes.reserve(nConcreteNodes);
  1483.  
  1484.                 IFlowNode::SActivationInfo actInfo(this, 0);
  1485.                 for (i = 0; i < nNodes; i++)
  1486.                 {
  1487.                         XmlNodeRef node = nodes->getChild(i);
  1488.                         const char* type = node->getAttr(NODE_TYPE_ATTR);
  1489.                         const char* name = node->getAttr(NODE_NAME_ATTR);
  1490.                         if (0 == strcmp(type, "_comment"))
  1491.                                 continue;
  1492.                         if (0 == strcmp(type, "_commentbox"))
  1493.                                 continue;
  1494.                         TFlowNodeTypeId typeId = m_pSys->GetTypeId(type);
  1495.                         std::pair<CFlowData*, TFlowNodeId> info = CreateNodeInt(typeId, name);
  1496.                         if (!info.first || info.second == InvalidFlowNodeId)
  1497.                         {
  1498.                                 FlowLoadError("Failed to create node '%s' of type '%s' - FLOWGRAPH DISCARDED", name, type);
  1499.                                 break;
  1500.                         }
  1501.                         actInfo.myID = info.second;
  1502.  
  1503. #ifdef FLOW_DEBUG_ID_MAPPING
  1504.                         {
  1505.                                 IEntity* pEnt = gEnv->pEntitySystem->GetEntity(GetGraphEntity(0));
  1506.                                 if (m_pAIAction != 0)
  1507.                                         CryLogAlways("[flow] %s : Mapping ID=%s to internal ID=%d", m_pAIAction->GetName(), name, actInfo.myID);
  1508.                                 else
  1509.                                         CryLogAlways("[flow] %s : Mapping ID=%s to internal ID=%d", pEnt ? pEnt->GetName() : "<noname>", name, actInfo.myID);
  1510.                         }
  1511. #endif
  1512.  
  1513.                         if (!info.first->SerializeXML(&actInfo, node, true))
  1514.                         {
  1515.                                 FlowLoadError("Failed to load node %s of type %s - FLOWGRAPH DISCARDED", name, type);
  1516.                                 DeallocateId(info.second);
  1517.                                 break;
  1518.                         }
  1519.                 }
  1520.                 if (i != nNodes) // didn't load all of the nodes
  1521.                 {
  1522.                         FlowLoadError("Did not load all nodes (%d/%d nodes) - FLOWGRAPH DISCARDED", i, nNodes);
  1523.                         break;
  1524.                 }
  1525.  
  1526.                 XmlNodeRef edges = root->findChild("Edges");
  1527.                 if (!edges)
  1528.                 {
  1529.                         FlowLoadError("No [Edges] XML child");
  1530.                         break;
  1531.                 }
  1532.                 int nEdges = edges->getChildCount();
  1533.  
  1534.                 int nConcreteEdges = 0;
  1535.  
  1536.                 for (i = 0; i < nEdges; i++)
  1537.                 {
  1538.                         XmlNodeRef edge = edges->getChild(i);
  1539.                         if (strcmp(edge->getTag(), "Edge"))
  1540.                                 break;
  1541.  
  1542.                         SFlowAddress from = ResolveAddress(edge->getAttr("nodeOut"), edge->getAttr("portOut"), true);
  1543.                         SFlowAddress to = ResolveAddress(edge->getAttr("nodeIn"), edge->getAttr("portIn"), false);
  1544.  
  1545.                         bool edgeEnabled;
  1546.                         if (((edge->getAttr("enabled", edgeEnabled) == false) || edgeEnabled) && ValidateLink(from, to))
  1547.                                 ++nConcreteEdges;
  1548.                 }
  1549.  
  1550.                 m_edges.reserve(nConcreteEdges);
  1551.  
  1552.                 for (i = 0; i < nEdges; i++)
  1553.                 {
  1554.                         XmlNodeRef edge = edges->getChild(i);
  1555.                         if (strcmp(edge->getTag(), "Edge"))
  1556.                                 break;
  1557.                         SFlowAddress from = ResolveAddress(edge->getAttr("nodeOut"), edge->getAttr("portOut"), true);
  1558.                         SFlowAddress to = ResolveAddress(edge->getAttr("nodeIn"), edge->getAttr("portIn"), false);
  1559.                         bool edgeEnabled;
  1560.                         if (edge->getAttr("enabled", edgeEnabled) == false)
  1561.                                 edgeEnabled = true;
  1562.  
  1563.                         if (edgeEnabled)
  1564.                         {
  1565.                                 if (!LinkNodes(from, to))
  1566.                                 {
  1567.                                         FlowLoadError("Can't link edge <%s,%s> to <%s,%s> - FLOWGRAPH DISCARDED",
  1568.                                                       edge->getAttr("nodeOut"), edge->getAttr("portOut"),
  1569.                                                       edge->getAttr("nodeIn"), edge->getAttr("portIn"));
  1570.                                         break;
  1571.                                 }
  1572.                         }
  1573.                         else
  1574.                         {
  1575. #if defined (FLOW_DEBUG_DISABLED_EDGES)
  1576.                                 IEntity* pEnt = gEnv->pEntitySystem->GetEntity(GetGraphEntity(0));
  1577.                                 if (m_pAIAction != 0)
  1578.                                 {
  1579.                                         CryLogAlways("[flow] Disabled edge %d for AI action graph '%s' <%s,%s> to <%s,%s>", i, m_pAIAction->GetName(),
  1580.                                                      edge->getAttr("nodeOut"), edge->getAttr("portOut"),
  1581.                                                      edge->getAttr("nodeIn"), edge->getAttr("portIn"));
  1582.                                 }
  1583.                                 else
  1584.                                 {
  1585.                                         GameWarning("[flow] Disabled edge %d for entity %d '%s' <%s,%s> to <%s,%s>", i, GetGraphEntity(0),
  1586.                                                     pEnt ? pEnt->GetName() : "<NULL>",
  1587.                                                     edge->getAttr("nodeOut"), edge->getAttr("portOut"),
  1588.                                                     edge->getAttr("nodeIn"), edge->getAttr("portIn"));
  1589.                                 }
  1590. #endif
  1591.                         }
  1592.                 }
  1593.                 if (i != nEdges) // didn't load all edges
  1594.                 {
  1595.                         FlowLoadError("Did not load all edges (%d/%d edges) - FLOWGRAPH DISCARDED", i, nEdges);
  1596.                         break;
  1597.                 }
  1598.  
  1599.                 XmlNodeRef graphTokens = root->findChild("GraphTokens");
  1600.                 if (graphTokens)
  1601.                 {
  1602.                         int nTokens = graphTokens->getChildCount();
  1603.                         RemoveGraphTokens();
  1604.                         for (int j = 0; j < nTokens; ++j)
  1605.                         {
  1606.                                 XmlString tokenName;
  1607.                                 int tokenType;
  1608.  
  1609.                                 XmlNodeRef tokenXml = graphTokens->getChild(j);
  1610.                                 tokenXml->getAttr("Name", tokenName);
  1611.                                 tokenXml->getAttr("Type", tokenType);
  1612.  
  1613.                                 IFlowGraph::SGraphToken token;
  1614.                                 token.name = tokenName.c_str();
  1615.                                 token.type = (EFlowDataTypes)tokenType;
  1616.  
  1617.                                 AddGraphToken(token);
  1618.                         }
  1619.                 }
  1620.  
  1621.                 ok = true;
  1622.                 break;
  1623.         }
  1624.  
  1625.         if (root->getAttr("enabled", m_bEnabled) == false)
  1626.                 m_bEnabled = true;
  1627.  
  1628.         if (!ok)
  1629.                 Cleanup();
  1630.         else
  1631.                 NeedInitialize();
  1632.  
  1633.         PrecacheResources();
  1634.  
  1635.         return ok;
  1636. }
  1637.  
  1638. bool CFlowGraphBase::WriteXML(const XmlNodeRef& root)
  1639. {
  1640.         XmlNodeRef nodes = root->createNode("Nodes");
  1641.         for (std::vector<CFlowData>::iterator iter = m_flowData.begin(); iter != m_flowData.end(); ++iter)
  1642.         {
  1643.                 if (iter->IsValid())
  1644.                 {
  1645.                         XmlNodeRef node = nodes->createNode(m_pSys->GetTypeName(iter->GetNodeTypeId()));
  1646.                         nodes->addChild(node);
  1647.  
  1648.                         node->setAttr(NODE_NAME_ATTR, iter->GetName().c_str());
  1649.                         IFlowNode::SActivationInfo info(this, (TFlowNodeId)(iter - m_flowData.begin()));
  1650.                         if (!iter->SerializeXML(&info, node, false))
  1651.                                 return false;
  1652.                 }
  1653.         }
  1654.  
  1655.         XmlNodeRef edges = root->createNode("Edges");
  1656.         for (std::vector<SEdge>::const_iterator iter = m_edges.begin(); iter != m_edges.end(); ++iter)
  1657.         {
  1658.                 string from = PrettyAddress(SFlowAddress(iter->fromNode, iter->fromPort, true));
  1659.                 string to = PrettyAddress(SFlowAddress(iter->toNode, iter->toPort, false));
  1660.  
  1661.                 XmlNodeRef edge = edges->createNode("Edge");
  1662.                 edges->addChild(edge);
  1663.                 edge->setAttr("from", from.c_str());
  1664.                 edge->setAttr("to", to.c_str());
  1665.         }
  1666.  
  1667.         XmlNodeRef tokens = root->createNode("GraphTokens");
  1668.         for (int i = 0; i < m_graphTokens.size(); ++i)
  1669.         {
  1670.                 XmlNodeRef tokenXml = tokens->createNode("Token");
  1671.                 tokens->addChild(tokenXml);
  1672.                 tokenXml->setAttr("Name", m_graphTokens[i].name);
  1673.                 tokenXml->setAttr("Type", m_graphTokens[i].type);
  1674.         }
  1675.  
  1676.         root->addChild(nodes);
  1677.         root->addChild(edges);
  1678.         root->addChild(tokens);
  1679.         root->setAttr("enabled", m_bEnabled);
  1680.         return true;
  1681. }
  1682.  
  1683. IFlowNodePtr CFlowGraphBase::CreateNodeOfType(IFlowNode::SActivationInfo* pActInfo, TFlowNodeTypeId typeId)
  1684. {
  1685.         IFlowNodePtr pPtr;
  1686.         for (size_t i = 0; i < m_hooks.size() && !pPtr; ++i)
  1687.                 pPtr = m_hooks[i]->CreateNode(pActInfo, typeId);
  1688.         if (!pPtr)
  1689.                 pPtr = m_pSys->CreateNodeOfType(pActInfo, typeId);
  1690.         return pPtr;
  1691. }
  1692.  
  1693. IFlowNodeIteratorPtr CFlowGraphBase::CreateNodeIterator()
  1694. {
  1695.         return new CNodeIterator(this);
  1696. }
  1697.  
  1698. IFlowEdgeIteratorPtr CFlowGraphBase::CreateEdgeIterator()
  1699. {
  1700.         return new CEdgeIterator(this);
  1701. }
  1702.  
  1703. bool CFlowGraphBase::IsOutputConnected(SFlowAddress addr)
  1704. {
  1705.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
  1706.  
  1707.         CRY_ASSERT(ValidateAddress(addr));
  1708.  
  1709.         bool connected = false;
  1710.         if (addr.isOutput)
  1711.         {
  1712.                 EnsureSortedEdges();
  1713.  
  1714.                 /*
  1715.                    SEdge firstEdge(addr.node, addr.port, 0, 0);
  1716.                    std::vector<SEdge>::const_iterator iter = std::lower_bound( m_edges.begin(), m_edges.end(), firstEdge );
  1717.                  */
  1718.                 std::vector<SEdge>::const_iterator iter = m_edges.begin() + m_flowData[addr.node].GetOutputFirstEdge(addr.port);
  1719.                 connected = iter != m_edges.end() && iter->fromNode == addr.node && iter->fromPort == addr.port;
  1720.         }
  1721.  
  1722.         return connected;
  1723. }
  1724.  
  1725. void CFlowGraphBase::Serialize(TSerialize ser)
  1726. {
  1727.         // When reading, we clear the regular updates before nodes are serialized
  1728.         // because their serialization could request to be scheduled as regularUpdate
  1729.         if (ser.IsReading())
  1730.         {
  1731.                 // clear regulars
  1732.                 m_regularUpdates.resize(0);
  1733.         }
  1734.  
  1735.         ser.Value("needsInitialize", m_bNeedsInitialize);
  1736.         ser.Value("enabled", m_bEnabled);
  1737.         ser.Value("suspended", m_bSuspended);
  1738.         ser.Value("active", m_bActive);
  1739.  
  1740.         std::vector<string> activatedNodes;
  1741.         if (ser.IsWriting())
  1742.         {
  1743.                 // get activations
  1744.                 for (TFlowNodeId id = m_firstModifiedNode; id != END_OF_MODIFIED_LIST; id = m_modifiedNodes[id])
  1745.                         activatedNodes.push_back(m_flowData[id].GetName());
  1746.         }
  1747.         ser.Value("activatedNodes", activatedNodes);
  1748.         if (ser.IsReading())
  1749.         {
  1750.                 // flush modified nodes
  1751.                 m_firstModifiedNode = END_OF_MODIFIED_LIST;
  1752.                 m_modifiedNodes.resize(0);
  1753.                 m_modifiedNodes.resize(m_flowData.size(), NOT_MODIFIED);
  1754.                 // reactivate
  1755.                 for (std::vector<string>::const_iterator iter = activatedNodes.begin(); iter != activatedNodes.end(); ++iter)
  1756.                 {
  1757.                         TFlowNodeId id = stl::find_in_map(m_nodeNameToId, *iter, InvalidFlowNodeId);
  1758.                         if (id != InvalidFlowNodeId)
  1759.                                 ActivateNodeInt(id);
  1760.                         else
  1761.                                 GameWarning("[flow] Flow graph has changed between save-games");
  1762.                 }
  1763.         }
  1764.  
  1765.         IFlowNode::SActivationInfo activationInfo(this, 0);
  1766.         if (ser.IsWriting())
  1767.         {
  1768.                 uint32 nodeCount = 0;
  1769.                 for (std::vector<CFlowData>::iterator iter = m_flowData.begin(), end = m_flowData.end(); iter != end; ++iter)
  1770.                 {
  1771.                         if (iter->IsValid())
  1772.                         {
  1773.                                 activationInfo.myID = (TFlowNodeId)(iter - m_flowData.begin());
  1774.                                 activationInfo.pEntity = GetIEntityForNode(activationInfo.myID);
  1775.                                 ser.BeginGroup("Node");
  1776.                                 ser.Value("id", iter->GetName());
  1777.                                 iter->Serialize(&activationInfo, ser);
  1778.                                 ser.EndGroup();
  1779.  
  1780.                                 ++nodeCount;
  1781.                         }
  1782.                 }
  1783.                 ser.Value("nodeCount", nodeCount);
  1784.         }
  1785.         else
  1786.         {
  1787.                 uint32 nodeCount;
  1788.                 ser.Value("nodeCount", nodeCount);
  1789.                 if (nodeCount != m_flowData.size())
  1790.                 {
  1791.                         // there are nodes in the MAP which are not in the SaveGame
  1792.                         // or there are nodes in the SaveGame which are not in the map
  1793.                         // can happen if level.pak got changed after savegame creation!
  1794.                         // this comment is just to remind, that this case exists.
  1795.                         // GameSerialize.cpp will send an eFE_Initialize after level load, but before serialize,
  1796.                         // so these nodes get at least initialized
  1797.                         // AlexL: 18/04/2007
  1798.                 }
  1799.  
  1800.                 while (nodeCount--)
  1801.                 {
  1802.                         ser.BeginGroup("Node");
  1803.                         string name;
  1804.                         ser.Value("id", name);
  1805.                         TFlowNodeId id = stl::find_in_map(m_nodeNameToId, name, InvalidFlowNodeId);
  1806.                         /*
  1807.                            if (id == InvalidFlowNodeId) {
  1808.                            std::map<string, TFlowNodeId>::const_iterator iter = m_nodeNameToId.begin();
  1809.                            CryLogAlways("Map Contents:");
  1810.                            while (iter != m_nodeNameToId.end())
  1811.                            {
  1812.                             CryLogAlways("Map: %s", iter->first.c_str());
  1813.                            ++iter;
  1814.                            }
  1815.                            }
  1816.                          */
  1817.                         if (id != InvalidFlowNodeId)
  1818.                         {
  1819.                                 activationInfo.myID = id;
  1820.                                 activationInfo.pEntity = GetIEntityForNode(activationInfo.myID);
  1821.                                 m_flowData[id].Serialize(&activationInfo, ser);
  1822.                         }
  1823.                         else
  1824.                                 GameWarning("[flow] Flowgraph '%s' has changed between save-games. Can't resolve node named '%s'", InternalGetDebugName(), name.c_str());
  1825.                         ser.EndGroup();
  1826.                 }
  1827.         }
  1828.  
  1829.         // regular updates
  1830.         std::vector<CryFixedStringT<32>> regularUpdates;
  1831.         regularUpdates.reserve(m_regularUpdates.size());
  1832.         if (ser.IsWriting())
  1833.         {
  1834.                 RegularUpdates::const_iterator iter(m_regularUpdates.begin());
  1835.                 RegularUpdates::const_iterator end(m_regularUpdates.end());
  1836.                 while (iter != end)
  1837.                 {
  1838.                         regularUpdates.push_back(m_flowData[*iter].GetName().c_str());
  1839.                         ++iter;
  1840.                 }
  1841.         }
  1842.  
  1843.         ser.Value("regularUpdates", regularUpdates);
  1844.         if (ser.IsReading())
  1845.         {
  1846.                 // reserve some space in the m_regularUpdates vector
  1847.                 // as there might have already been added some this is somewhat conservative
  1848.                 // regularUpdates.size()+m_regularUpdates.size() would be maximum, but most of the time
  1849.                 // too much
  1850.                 m_regularUpdates.reserve(regularUpdates.size());
  1851.  
  1852.                 // re-fill regular updates
  1853.                 for (std::vector<CryFixedStringT<32>>::const_iterator iter = regularUpdates.begin(); iter != regularUpdates.end(); ++iter)
  1854.                 {
  1855.                         TFlowNodeId id = stl::find_in_map(m_nodeNameToId, CONST_TEMP_STRING(iter->c_str()), InvalidFlowNodeId);
  1856.                         if (id != InvalidFlowNodeId)
  1857.                                 SetRegularlyUpdated(id, true);
  1858.                         else
  1859.                                 GameWarning("[flow] Flow graph has changed between save-games");
  1860.                 }
  1861.         }
  1862.  
  1863.         // when we load a flowgraph and it didn't have activations so far
  1864.         // it is still in the initialized state
  1865.         // so we need to mark this graph to be updated, so it gets initialized
  1866.         if (ser.IsReading() && m_bNeedsInitialize)
  1867.         {
  1868.                 NeedUpdate();
  1869.         }
  1870. }
  1871.  
  1872. //////////////////////////////////////////////////////////////////////////
  1873. void CFlowGraphBase::PostSerialize()
  1874. {
  1875.         IFlowNode::SActivationInfo activationInfo(this, 0);
  1876.         for (std::vector<CFlowData>::iterator iter = m_flowData.begin(), end = m_flowData.end(); iter != end; ++iter)
  1877.         {
  1878.                 if (iter->IsValid())
  1879.                 {
  1880.                         activationInfo.myID = (TFlowNodeId)(iter - m_flowData.begin());
  1881.                         activationInfo.pEntity = GetIEntityForNode(activationInfo.myID);
  1882.                         iter->PostSerialize(&activationInfo);
  1883.                 }
  1884.         }
  1885. }
  1886.  
  1887. //////////////////////////////////////////////////////////////////////////
  1888. IEntity* CFlowGraphBase::GetIEntityForNode(TFlowNodeId flowNodeId)
  1889. {
  1890.         CRY_ASSERT(ValidateNode(flowNodeId));
  1891.         EntityId id = m_flowData[flowNodeId].GetEntityId();
  1892.         if (id == 0)
  1893.                 return 0;
  1894.  
  1895.         if (id == (EntityId)EFLOWNODE_ENTITY_ID_GRAPH1)
  1896.                 id = m_graphEntityId[0];
  1897.         else if (id == (EntityId)EFLOWNODE_ENTITY_ID_GRAPH2)
  1898.                 id = m_graphEntityId[1];
  1899.  
  1900.         IEntity* pEntity = m_pEntitySystem->GetEntity(id);
  1901.         return pEntity;
  1902. }
  1903.  
  1904. //////////////////////////////////////////////////////////////////////////
  1905. void CFlowGraphBase::NotifyFlowSystemDestroyed()
  1906. {
  1907.         m_pSys = NULL;
  1908. }
  1909.  
  1910. //////////////////////////////////////////////////////////////////////////
  1911. void CFlowGraphBase::RegisterInspector(IFlowGraphInspectorPtr pInspector)
  1912. {
  1913.         stl::push_back_unique(m_inspectors, pInspector);
  1914. }
  1915.  
  1916. //////////////////////////////////////////////////////////////////////////
  1917. void CFlowGraphBase::UnregisterInspector(IFlowGraphInspectorPtr pInspector)
  1918. {
  1919.         stl::find_and_erase(m_inspectors, pInspector);
  1920. }
  1921.  
  1922. //////////////////////////////////////////////////////////////////////////
  1923. void CFlowGraphBase::GetGraphStats(int& nodeCount, int& edgeCount)
  1924. {
  1925.         nodeCount = m_flowData.size();
  1926.         edgeCount = m_edges.size();
  1927.         size_t cool = m_nodeNameToId.size();
  1928. }
  1929.  
  1930. //////////////////////////////////////////////////////////////////////////
  1931. void CFlowGraphBase::OnEntityReused(IEntity* pEntity, SEntitySpawnParams& params)
  1932. {
  1933.         for (std::vector<CFlowData>::iterator it = m_flowData.begin(); it != m_flowData.end(); ++it)
  1934.         {
  1935.                 if (it->IsValid())
  1936.                 {
  1937.                         CFlowData& flowData = *it;
  1938.  
  1939.                         if (params.id == flowData.GetEntityId() && flowData.GetCurrentForwardingEntity() == 0) // if is forwarding to an spawned entity, we dont want to do all this
  1940.                         {
  1941.                                 // Notify the Flowgraph to set its EntityId again so it can act on the entity now that it exists
  1942.                                 IFlowNode::SActivationInfo actInfo(this, 0);
  1943.                                 actInfo.myID = (TFlowNodeId)(it - m_flowData.begin());
  1944.                                 actInfo.pEntity = GetIEntityForNode(actInfo.myID);
  1945.                                 flowData.CompleteActivationInfo(&actInfo);
  1946.                                 flowData.GetNode()->ProcessEvent(IFlowNode::eFE_SetEntityId, &actInfo);
  1947.                         }
  1948.                 }
  1949.         }
  1950. }
  1951.  
  1952. //////////////////////////////////////////////////////////////////////////
  1953. void CFlowGraphBase::OnEntityIdChanged(EntityId oldId, EntityId newId)
  1954. {
  1955.         for (std::vector<CFlowData>::iterator it = m_flowData.begin(); it != m_flowData.end(); ++it)
  1956.         {
  1957.                 if (it->IsValid())
  1958.                 {
  1959.                         CFlowData& flowData = *it;
  1960.  
  1961.                         if (oldId == flowData.GetEntityId()) // if this node was holding the old EntityID, update it
  1962.                         {
  1963.                                 IFlowNode::SActivationInfo actInfo(this, 0);
  1964.                                 actInfo.myID = (TFlowNodeId)(it - m_flowData.begin());
  1965.                                 m_flowData[actInfo.myID].SetEntityId(newId);
  1966.                                 actInfo.pEntity = GetIEntityForNode(actInfo.myID);
  1967.                                 flowData.CompleteActivationInfo(&actInfo);
  1968.                                 flowData.GetNode()->ProcessEvent(IFlowNode::eFE_SetEntityId, &actInfo);
  1969.                         }
  1970.                 }
  1971.         }
  1972. }
  1973.  
  1974. //////////////////////////////////////////////////////////////////////////
  1975. // executes any pending forwarding.
  1976. // this needs to be done explicitly, because otherwise some nodes may stay in "toforward" state but never actually be forwarded (this happens for example if they dont receive any input)
  1977. void CFlowGraphBase::UpdateForwardings()
  1978. {
  1979.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
  1980.  
  1981.         std::vector<CFlowData>::iterator endIt = m_flowData.end();
  1982.         for (std::vector<CFlowData>::iterator it = m_flowData.begin(); it != endIt; ++it)
  1983.         {
  1984.                 if (it->IsValid())
  1985.                 {
  1986.                         CFlowData& flowData = *it;
  1987.  
  1988.                         IFlowNode::SActivationInfo actInfo(this, 0);
  1989.                         actInfo.myID = (TFlowNodeId)(it - m_flowData.begin());
  1990.                         actInfo.pEntity = GetIEntityForNode(actInfo.myID);
  1991.                         flowData.DoForwardingIfNeed(&actInfo);
  1992.                 }
  1993.         }
  1994. }
  1995.  
  1996. //////////////////////////////////////////////////////////////////////////
  1997. void CFlowGraphBase::GetMemoryUsage(ICrySizer* s) const
  1998. {
  1999.         {
  2000.                 SIZER_SUBCOMPONENT_NAME(s, "FlowGraphLocal");
  2001.                 s->AddObject(m_modifiedNodes);
  2002.                 s->AddObject(m_activatingNodes);
  2003.                 s->AddObject(m_finalActivatingNodes);
  2004.                 s->AddObject(m_deallocatedIds);
  2005.                 s->AddObject(m_edges);
  2006.                 s->AddObject(m_regularUpdates);
  2007.                 s->AddObject(m_activatingNodes);
  2008.                 s->AddObject(m_nodeNameToId);
  2009.                 s->AddObject(m_hooks);
  2010.                 s->AddObject(m_userData);
  2011.                 s->AddObject(m_inspectors);
  2012.         }
  2013.  
  2014.         {
  2015.                 SIZER_SUBCOMPONENT_NAME(s, "FlowData-FlowData-Struct");
  2016.                 s->AddObject(m_flowData);
  2017.         }
  2018.  
  2019.         {
  2020.                 SIZER_SUBCOMPONENT_NAME(s, "NodeNameToIdMap");
  2021.                 s->AddObject(m_nodeNameToId);
  2022.         }
  2023. }
  2024.  
  2025. void CFlowGraph::GetMemoryUsage(ICrySizer* s) const
  2026. {
  2027.         s->Add(*this);
  2028.         CFlowGraphBase::GetMemoryUsage(s);
  2029. }
  2030.  
  2031. #if defined(__GNUC__)
  2032. const TFlowNodeId CFlowGraphBase::NOT_MODIFIED = ~TFlowNodeId(0);
  2033. const TFlowNodeId CFlowGraphBase::END_OF_MODIFIED_LIST = NOT_MODIFIED - 1;
  2034. #endif
  2035.  
downloadFlowGraph.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