BVB Source Codes

CRYENGINE Show TreeVisualizer.cpp Source code

Return Download CRYENGINE: download TreeVisualizer.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 "TreeVisualizer.h"
  5.  
  6. #include <CryAISystem/IAIDebugRenderer.h>
  7. #include <CryAISystem/BehaviorTree/Node.h>
  8. #include <CryAISystem/BehaviorTree/TimestampCollection.h>
  9. #include <CryCore/Containers/VariableCollection.h>
  10.  
  11. #include <CrySerialization/IArchive.h>
  12. #include <CrySerialization/STL.h>
  13.  
  14. #ifdef USING_BEHAVIOR_TREE_VISUALIZER
  15. namespace BehaviorTree
  16. {
  17. const float nodePosX = 10.0f;
  18. const float nodePosY = 30.0f;
  19. const float behaviorLogPosX = 600.0f;
  20. const float behaviorLogPosY = 30.0f;
  21. const float timestampPosX = behaviorLogPosX;
  22. const float timestampPosY = 370.0f;
  23. const float blackboardPosX = 900.0f;
  24. const float blackboardPosY = 30.0f;
  25.  
  26. const float eventLogPosX = 1250.0f;
  27. const float eventLogPosY = 370.0f;
  28.  
  29. const float fontSize = 1.25f;
  30. const float lineHeight = 11.5f * fontSize;
  31.  
  32. TreeVisualizer::TreeVisualizer(const UpdateContext& updateContext)
  33.         : m_updateContext(updateContext)
  34.         , m_currentLinePositionX(0.0f)
  35.         , m_currentLinePositionY(0.0f)
  36. {
  37. }
  38.  
  39. void TreeVisualizer::Draw(
  40.   const DebugTree& tree,
  41.   const char* behaviorTreeName,
  42.   const char* agentName,
  43.         #ifdef USING_BEHAVIOR_TREE_LOG
  44.   const MessageQueue& behaviorLog,
  45.         #endif // USING_BEHAVIOR_TREE_LOG
  46.   const TimestampCollection& timestampCollection,
  47.   const Blackboard& blackboard
  48.         #ifdef USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  49.   , const MessageQueue& eventsLog
  50.         #endif // USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  51.   )
  52. {
  53.         // Nodes
  54.         {
  55.                 const DebugNode* firstNode = tree.GetFirstNode().get();
  56.                 if (firstNode)
  57.                 {
  58.                         SetLinePosition(nodePosX, nodePosY);
  59.                         stack_string caption;
  60.                         caption.Format("  Modular Behavior Tree '%s' for agent '%s'", behaviorTreeName, agentName);
  61.                         DrawLine(caption, Col_Yellow);
  62.                         DrawLine("", Col_White);
  63.                         DrawNode(*firstNode, 0);
  64.                 }
  65.         }
  66.  
  67.         #ifdef USING_BEHAVIOR_TREE_LOG
  68.         DrawBehaviorLog(behaviorLog);
  69.         #endif // USING_BEHAVIOR_TREE_LOG
  70.  
  71.         #ifdef USING_BEHAVIOR_TREE_TIMESTAMP_DEBUGGING
  72.         if (gAIEnv.CVars.DebugTimestamps)
  73.         {
  74.                 DrawTimestampCollection(timestampCollection);
  75.         }
  76.         #endif // USING_BEHAVIOR_TREE_TIMESTAMP_DEBUGGING
  77.  
  78.         DrawBlackboard(blackboard);
  79.  
  80.         #ifdef USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  81.         DrawEventLog(eventsLog);
  82.         #endif // USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  83. }
  84.  
  85. void TreeVisualizer::DrawNode(const DebugNode& node, const uint32 depth)
  86. {
  87.         // Construct a nice readable debug text for this node
  88.         stack_string str;
  89.  
  90.         // Line
  91.         const uint32 xmlLine = static_cast<const Node*>(node.node)->GetXmlLine();
  92.         if (xmlLine > 0)
  93.                 str.Format("%5d ", xmlLine);
  94.         else
  95.                 str.Format("      ", xmlLine);
  96.  
  97.         // Indention
  98.         for (uint32 i = 0; i < (depth + 1); ++i)
  99.         {
  100.                 if ((i % 2) == 1)
  101.                         str += "- ";
  102.                 else
  103.                         str += "  ";
  104.         }
  105.  
  106.         // Node type
  107.         const char* nodeType = static_cast<const Node*>(node.node)->GetCreator()->GetTypeName();
  108.         str += nodeType;
  109.  
  110.         bool hasCustomText = false;
  111.  
  112.         #ifdef USING_BEHAVIOR_TREE_NODE_CUSTOM_DEBUG_TEXT
  113.         // Custom debug text from the node
  114.         stack_string customDebugText;
  115.  
  116.         UpdateContext updateContext = m_updateContext;
  117.         const Node* nodeToDraw = static_cast<const Node*>(node.node);
  118.         const RuntimeDataID runtimeDataID = MakeRuntimeDataID(updateContext.entityId, nodeToDraw->m_id);
  119.         updateContext.runtimeData = nodeToDraw->GetCreator()->GetRuntimeData(runtimeDataID);
  120.  
  121.         nodeToDraw->GetCustomDebugText(updateContext, customDebugText);
  122.         if (!customDebugText.empty())
  123.         {
  124.                 str += " - " + customDebugText;
  125.                 hasCustomText = true;
  126.         }
  127.         #endif // USING_BEHAVIOR_TREE_NODE_CUSTOM_DEBUG_TEXT
  128.  
  129.         // Draw
  130.         ColorB color;
  131.         const bool leaf = node.children.empty();
  132.         if (leaf)
  133.                 color = Col_SlateBlue;
  134.         else if (hasCustomText)
  135.                 color = Col_White;
  136.         else
  137.                 color = Col_DarkSlateGrey;
  138.  
  139.         DrawLine(str.c_str(), color);
  140.  
  141.         // Recursively draw children
  142.         DebugNode::Children::const_iterator it = node.children.begin();
  143.         DebugNode::Children::const_iterator end = node.children.end();
  144.         for (; it != end; ++it)
  145.         {
  146.                 DrawNode(*(*it), depth + 1);
  147.         }
  148. }
  149.  
  150. void TreeVisualizer::DrawLine(const char* label, const ColorB& color)
  151. {
  152.         gEnv->pAISystem->GetAIDebugRenderer()->Draw2dLabel(m_currentLinePositionX, m_currentLinePositionY, fontSize, color, false, label);
  153.         m_currentLinePositionY += lineHeight;
  154. }
  155.  
  156.         #ifdef USING_BEHAVIOR_TREE_LOG
  157. void TreeVisualizer::DrawBehaviorLog(const MessageQueue& behaviorLog)
  158. {
  159.         SetLinePosition(behaviorLogPosX, behaviorLogPosY);
  160.         DrawLine("Behavior Log", Col_Yellow);
  161.         DrawLine("", Col_White);
  162.  
  163.         PersonalLog::Messages::const_iterator it = behaviorLog.GetMessages().begin();
  164.         PersonalLog::Messages::const_iterator end = behaviorLog.GetMessages().end();
  165.         for (; it != end; ++it)
  166.                 DrawLine(*it, Col_White);
  167. }
  168.         #endif // USING_BEHAVIOR_TREE_LOG
  169.  
  170.         #ifdef USING_BEHAVIOR_TREE_TIMESTAMP_DEBUGGING
  171. void TreeVisualizer::DrawTimestampCollection(const TimestampCollection& timestampCollection)
  172. {
  173.         SetLinePosition(timestampPosX, timestampPosY);
  174.         DrawLine("Timestamp Collection", Col_Yellow);
  175.         DrawLine("", Col_White);
  176.  
  177.         CTimeValue timeNow = gEnv->pTimer->GetFrameStartTime();
  178.         Timestamps::const_iterator it = timestampCollection.GetTimestamps().begin();
  179.         Timestamps::const_iterator end = timestampCollection.GetTimestamps().end();
  180.         for (; it != end; ++it)
  181.         {
  182.                 stack_string s;
  183.                 ColorB color;
  184.                 if (it->IsValid())
  185.                 {
  186.                         s.Format("%s [%.2f]", it->id.timestampName, (timeNow - it->time).GetSeconds());
  187.                         color = Col_ForestGreen;
  188.                 }
  189.                 else
  190.                 {
  191.                         s.Format("%s [--]", it->id.timestampName);
  192.                         color = Col_Gray;
  193.                 }
  194.                 DrawLine(s.c_str(), color);
  195.         }
  196. }
  197.         #endif // USING_BEHAVIOR_TREE_TIMESTAMP_DEBUGGING
  198.  
  199. void TreeVisualizer::SetLinePosition(float x, float y)
  200. {
  201.         m_currentLinePositionX = x;
  202.         m_currentLinePositionY = y;
  203. }
  204.  
  205. void TreeVisualizer::DrawBlackboard(const Blackboard& blackboard)
  206. {
  207.         #ifdef STORE_BLACKBOARD_VARIABLE_NAMES
  208.         SetLinePosition(blackboardPosX, blackboardPosY);
  209.  
  210.         DrawLine("Blackboard variables", Col_Yellow);
  211.         DrawLine("", Col_White);
  212.  
  213.         Blackboard::BlackboardVariableArray blackboardVariableArray = blackboard.GetBlackboardVariableArray();
  214.  
  215.         Blackboard::BlackboardVariableArray::const_iterator it = blackboardVariableArray.begin();
  216.         Blackboard::BlackboardVariableArray::const_iterator end = blackboardVariableArray.end();
  217.         for (; it != end; ++it)
  218.         {
  219.                 BlackboardVariableId id = it->first;
  220.                 IBlackboardVariablePtr variable = it->second;
  221.  
  222.                 Serialization::TypeID typeId = variable->GetDataTypeId();
  223.                 if (typeId == Serialization::TypeID::get<Vec3>())
  224.                 {
  225.                         stack_string variableText;
  226.  
  227.                         Vec3 data;
  228.                         variable->GetData(data);
  229.                         variableText.Format("%s - (%f, %f, %f)", id.name.c_str(), data.x, data.y, data.z);
  230.  
  231.                         DrawLine(variableText.c_str(), Col_White);
  232.                 }
  233.         }
  234.         #endif
  235. }
  236.  
  237.         #ifdef USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  238. void TreeVisualizer::DrawEventLog(const MessageQueue& eventsLog)
  239. {
  240.         SetLinePosition(eventLogPosX, eventLogPosY);
  241.         DrawLine("Event Log", Col_Yellow);
  242.         DrawLine("", Col_White);
  243.  
  244.         PersonalLog::Messages::const_reverse_iterator it = eventsLog.GetMessages().rbegin();
  245.         PersonalLog::Messages::const_reverse_iterator end = eventsLog.GetMessages().rend();
  246.         for (; it != end; ++it)
  247.                 DrawLine(*it, Col_White);
  248. }
  249.         #endif // USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  250.  
  251. //////////////////////////////////////////////////////////////////////////
  252.  
  253. void DebugTreeSerializer::TreeNode::Serialize(Serialization::IArchive& archive)
  254. {
  255.         archive(xmlLine, "xmlLine");
  256.         archive(node, "node");
  257.         archive(children, "children");
  258. }
  259.  
  260. void DebugTreeSerializer::MBTree::Serialize(Serialization::IArchive& archive)
  261. {
  262.         archive(name, "name");
  263.         archive(rootNode, "rootNode");
  264. }
  265.  
  266. void DebugTreeSerializer::Variable::Serialize(Serialization::IArchive& archive)
  267. {
  268.         archive(name, "name");
  269.         archive(value, "value");
  270. }
  271.  
  272. void DebugTreeSerializer::TimeStamp::Serialize(Serialization::IArchive& archive)
  273. {
  274.         archive(name, "name");
  275.         archive(value, "value");
  276.         archive(bIsValid, "isValid");
  277. }
  278.  
  279. void DebugTreeSerializer::Data::Serialize(Serialization::IArchive& archive)
  280. {
  281.         archive(tree, "tree");
  282.         archive(variables, "variables");
  283.         archive(timeStamps, "timeStamps");
  284.         archive(eventLog, "eventLog");
  285.         archive(errorLog, "errorLog");
  286. }
  287. //////////////////////////////////////////////////////////////////////////
  288.  
  289. DebugTreeSerializer::DebugTreeSerializer(const BehaviorTreeInstance& treeInstance, const DebugTree& debugTree, const UpdateContext& updateContext, const bool bExecutionError)
  290. {
  291.         m_data.tree.name = treeInstance.behaviorTreeTemplate->mbtFilename.c_str();
  292.  
  293.         if (bExecutionError)
  294.         {
  295.                 CollectExecutionErrorInfo(debugTree);
  296.         }
  297.         else
  298.         {
  299.                 const DebugNode* pFirstNode = debugTree.GetFirstNode().get();
  300.                 if (pFirstNode)
  301.                 {
  302.                         CollectTreeNodeInfo(*pFirstNode, updateContext, m_data.tree.rootNode);
  303.                 }
  304.                 CollectVariablesInfo(treeInstance);
  305.                 CollectTimeStamps(treeInstance);
  306.                 CollectEventsLog(treeInstance);
  307.         }
  308. }
  309.  
  310. void DebugTreeSerializer::Serialize(Serialization::IArchive& archive)
  311. {
  312.         archive(m_data, "aiMbt");
  313. }
  314.  
  315. void DebugTreeSerializer::CollectTreeNodeInfo(const DebugNode& debugNode, const UpdateContext& updateContext, TreeNode& outNode)
  316. {
  317.         const uint32 xmlLine = static_cast<const Node*>(debugNode.node)->GetXmlLine();
  318.  
  319.         stack_string tempOutput;
  320.         const char* szNodeType = static_cast<const Node*>(debugNode.node)->GetCreator()->GetTypeName();
  321.         tempOutput += szNodeType;
  322.  
  323.         #ifdef USING_BEHAVIOR_TREE_NODE_CUSTOM_DEBUG_TEXT
  324.         // Custom debug text from the node
  325.         stack_string customDebugText;
  326.  
  327.         UpdateContext updateContextCopy = updateContext;
  328.         const Node* pNodeToDraw = static_cast<const Node*>(debugNode.node);
  329.         const RuntimeDataID runtimeDataID = MakeRuntimeDataID(updateContext.entityId, pNodeToDraw->m_id);
  330.         updateContextCopy.runtimeData = pNodeToDraw->GetCreator()->GetRuntimeData(runtimeDataID);
  331.  
  332.         pNodeToDraw->GetCustomDebugText(updateContextCopy, customDebugText);
  333.         if (!customDebugText.empty())
  334.         {
  335.                 tempOutput += " - " + customDebugText;
  336.         }
  337.         #endif // USING_BEHAVIOR_TREE_NODE_CUSTOM_DEBUG_TEXT
  338.  
  339.         outNode.xmlLine = xmlLine;
  340.         outNode.node = tempOutput.c_str();
  341.         outNode.children.reserve(debugNode.children().size());
  342.  
  343.         DebugNode::Children::const_iterator it = debugNode.children.begin();
  344.         DebugNode::Children::const_iterator endIt = debugNode.children.end();
  345.         for (; it != endIt; ++it)
  346.         {
  347.                 outNode.children.push_back(TreeNode());
  348.                 CollectTreeNodeInfo(*(*it), updateContext, outNode.children.back());
  349.         }
  350. }
  351.  
  352. void DebugTreeSerializer::CollectVariablesInfo(const BehaviorTreeInstance& instance)
  353. {
  354.         #ifdef DEBUG_VARIABLE_COLLECTION
  355.         DynArray<::Variables::DebugHelper::DebugVariable> outVariables;
  356.         ::Variables::DebugHelper::CollectDebugVariables(instance.variables, instance.behaviorTreeTemplate->variableDeclarations, outVariables);
  357.  
  358.         m_data.variables.reserve(outVariables.size());
  359.         for (DynArray<::Variables::DebugHelper::DebugVariable>::iterator it = outVariables.begin(), end = outVariables.end(); it != end; ++it)
  360.         {
  361.                 Variable variable;
  362.                 variable.name = it->name;
  363.                 variable.value = it->value;
  364.                 m_data.variables.push_back(variable);
  365.         }
  366.         #endif
  367. }
  368.  
  369. void DebugTreeSerializer::CollectTimeStamps(const BehaviorTreeInstance& instance)
  370. {
  371.         #ifdef USING_BEHAVIOR_TREE_TIMESTAMP_DEBUGGING
  372.         CTimeValue timeNow = gEnv->pTimer->GetFrameStartTime();
  373.         Timestamps::const_iterator it = instance.timestampCollection.GetTimestamps().begin();
  374.         Timestamps::const_iterator end = instance.timestampCollection.GetTimestamps().end();
  375.  
  376.         m_data.timeStamps.reserve(instance.timestampCollection.GetTimestamps().size());
  377.         for (; it != end; ++it)
  378.         {
  379.                 TimeStamp timeStamp;
  380.                 timeStamp.name = it->id.timestampName;
  381.                 timeStamp.bIsValid = it->IsValid();
  382.                 timeStamp.value = it->IsValid() ? (timeNow - it->time).GetSeconds() : 0.0f;
  383.  
  384.                 m_data.timeStamps.push_back(timeStamp);
  385.         }
  386.         #endif
  387. }
  388.  
  389. void DebugTreeSerializer::CollectEventsLog(const BehaviorTreeInstance& instance)
  390. {
  391.         #ifdef USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  392.         PersonalLog::Messages::const_reverse_iterator it = instance.eventsLog.GetMessages().rbegin();
  393.         PersonalLog::Messages::const_reverse_iterator end = instance.eventsLog.GetMessages().rend();
  394.  
  395.         m_data.eventLog.reserve(instance.eventsLog.GetMessages().size());
  396.         for (; it != end; ++it)
  397.         {
  398.                 m_data.eventLog.push_back(*it);
  399.         }
  400.         #endif
  401. }
  402.  
  403. void DebugTreeSerializer::CollectExecutionErrorInfo(const DebugTree& debugTree)
  404. {
  405.         #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  406.         m_data.errorLog.reserve(debugTree.GetSucceededAndFailedNodes().size() + 1);
  407.  
  408.         DynArray<DebugNodePtr>::const_iterator it = debugTree.GetSucceededAndFailedNodes().begin();
  409.         DynArray<DebugNodePtr>::const_iterator end = debugTree.GetSucceededAndFailedNodes().end();
  410.  
  411.         string messageLine("ERROR: Root Node failed or succeeded");
  412.         m_data.errorLog.push_back(messageLine);
  413.         for (; it != end; ++it)
  414.         {
  415.                 const BehaviorTree::Node* node = static_cast<const BehaviorTree::Node*>((*it)->node);
  416.                 messageLine.Format("(%d) %s.", node->GetXmlLine(), node->GetCreator()->GetTypeName());
  417.                 m_data.errorLog.push_back(messageLine);
  418.         }
  419.         #endif // DEBUG_MODULAR_BEHAVIOR_TREE
  420. }
  421.  
  422. }
  423.  
  424. #endif // USING_BEHAVIOR_TREE_VISUALIZER
  425.  
downloadTreeVisualizer.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