BVB Source Codes

CRYENGINE Show FlowGraphDebugger.cpp Source code

Return Download CRYENGINE: download FlowGraphDebugger.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   FlowGraphDebugger.cpp
  5. //  Version:     v1.00
  6. //  Created:     13/09/2011 by Sascha Hoba.
  7. //  Description:
  8. // -------------------------------------------------------------------------
  9. //  History:
  10. //
  11. ////////////////////////////////////////////////////////////////////////////
  12.  
  13. #include "StdAfx.h"
  14.  
  15. #ifdef INCLUDE_FLOWGRAPHDEBUGGER_EXTENSION
  16.  
  17.         #include "FlowGraphDebugger.h"
  18.         #include "FlowData.h"
  19.         #include "FlowGraph.h"
  20.         #include <CryFlowGraph/IFlowGraphModuleManager.h>
  21.         #include <CryFlowGraph/IFlowGraphDebugger.h>
  22.  
  23. CRYREGISTER_SINGLETON_CLASS(CFlowGraphDebugger)
  24.  
  25. CFlowGraphDebugger::CFlowGraphDebugger() :
  26.         m_DebugInfo(),
  27.         m_BreakpointHit(false),
  28.         m_RePerformActivation(false),
  29.         m_bStepModeEnabled(false),
  30.         m_BreakPoint(),
  31.         m_DelayedActivations(),
  32.         m_Listeners(1)
  33. {
  34. }
  35.  
  36. CFlowGraphDebugger::~CFlowGraphDebugger()
  37. {
  38.         m_DebugInfo.clear();
  39.         m_Listeners.Clear();
  40.         m_IgnoredFlowgraphs.clear();
  41. }
  42.  
  43. void CFlowGraphDebugger::ClearBreakpoints()
  44. {
  45.         m_DebugInfo.clear();
  46. }
  47.  
  48. bool CFlowGraphDebugger::AddBreakpoint(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr)
  49. {
  50.         if (!pFlowgraph)
  51.                 return false;
  52.  
  53.         if (!CheckForValidIDs(addr.node, addr.port))
  54.                 return false;
  55.  
  56.         bool bAddedBreakpoint = false;
  57.  
  58.         TDebugInfo::iterator iter = m_DebugInfo.find(pFlowgraph);
  59.         if (iter != m_DebugInfo.end())
  60.         {
  61.                 TFlowNodesDebugInfo* flownodesDebugInfo = &(*iter).second;
  62.                 TFlowNodesDebugInfo::iterator iterNode = flownodesDebugInfo->find(addr.node);
  63.  
  64.                 if (iterNode != flownodesDebugInfo->end())
  65.                 {
  66.                         //we are already debugging this node, check if we have to add a new port
  67.                         SBreakPoints* breakPoints = &(*iterNode).second;
  68.  
  69.                         TFlowPortIDS* flowPortIDS = NULL;
  70.                         if (addr.isOutput)
  71.                                 flowPortIDS = &breakPoints->outputPorts;
  72.                         else
  73.                                 flowPortIDS = &breakPoints->inputPorts;
  74.  
  75.                         for (std::vector<SBreakPointPortInfo>::const_iterator iterBreakpoint = (*flowPortIDS).begin(); iterBreakpoint != (*flowPortIDS).end(); ++iterBreakpoint)
  76.                         {
  77.                                 if (iterBreakpoint->portID == addr.port)
  78.                                 {
  79.                                         CryWarning(VALIDATOR_MODULE_FLOWGRAPH, VALIDATOR_WARNING, "Port %u for Flownode %u is already in debug list [CFlowgraphDebugger::AddBreakPoint]", addr.port, addr.node);
  80.                                         return false;
  81.                                 }
  82.                         }
  83.  
  84.                         SBreakPointPortInfo portInfo;
  85.                         portInfo.portID = addr.port;
  86.                         flowPortIDS->push_back(portInfo);
  87.                         bAddedBreakpoint = true;
  88.                 }
  89.                 else
  90.                 {
  91.                         //we don't debug this flownode yet, so add the flownode and port
  92.                         SBreakPoints breakPoints;
  93.  
  94.                         TFlowPortIDS flowPortIDS;
  95.                         SBreakPointPortInfo portInfo;
  96.                         portInfo.portID = addr.port;
  97.                         flowPortIDS.push_back(portInfo);
  98.  
  99.                         if (addr.isOutput)
  100.                                 breakPoints.outputPorts = flowPortIDS;
  101.                         else
  102.                                 breakPoints.inputPorts = flowPortIDS;
  103.  
  104.                         flownodesDebugInfo->insert(std::make_pair(addr.node, breakPoints));
  105.  
  106.                         bAddedBreakpoint = true;
  107.                 }
  108.         }
  109.         else
  110.         {
  111.                 // we don't debug any flownode of this flowgraph yet
  112.                 TFlowNodesDebugInfo flownodesDebugInfo;
  113.                 SBreakPoints breakPoints;
  114.  
  115.                 TFlowPortIDS flowPortIDS;
  116.                 SBreakPointPortInfo portInfo;
  117.                 portInfo.portID = addr.port;
  118.                 flowPortIDS.push_back(portInfo);
  119.  
  120.                 if (addr.isOutput)
  121.                         breakPoints.outputPorts = flowPortIDS;
  122.                 else
  123.                         breakPoints.inputPorts = flowPortIDS;
  124.  
  125.                 flownodesDebugInfo.insert(std::make_pair(addr.node, breakPoints));
  126.                 m_DebugInfo.insert(std::make_pair(pFlowgraph, flownodesDebugInfo));
  127.  
  128.                 bAddedBreakpoint = true;
  129.         }
  130.  
  131.         if (bAddedBreakpoint)
  132.         {
  133.                 for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  134.                 {
  135.                         SBreakPoint breakpoint;
  136.                         breakpoint.flowGraph = pFlowgraph;
  137.                         breakpoint.addr = addr;
  138.  
  139.                         notifier->OnBreakpointAdded(breakpoint);
  140.                 }
  141.         }
  142.  
  143.         return bAddedBreakpoint;
  144. }
  145.  
  146. bool CFlowGraphDebugger::RemoveBreakpoint(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr)
  147. {
  148.         TDebugInfo::iterator iterDebugInfo = m_DebugInfo.find(pFlowgraph);
  149.         if (iterDebugInfo != m_DebugInfo.end())
  150.         {
  151.                 TFlowNodesDebugInfo* flownodesDebugInfo = &(*iterDebugInfo).second;
  152.                 TFlowNodesDebugInfo::iterator iterNode = flownodesDebugInfo->find(addr.node);
  153.  
  154.                 if (iterNode != flownodesDebugInfo->end())
  155.                 {
  156.                         SBreakPoints* breakPointInfo = &(*iterNode).second;
  157.                         TFlowPortIDS* flowPortIDS = NULL;
  158.  
  159.                         if (addr.isOutput)
  160.                                 flowPortIDS = &breakPointInfo->outputPorts;
  161.                         else
  162.                                 flowPortIDS = &breakPointInfo->inputPorts;
  163.  
  164.                         const int numBreakpoints = breakPointInfo->inputPorts.size() + breakPointInfo->outputPorts.size();
  165.  
  166.                         TFlowPortIDS::iterator iter = flowPortIDS->begin();
  167.                         while (iter != flowPortIDS->end())
  168.                         {
  169.                                 if ((*iter).portID == addr.port)
  170.                                 {
  171.                                         if (numBreakpoints == 1)
  172.                                         {
  173.                                                 // we are about to delete the last port for this flownode from the debug list,
  174.                                                 // just remove the whole flownode information from the list
  175.                                                 flownodesDebugInfo->erase(iterNode);
  176.  
  177.                                                 if (flownodesDebugInfo->empty())
  178.                                                         m_DebugInfo.erase(iterDebugInfo);
  179.                                         }
  180.                                         else
  181.                                         {
  182.                                                 flowPortIDS->erase(iter);
  183.                                         }
  184.  
  185.                                         for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  186.                                         {
  187.                                                 SBreakPoint breakpoint;
  188.                                                 breakpoint.flowGraph = pFlowgraph;
  189.                                                 breakpoint.addr = addr;
  190.  
  191.                                                 notifier->OnBreakpointRemoved(breakpoint);
  192.                                         }
  193.  
  194.                                         return true;
  195.                                 }
  196.                                 ++iter;
  197.                         }
  198.                 }
  199.                 else
  200.                 {
  201.                         CryWarning(VALIDATOR_MODULE_FLOWGRAPH, VALIDATOR_WARNING, "Flownode %u is not in debug list [CFlowgraphDebugger::RemoveBreakPoint]", addr.node);
  202.                         return false;
  203.                 }
  204.         }
  205.  
  206.         CryWarning(VALIDATOR_MODULE_FLOWGRAPH, VALIDATOR_WARNING, "Port %u of Flownode %u is not in debug list [CFlowgraphDebugger::RemoveBreakPoint]", addr.port, addr.node);
  207.         return false;
  208. }
  209.  
  210. bool CFlowGraphDebugger::RemoveAllBreakpointsForNode(IFlowGraphPtr pFlowgraph, TFlowNodeId nodeID)
  211. {
  212.         CRY_ASSERT(nodeID != InvalidFlowNodeId);
  213.  
  214.         if (nodeID == InvalidFlowNodeId)
  215.                 return false;
  216.  
  217.         TDebugInfo::iterator iterDebugInfo = m_DebugInfo.find(pFlowgraph);
  218.         if (iterDebugInfo != m_DebugInfo.end())
  219.         {
  220.                 TFlowNodesDebugInfo* flownodesDebugInfo = &(*iterDebugInfo).second;
  221.                 TFlowNodesDebugInfo::iterator iterNode = flownodesDebugInfo->find(nodeID);
  222.  
  223.                 if (iterNode != flownodesDebugInfo->end())
  224.                 {
  225.                         flownodesDebugInfo->erase(iterNode);
  226.  
  227.                         for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  228.                         {
  229.                                 notifier->OnAllBreakpointsRemovedForNode(pFlowgraph, nodeID);
  230.                         }
  231.  
  232.                         return true;
  233.                 }
  234.         }
  235.         else
  236.         {
  237.                 CryWarning(VALIDATOR_MODULE_FLOWGRAPH, VALIDATOR_WARNING, "Flownode %u is not in debug list [CFlowgraphDebugger::RemoveBreakPointsForNode]", nodeID);
  238.                 return false;
  239.         }
  240.  
  241.         return false;
  242. }
  243.  
  244. bool CFlowGraphDebugger::RemoveAllBreakpointsForGraph(IFlowGraphPtr pFlowgraph)
  245. {
  246.         TDebugInfo::iterator iterDebugInfo = m_DebugInfo.find(pFlowgraph);
  247.         if (iterDebugInfo != m_DebugInfo.end())
  248.         {
  249.                 m_DebugInfo.erase(iterDebugInfo);
  250.  
  251.                 for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  252.                 {
  253.                         notifier->OnAllBreakpointsRemovedForGraph(pFlowgraph);
  254.                 }
  255.                 return true;
  256.         }
  257.  
  258.         return false;
  259. }
  260.  
  261. bool CFlowGraphDebugger::HasBreakpoint(IFlowGraphPtr pFlowGraph, const SFlowAddress& addr) const
  262. {
  263.         CRY_ASSERT(NULL != pFlowGraph);
  264.  
  265.         if (!pFlowGraph)
  266.                 return false;
  267.  
  268.         const SBreakPointPortInfo* breakpointInfo = GetBreakpointInfo(pFlowGraph, addr);
  269.  
  270.         if (breakpointInfo)
  271.         {
  272.                 return true;
  273.         }
  274.         else
  275.         {
  276.                 // no breakpoints at all for this flownode
  277.                 return false;
  278.         }
  279.  
  280.         return false;
  281. }
  282.  
  283. bool CFlowGraphDebugger::HasBreakpoint(IFlowGraphPtr pFlowGraph, TFlowNodeId nodeID) const
  284. {
  285.         CRY_ASSERT(NULL != pFlowGraph);
  286.  
  287.         if (!pFlowGraph)
  288.                 return false;
  289.  
  290.         CRY_ASSERT(nodeID != InvalidFlowNodeId);
  291.  
  292.         if (nodeID == InvalidFlowNodeId)
  293.                 return false;
  294.  
  295.         pFlowGraph = GetRootGraph(pFlowGraph);
  296.  
  297.         TDebugInfo::const_iterator iterDebugInfo = m_DebugInfo.find(pFlowGraph);
  298.  
  299.         if (iterDebugInfo != m_DebugInfo.end())
  300.         {
  301.                 const TFlowNodesDebugInfo* flownodesDebugInfo = &(*iterDebugInfo).second;
  302.                 TFlowNodesDebugInfo::const_iterator iterNode = flownodesDebugInfo->find(nodeID);
  303.  
  304.                 if (iterNode != flownodesDebugInfo->end())
  305.                 {
  306.                         // this flownode has at least one breakpoint
  307.                         return true;
  308.                 }
  309.  
  310.                 // no breakpoints at all for this flownode
  311.                 return false;
  312.         }
  313.  
  314.         return false;
  315. }
  316.  
  317. bool CFlowGraphDebugger::HasBreakpoint(IFlowGraphPtr pFlowGraph) const
  318. {
  319.         CRY_ASSERT(NULL != pFlowGraph);
  320.  
  321.         if (!pFlowGraph)
  322.                 return false;
  323.  
  324.         pFlowGraph = GetRootGraph(pFlowGraph);
  325.  
  326.         TDebugInfo::const_iterator iter = m_DebugInfo.find(pFlowGraph);
  327.  
  328.         if (iter != m_DebugInfo.end())
  329.                 return true;
  330.  
  331.         return false;
  332. }
  333.  
  334. bool CFlowGraphDebugger::CheckForValidIDs(TFlowNodeId nodeID, TFlowPortId portID) const
  335. {
  336.         if (nodeID == InvalidFlowNodeId)
  337.                 return false;
  338.  
  339.         if (portID == InvalidFlowPortId)
  340.                 return false;
  341.  
  342.         if (m_BreakPoint.addr.node == nodeID && m_BreakPoint.addr.port == portID)
  343.                 return false;
  344.  
  345.         if (m_BreakPoint.fromAddr.node == nodeID && m_BreakPoint.fromAddr.port == portID)
  346.                 return false;
  347.  
  348.         return true;
  349. }
  350.  
  351. bool CFlowGraphDebugger::PerformActivation(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr, const TFlowInputData& value)
  352. {
  353.         if (IsFlowgraphIgnored(pFlowgraph) || IsFlowgraphTypeIgnored(pFlowgraph->GetType()) || !CheckForValidIDs(addr.node, addr.port))
  354.                 return true;
  355.  
  356.         if (m_BreakpointHit && !m_RePerformActivation)
  357.         {
  358.                 // The system tries to activate a port after a breakpoint was hit, so cache the activation in a deque.
  359.                 // This is a valid case as it is allowed to activate 2 output ports in a row:
  360.                 // ActivateOutput(eOP_Done,...);
  361.                 // ActivateOutput(eOP_Succeded,...);
  362.                 // If the first activation results in a breakpoint the second (if it also results in a breakpoint)
  363.                 // would override the first, even though we paused the game/flowsystem.
  364.                 SBreakPoint breakpoint;
  365.                 breakpoint.addr = addr;
  366.                 breakpoint.flowGraph = pFlowgraph;
  367.                 breakpoint.value = value;
  368.                 breakpoint.type = eBT_Output_Without_Edges;
  369.  
  370.                 m_DelayedActivations.push_back(breakpoint);
  371.                 return false;
  372.         }
  373.  
  374.         const SBreakPointPortInfo* breakpointInfo = GetBreakpointInfo(pFlowgraph, addr);
  375.  
  376.         if (!breakpointInfo)
  377.         {
  378.                 if (!m_bStepModeEnabled)
  379.                         return true;
  380.         }
  381.  
  382.         const bool bIsEnabled = breakpointInfo ? breakpointInfo->bIsEnabled : m_bStepModeEnabled;
  383.         const bool bIsTracepoint = breakpointInfo ? breakpointInfo->bIsTracepoint : false;
  384.  
  385.         if (bIsEnabled)
  386.         {
  387.                 if (!bIsTracepoint)
  388.                 {
  389.                         InvalidateBreakpoint();
  390.                         // Special case: This output has no edges, so it will never activate any input port.
  391.                         // We still want to be able to pause the game/flowsystem if an output port with no
  392.                         // edges was activated.
  393.                         m_BreakPoint.flowGraph = pFlowgraph;
  394.                         m_BreakPoint.addr = addr;
  395.                         m_BreakPoint.value = value;
  396.                         m_BreakPoint.type = eBT_Output_Without_Edges;
  397.  
  398.                         m_BreakpointHit = true;
  399.  
  400.                         for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  401.                         {
  402.                                 notifier->OnBreakpointHit(m_BreakPoint);
  403.                         }
  404.  
  405.                         return false;
  406.                 }
  407.                 else
  408.                 {
  409.                         for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  410.                         {
  411.                                 STracePoint tracepoint;
  412.                                 tracepoint.addr = addr;
  413.                                 tracepoint.flowGraph = pFlowgraph;
  414.                                 tracepoint.value = value;
  415.                                 notifier->OnTracepointHit(tracepoint);
  416.                         }
  417.                 }
  418.         }
  419.  
  420.         return true;
  421. }
  422.  
  423. bool CFlowGraphDebugger::PerformActivation(IFlowGraphPtr pFlowgraph, int edgeIndex, const SFlowAddress& fromAddr, const SFlowAddress& toAddr, const TFlowInputData& value)
  424. {
  425.         if (m_BreakpointHit && !m_RePerformActivation)
  426.         {
  427.                 // The system tries to activate a port after a breakpoint was hit, so cache the activation in a deque.
  428.                 // This is a valid case as it is allowed to activate 2 output ports in a row:
  429.                 // ActivateOutput(eOP_Done,...);
  430.                 // ActivateOutput(eOP_Succeded,...);
  431.                 // If the first activation results in a breakpoint the second (if it also results in a breakpoint)
  432.                 // would override the first, even though we paused the game/flowsystem.
  433.                 SBreakPoint breakpoint;
  434.                 breakpoint.addr = fromAddr;
  435.                 breakpoint.flowGraph = pFlowgraph;
  436.                 breakpoint.value = value;
  437.                 breakpoint.type = eBT_Output;
  438.                 breakpoint.edgeIndex = edgeIndex;
  439.  
  440.                 m_DelayedActivations.push_back(breakpoint);
  441.                 return false;
  442.         }
  443.  
  444.         bool bInformListeners = false;
  445.  
  446.         const SBreakPointPortInfo* breakpointInfoFrom = GetBreakpointInfo(pFlowgraph, fromAddr);
  447.         const bool bFromIsEnabled = breakpointInfoFrom ? breakpointInfoFrom->bIsEnabled : m_bStepModeEnabled;
  448.         const bool bFromIsTracepoint = breakpointInfoFrom ? breakpointInfoFrom->bIsTracepoint : false;
  449.  
  450.         const SBreakPointPortInfo* breakpointInfoTo = GetBreakpointInfo(pFlowgraph, toAddr);
  451.         const bool bToIsEnabled = breakpointInfoTo ? breakpointInfoTo->bIsEnabled : m_bStepModeEnabled;
  452.         const bool bToIsTracepoint = breakpointInfoTo ? breakpointInfoTo->bIsTracepoint : false;
  453.  
  454.         const bool bIgnoredGraph = (IsFlowgraphIgnored(pFlowgraph) || IsFlowgraphTypeIgnored(pFlowgraph->GetType()));
  455.         if (!bIgnoredGraph && CheckForValidIDs(fromAddr.node, fromAddr.port) && (breakpointInfoFrom || m_bStepModeEnabled))
  456.         {
  457.                 if (bFromIsEnabled)
  458.                 {
  459.                         if (!bFromIsTracepoint)
  460.                         {
  461.                                 InvalidateBreakpoint();
  462.                                 // First check if the from address has a breakpoint (output port)
  463.                                 m_BreakPoint.addr = fromAddr;
  464.                                 m_BreakPoint.flowGraph = pFlowgraph;
  465.                                 m_BreakPoint.value = value;
  466.                                 m_BreakPoint.type = eBT_Output;
  467.                                 m_BreakPoint.edgeIndex = edgeIndex;
  468.  
  469.                                 bInformListeners = true;
  470.                         }
  471.                         else
  472.                         {
  473.                                 for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  474.                                 {
  475.                                         STracePoint tracepoint;
  476.                                         tracepoint.addr = fromAddr;
  477.                                         tracepoint.flowGraph = pFlowgraph;
  478.                                         tracepoint.value = value;
  479.                                         notifier->OnTracepointHit(tracepoint);
  480.                                 }
  481.                         }
  482.                 }
  483.         }
  484.         else if (!bIgnoredGraph && CheckForValidIDs(toAddr.node, toAddr.port) && (breakpointInfoTo || m_bStepModeEnabled))
  485.         {
  486.                 if (bToIsEnabled)
  487.                 {
  488.                         if (!bToIsTracepoint)
  489.                         {
  490.                                 InvalidateBreakpoint();
  491.                                 // Now check if the to address has a breakpoint (input port)
  492.                                 m_BreakPoint.addr = toAddr;
  493.                                 m_BreakPoint.fromAddr = fromAddr;
  494.                                 m_BreakPoint.flowGraph = pFlowgraph;
  495.                                 m_BreakPoint.value = value;
  496.                                 m_BreakPoint.type = eBT_Input;
  497.                                 m_BreakPoint.edgeIndex = edgeIndex;
  498.  
  499.                                 bInformListeners = true;
  500.                         }
  501.                         else
  502.                         {
  503.                                 for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  504.                                 {
  505.                                         STracePoint tracepoint;
  506.                                         tracepoint.addr = toAddr;
  507.                                         tracepoint.flowGraph = pFlowgraph;
  508.                                         tracepoint.value = value;
  509.                                         notifier->OnTracepointHit(tracepoint);
  510.                                 }
  511.                         }
  512.                 }
  513.         }
  514.  
  515.         if (bInformListeners)
  516.         {
  517.                 m_BreakpointHit = true;
  518.  
  519.                 for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  520.                 {
  521.                         notifier->OnBreakpointHit(m_BreakPoint);
  522.                 }
  523.  
  524.                 return false;
  525.         }
  526.  
  527.         return true;
  528. }
  529.  
  530. bool CFlowGraphDebugger::RePerformActivation()
  531. {
  532.         if (m_BreakPoint.type == eBT_Output_Without_Edges)
  533.         {
  534.                 // Special case: Output port with no edges never activates any input port, simply check for delayed
  535.                 // activations.
  536.                 return CheckForDelayedActivations();
  537.         }
  538.         else if (m_BreakPoint.type == eBT_Output || m_BreakPoint.type == eBT_Input)
  539.         {
  540.                 // Output port with edges, simply go through all edges connected to this output port and activate the
  541.                 // connected input ports with the stored value.
  542.                 m_RePerformActivation = true;
  543.  
  544.                 CRY_ASSERT(m_BreakPoint.flowGraph != 0);
  545.                 m_BreakPoint.flowGraph->EnsureSortedEdges();
  546.  
  547.                 IFlowEdgeIteratorPtr pEdgeIter = m_BreakPoint.flowGraph->CreateEdgeIterator();
  548.  
  549.                 if (pEdgeIter)
  550.                 {
  551.                         IFlowEdgeIterator::Edge edge;
  552.  
  553.                         if (m_BreakPoint.type == eBT_Input)
  554.                         {
  555.                                 CFlowData* pData = static_cast<CFlowData*>(m_BreakPoint.flowGraph->GetNodeData(m_BreakPoint.fromAddr.node));
  556.  
  557.                                 if (pData)
  558.                                 {
  559.                                         int firstEdge = pData->GetOutputFirstEdge(m_BreakPoint.fromAddr.port) + m_BreakPoint.edgeIndex;
  560.  
  561.                                         while (firstEdge > 0 && pEdgeIter->Next(edge))
  562.                                         {
  563.                                                 --firstEdge;
  564.                                         }
  565.                                 }
  566.                         }
  567.  
  568.                         int edgeIndex = m_BreakPoint.edgeIndex;
  569.                         bool bPerform = true;
  570.                         while (pEdgeIter->Next(edge) && bPerform)
  571.                         {
  572.                                 if (m_BreakPoint.type == eBT_Output && edge.fromNodeId == m_BreakPoint.addr.node && edge.fromPortId == m_BreakPoint.addr.port)
  573.                                 {
  574.                                         if (!TryActivatePort(m_BreakPoint, edge, bPerform, edgeIndex))
  575.                                         {
  576.                                                 return false;
  577.                                         }
  578.                                         ++edgeIndex;
  579.                                 }
  580.                                 else if (m_BreakPoint.type == eBT_Input && edge.fromNodeId == m_BreakPoint.fromAddr.node && edge.fromPortId == m_BreakPoint.fromAddr.port)
  581.                                 {
  582.                                         if (!TryActivatePort(m_BreakPoint, edge, bPerform, edgeIndex))
  583.                                         {
  584.                                                 return false;
  585.                                         }
  586.                                         ++edgeIndex;
  587.                                 }
  588.  
  589.                         }
  590.                 }
  591.  
  592.                 m_RePerformActivation = false;
  593.                 return CheckForDelayedActivations();
  594.         }
  595.  
  596.         return true;
  597. }
  598.  
  599. bool CFlowGraphDebugger::TryActivatePort(SBreakPoint& breakpoint, IFlowEdgeIterator::Edge& edge, bool& bPerform, int edgeIndex)
  600. {
  601.         SFlowAddress fromAddr;
  602.         fromAddr.node = edge.fromNodeId;
  603.         fromAddr.port = edge.fromPortId;
  604.         fromAddr.isOutput = true;
  605.  
  606.         SFlowAddress toAddr;
  607.         toAddr.node = edge.toNodeId;
  608.         toAddr.port = edge.toPortId;
  609.         toAddr.isOutput = false;
  610.  
  611.         bPerform = PerformActivation(breakpoint.flowGraph, edgeIndex, fromAddr, toAddr, breakpoint.value);
  612.  
  613.         if (bPerform)
  614.         {
  615.                 CFlowData* pData = static_cast<CFlowData*>(breakpoint.flowGraph->GetNodeData(edge.toNodeId));
  616.  
  617.                 if (pData)
  618.                 {
  619.                         pData->ActivateInputPort(edge.toPortId, breakpoint.value);
  620.                         breakpoint.flowGraph->ActivateNode(edge.toNodeId);
  621.  
  622.                         string val;
  623.                         if (breakpoint.value.GetValueWithConversion(val))
  624.                         {
  625.                                 breakpoint.flowGraph->NotifyFlowNodeActivationListeners(fromAddr.node, fromAddr.port, toAddr.node, toAddr.port, val.c_str());
  626.                         }
  627.                 }
  628.         }
  629.         else
  630.         {
  631.                 m_RePerformActivation = false;
  632.                 return false;
  633.         }
  634.  
  635.         return true;
  636. }
  637.  
  638. bool CFlowGraphDebugger::CheckForDelayedActivations()
  639. {
  640.         if (m_BreakpointHit)
  641.                 InvalidateBreakpoint();
  642.  
  643.         if (m_DelayedActivations.empty() && m_BreakPoint.type == eBT_Output_Without_Edges)
  644.         {
  645.                 // we just stopped at an output port without edges and no delayed activations exist
  646.                 return true;
  647.         }
  648.  
  649.         bool bPerform = true;
  650.  
  651.         while (bPerform)
  652.         {
  653.                 if (m_DelayedActivations.empty())
  654.                 {
  655.                         break;
  656.                 }
  657.  
  658.                 SBreakPoint delayedActivation = m_DelayedActivations.front();
  659.  
  660.                 if (delayedActivation.addr.isOutput && delayedActivation.type == eBT_Output_Without_Edges)
  661.                 {
  662.                         // We have a delayed output port activation with NO edges, invalidate the breakpoint
  663.                         // and perform the activation directly
  664.                         bPerform = PerformActivation(delayedActivation.flowGraph, delayedActivation.addr, delayedActivation.value);
  665.  
  666.                         m_DelayedActivations.pop_front();
  667.                 }
  668.                 else if (delayedActivation.type == eBT_Output)
  669.                 {
  670.                         // We have a delayed output port activation WITH edges, invalidate the breakpoint
  671.                         // and perform the activation to check if some edges result in a new breakpoint
  672.  
  673.                         // ensure sorted edges so we activate in the same order as usual
  674.                         delayedActivation.flowGraph->EnsureSortedEdges();
  675.  
  676.                         IFlowEdgeIteratorPtr pEdgeIter = delayedActivation.flowGraph->CreateEdgeIterator();
  677.                         if (pEdgeIter)
  678.                         {
  679.                                 IFlowEdgeIterator::Edge edge;
  680.                                 int edgeIndex = 0;
  681.                                 while (pEdgeIter->Next(edge) && bPerform)
  682.                                 {
  683.                                         if (edge.fromNodeId == delayedActivation.addr.node && edge.fromPortId == delayedActivation.addr.port)
  684.                                         {
  685.                                                 TryActivatePort(delayedActivation, edge, bPerform, edgeIndex);
  686.                                                 ++edgeIndex;
  687.                                         }
  688.                                 }
  689.                         }
  690.  
  691.                         m_DelayedActivations.pop_front();
  692.                 }
  693.         }
  694.  
  695.         return bPerform;
  696. }
  697.  
  698. void CFlowGraphDebugger::InvalidateBreakpoint()
  699. {
  700.         if (m_BreakPoint.type == eBT_Invalid)
  701.                 return;
  702.  
  703.         const SBreakPoint temp = m_BreakPoint;
  704.  
  705.         m_BreakPoint.addr.node = InvalidFlowNodeId;
  706.         m_BreakPoint.addr.port = InvalidFlowPortId;
  707.         m_BreakPoint.fromAddr.node = InvalidFlowNodeId;
  708.         m_BreakPoint.fromAddr.port = InvalidFlowPortId;
  709.         m_BreakPoint.flowGraph = NULL;
  710.         m_BreakPoint.type = eBT_Invalid;
  711.         m_BreakPoint.value.ClearUserFlag();
  712.  
  713.         m_BreakpointHit = false;
  714.  
  715.         for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  716.         {
  717.                 notifier->OnBreakpointInvalidated(temp);
  718.         }
  719. }
  720.  
  721. bool CFlowGraphDebugger::BreakpointHit() const
  722. {
  723.         return m_BreakpointHit;
  724. }
  725.  
  726. bool CFlowGraphDebugger::RegisterListener(IFlowGraphDebugListener* pListener, const char* name)
  727. {
  728.         return m_Listeners.Add(pListener, name);
  729. }
  730.  
  731. void CFlowGraphDebugger::UnregisterListener(IFlowGraphDebugListener* pListener)
  732. {
  733.         m_Listeners.Remove(pListener);
  734. }
  735.  
  736. bool CFlowGraphDebugger::GetBreakpoints(DynArray<SBreakPoint>& breakpointsDynArray)
  737. {
  738.         if (m_DebugInfo.empty())
  739.         {
  740.                 return false;
  741.         }
  742.  
  743.         TDebugInfo::const_iterator iterDebugInfo = m_DebugInfo.begin();
  744.  
  745.         for (iterDebugInfo; iterDebugInfo != m_DebugInfo.end(); ++iterDebugInfo)
  746.         {
  747.                 TFlowNodesDebugInfo flownodesDebugInfo = (*iterDebugInfo).second;
  748.                 TFlowNodesDebugInfo::const_iterator iterNodesDebugInfo = flownodesDebugInfo.begin();
  749.  
  750.                 for (iterNodesDebugInfo; iterNodesDebugInfo != flownodesDebugInfo.end(); ++iterNodesDebugInfo)
  751.                 {
  752.                         SBreakPoints breakpoints = (*iterNodesDebugInfo).second;
  753.                         // Fill with INPUT port breakpoints
  754.                         FillDynArray(breakpointsDynArray, breakpoints.inputPorts, (*iterDebugInfo).first, (*iterNodesDebugInfo).first, false);
  755.                         // Fill with OUTPUT port breakpoints
  756.                         FillDynArray(breakpointsDynArray, breakpoints.outputPorts, (*iterDebugInfo).first, (*iterNodesDebugInfo).first, true);
  757.                 }
  758.         }
  759.  
  760.         if (breakpointsDynArray.empty())
  761.         {
  762.                 return false;
  763.         }
  764.  
  765.         return true;
  766. }
  767.  
  768. void CFlowGraphDebugger::FillDynArray(DynArray<SBreakPoint>& breakpointsDynArray, TFlowPortIDS portIDS, IFlowGraphPtr pFlowgraph, TFlowNodeId nodeID, bool bIsOutput)
  769. {
  770.         TFlowPortIDS::const_iterator iterPorts = portIDS.begin();
  771.         for (iterPorts; iterPorts != portIDS.end(); ++iterPorts)
  772.         {
  773.                 TFlowPortId port = (*iterPorts).portID;
  774.                 SBreakPoint breakpoint;
  775.                 breakpoint.flowGraph = pFlowgraph;
  776.                 breakpoint.addr.node = nodeID;
  777.                 breakpoint.addr.port = port;
  778.                 breakpoint.addr.isOutput = bIsOutput;
  779.  
  780.                 breakpointsDynArray.push_back(breakpoint);
  781.         }
  782. }
  783.  
  784. IFlowGraphPtr CFlowGraphDebugger::GetRootGraph(IFlowGraphPtr pFlowGraph) const
  785. {
  786.         if (pFlowGraph->GetType() == IFlowGraph::eFGT_Module)
  787.         {
  788.                 IFlowGraphModule* pModule = gEnv->pFlowSystem->GetIModuleManager()->GetModule(pFlowGraph);
  789.  
  790.                 if (pModule)
  791.                 {
  792.                         return pModule->GetRootGraph();
  793.                 }
  794.         }
  795.         else if (pFlowGraph->GetType() == IFlowGraph::eFGT_AIAction)
  796.         {
  797.                 if (IFlowGraphPtr pClonedGraph = pFlowGraph->GetClonedFlowGraph())
  798.                 {
  799.                         return pClonedGraph;
  800.                 }
  801.         }
  802.  
  803.         return pFlowGraph;
  804. }
  805.  
  806. bool CFlowGraphDebugger::EnableBreakpoint(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr, bool enable)
  807. {
  808.         SBreakPointPortInfo* breakpointInfo = GetBreakpointInfo(pFlowgraph, addr);
  809.  
  810.         if (breakpointInfo)
  811.         {
  812.                 breakpointInfo->bIsEnabled = enable;
  813.  
  814.                 for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  815.                 {
  816.                         SBreakPoint breakpoint;
  817.                         breakpoint.addr = addr;
  818.                         breakpoint.flowGraph = pFlowgraph;
  819.  
  820.                         notifier->OnEnableBreakpoint(breakpoint, enable);
  821.                 }
  822.  
  823.                 return true;
  824.         }
  825.  
  826.         return false;
  827. }
  828.  
  829. bool CFlowGraphDebugger::EnableTracepoint(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr, bool enable)
  830. {
  831.         SBreakPointPortInfo* breakpointInfo = GetBreakpointInfo(pFlowgraph, addr);
  832.  
  833.         if (breakpointInfo)
  834.         {
  835.                 breakpointInfo->bIsTracepoint = enable;
  836.  
  837.                 for (CListenerSet<IFlowGraphDebugListener*>::Notifier notifier(m_Listeners); notifier.IsValid(); notifier.Next())
  838.                 {
  839.                         STracePoint tracepoint;
  840.                         tracepoint.addr = addr;
  841.                         tracepoint.flowGraph = pFlowgraph;
  842.  
  843.                         notifier->OnEnableTracepoint(tracepoint, enable);
  844.                 }
  845.                 return true;
  846.         }
  847.  
  848.         return false;
  849. }
  850.  
  851. bool CFlowGraphDebugger::IsBreakpointEnabled(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr) const
  852. {
  853.         const SBreakPointPortInfo* breakpointInfo = GetBreakpointInfo(pFlowgraph, addr);
  854.         return breakpointInfo ? breakpointInfo->bIsEnabled : false;
  855. }
  856.  
  857. bool CFlowGraphDebugger::IsTracepoint(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr) const
  858. {
  859.         const SBreakPointPortInfo* breakpointInfo = GetBreakpointInfo(pFlowgraph, addr);
  860.         return breakpointInfo ? breakpointInfo->bIsTracepoint : false;
  861. }
  862.  
  863. const SBreakPointPortInfo* CFlowGraphDebugger::GetBreakpointInfo(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr) const
  864. {
  865.         pFlowgraph = GetRootGraph(pFlowgraph);
  866.  
  867.         TDebugInfo::const_iterator iterDebugInfo = m_DebugInfo.find(pFlowgraph);
  868.         if (iterDebugInfo != m_DebugInfo.end())
  869.         {
  870.                 const TFlowNodesDebugInfo* flownodesDebugInfo = &(*iterDebugInfo).second;
  871.                 TFlowNodesDebugInfo::const_iterator iterNode = flownodesDebugInfo->find(addr.node);
  872.  
  873.                 if (iterNode != flownodesDebugInfo->end())
  874.                 {
  875.                         const SBreakPoints* breakPointInfo = &(*iterNode).second;
  876.                         const TFlowPortIDS* flowPortIDS = NULL;
  877.  
  878.                         if (addr.isOutput)
  879.                                 flowPortIDS = &breakPointInfo->outputPorts;
  880.                         else
  881.                                 flowPortIDS = &breakPointInfo->inputPorts;
  882.  
  883.                         TFlowPortIDS::const_iterator iter = flowPortIDS->begin();
  884.                         while (iter != flowPortIDS->end())
  885.                         {
  886.                                 if ((*iter).portID == addr.port)
  887.                                 {
  888.                                         return &(*iter);
  889.                                 }
  890.                                 ++iter;
  891.                         }
  892.                 }
  893.         }
  894.  
  895.         return NULL;
  896. }
  897.  
  898. SBreakPointPortInfo* CFlowGraphDebugger::GetBreakpointInfo(IFlowGraphPtr pFlowgraph, const SFlowAddress& addr)
  899. {
  900.         // code duplication vs. casting - casting wins
  901.         return const_cast<SBreakPointPortInfo*>(
  902.           static_cast<const CFlowGraphDebugger&>(*this).GetBreakpointInfo(pFlowgraph, addr));
  903. }
  904.  
  905. bool CFlowGraphDebugger::AddIgnoredFlowgraph(IFlowGraphPtr pFlowgraph)
  906. {
  907.         return stl::push_back_unique(m_IgnoredFlowgraphs, pFlowgraph);
  908. }
  909.  
  910. bool CFlowGraphDebugger::RemoveIgnoredFlowgraph(IFlowGraphPtr pFlowgraph)
  911. {
  912.         return stl::find_and_erase(m_IgnoredFlowgraphs, pFlowgraph);
  913. }
  914.  
  915. bool CFlowGraphDebugger::IsFlowgraphIgnored(IFlowGraphPtr pFlowgraph)
  916. {
  917.         return stl::find(m_IgnoredFlowgraphs, pFlowgraph);
  918. }
  919.  
  920. bool CFlowGraphDebugger::IgnoreFlowgraphType(IFlowGraph::EFlowGraphType type, bool bIgnore)
  921. {
  922.         if (bIgnore)
  923.         {
  924.                 return stl::push_back_unique(m_IgnoredFlowgraphTypes, type);
  925.         }
  926.         else
  927.         {
  928.                 return stl::find_and_erase(m_IgnoredFlowgraphTypes, type);
  929.         }
  930. }
  931.  
  932. bool CFlowGraphDebugger::IsFlowgraphTypeIgnored(IFlowGraph::EFlowGraphType type)
  933. {
  934.         return stl::find(m_IgnoredFlowgraphTypes, type);
  935. }
  936.  
  937. #endif
  938.  
downloadFlowGraphDebugger.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