BVB Source Codes

CRYENGINE Show BehaviorTreeManager.cpp Source code

Return Download CRYENGINE: download BehaviorTreeManager.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4.  
  5. #include "BehaviorTreeManager.h"
  6. #include <CryAISystem/BehaviorTree/XmlLoader.h>
  7. #include <CryAISystem/BehaviorTree/NodeFactory.h>
  8. #include "BehaviorTree/BehaviorTreeMetaExtensions.h"
  9.  
  10. #ifdef USING_BEHAVIOR_TREE_VISUALIZER
  11.         #include "BehaviorTree/TreeVisualizer.h"
  12. #endif // USING_BEHAVIOR_TREE_VISUALIZER
  13.  
  14. #ifdef USING_BEHAVIOR_TREE_EXECUTION_STACKS_FILE_LOG
  15.         #include "ExecutionStackFileLogger.h"
  16. #endif
  17.  
  18. #if defined(COMPILE_WITH_MOVEMENT_SYSTEM_DEBUG)
  19.         #include <CryAISystem/IAIDebugRenderer.h>
  20. #endif
  21.  
  22. #include "PipeUser.h"
  23.  
  24. #ifdef USING_BEHAVIOR_TREE_SERIALIZATION
  25.         #include <CrySerialization/ClassFactory.h>
  26. #endif
  27.  
  28. #if defined (DEBUG_MODULAR_BEHAVIOR_TREE_WEB)
  29.         #include <CryGame/IGameFramework.h>
  30.         #include <CrySerialization/IArchiveHost.h>
  31. #endif
  32.  
  33. namespace
  34. {
  35. static CAIActor* GetAIActor(EntityId entityId)
  36. {
  37.         IEntity* entity = gEnv->pEntitySystem->GetEntity(entityId);
  38.         IAIObject* aiObject = entity ? entity->GetAI() : NULL;
  39.         return aiObject ? aiObject->CastToCAIActor() : NULL;
  40. }
  41.  
  42. static CPipeUser* GetPipeUser(EntityId entityId)
  43. {
  44.         IEntity* entity = gEnv->pEntitySystem->GetEntity(entityId);
  45.         IAIObject* aiObject = entity ? entity->GetAI() : NULL;
  46.         return aiObject ? aiObject->CastToCPipeUser() : NULL;
  47. }
  48.  
  49. #if defined (DEBUG_MODULAR_BEHAVIOR_TREE_WEB)
  50. IGameWebDebugService* GetIGameWebDebugService()
  51. {
  52.         if (gEnv)
  53.         {
  54.                 if (auto* pGame = gEnv->pGameFramework->GetIGame())
  55.                         return pGame->GetIWebDebugService();
  56.         }
  57.  
  58.         return nullptr;
  59. }
  60. #endif
  61. }
  62.  
  63. namespace BehaviorTree
  64. {
  65. #ifdef USE_GLOBAL_BUCKET_ALLOCATOR
  66. NodeFactory::BehaviorTreeBucketAllocator NodeFactory::s_bucketAllocator(NULL, false);
  67. #else
  68. NodeFactory::BehaviorTreeBucketAllocator NodeFactory::s_bucketAllocator;
  69. #endif
  70.  
  71. BehaviorTreeManager::BehaviorTreeManager()
  72. #if defined(DEBUG_MODULAR_BEHAVIOR_TREE_WEB)
  73.         : m_bRegisteredAsDebugChannel(false)
  74. #endif
  75. {
  76.         m_metaExtensionFactory.reset(new BehaviorTree::MetaExtensionFactory);
  77.         m_nodeFactory.reset(new NodeFactory);
  78. }
  79.  
  80. BehaviorTreeManager::~BehaviorTreeManager()
  81. {
  82. #if defined(DEBUG_MODULAR_BEHAVIOR_TREE_WEB)
  83.         if (m_bRegisteredAsDebugChannel)
  84.         {
  85.                 IGameWebDebugService* pWebDebugService = GetIGameWebDebugService();
  86.                 if (pWebDebugService)
  87.                 {
  88.                         pWebDebugService->RemoveChannel(this);
  89.                         m_bRegisteredAsDebugChannel = false;
  90.                 }
  91.         }
  92. #endif
  93. }
  94.  
  95. IMetaExtensionFactory& BehaviorTreeManager::GetMetaExtensionFactory()
  96. {
  97.         assert(m_metaExtensionFactory.get());
  98.         return *m_metaExtensionFactory.get();
  99. }
  100.  
  101. INodeFactory& BehaviorTreeManager::GetNodeFactory()
  102. {
  103.         assert(m_nodeFactory.get());
  104.         return *m_nodeFactory.get();
  105. }
  106.  
  107. #ifdef USING_BEHAVIOR_TREE_SERIALIZATION
  108. SERIALIZATION_CLASS_NULL(INode, "[ Node ]");
  109.  
  110. Serialization::ClassFactory<INode>& BehaviorTreeManager::GetNodeSerializationFactory()
  111. {
  112.         return Serialization::ClassFactory<INode>::the();
  113. }
  114. #endif
  115.  
  116. BehaviorTreeInstancePtr BehaviorTreeManager::CreateBehaviorTreeInstanceFromDiskCache(const char* behaviorTreeName)
  117. {
  118.         BehaviorTreeInstancePtr instance = LoadFromCache(behaviorTreeName);
  119.  
  120.         if (instance.get())
  121.                 return instance;
  122.  
  123.         // In the editor the behavior trees are not cached up front so we
  124.         // need to load the tree into the cache if it wasn't already there.
  125.         LoadFromDiskIntoCache(behaviorTreeName);
  126.         return LoadFromCache(behaviorTreeName);
  127. }
  128.  
  129. BehaviorTreeInstancePtr BehaviorTreeManager::CreateBehaviorTreeInstanceFromXml(const char* behaviorTreeName, XmlNodeRef behaviorTreeXmlNode)
  130. {
  131.         BehaviorTreeTemplatePtr behaviorTreeTemplate = BehaviorTreeTemplatePtr(new BehaviorTreeTemplate());
  132.         if (LoadBehaviorTreeTemplate(behaviorTreeName, behaviorTreeXmlNode, *(behaviorTreeTemplate.get())))
  133.         {
  134.                 return BehaviorTreeInstancePtr(new BehaviorTreeInstance(
  135.                                                  behaviorTreeTemplate->defaultTimestampCollection,
  136.                                                  behaviorTreeTemplate->variableDeclarations.GetDefaults(),
  137.                                                  behaviorTreeTemplate,
  138.                                                  GetNodeFactory()
  139.                                                  ));
  140.         }
  141.  
  142.         return BehaviorTreeInstancePtr();
  143. }
  144.  
  145. BehaviorTreeInstancePtr BehaviorTreeManager::LoadFromCache(const char* behaviorTreeName)
  146. {
  147.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Other, 0, "Load Modular Behavior Tree From Cache: %s", behaviorTreeName);
  148.  
  149.         BehaviorTreeCache::iterator findResult = m_behaviorTreeCache.find(behaviorTreeName);
  150.         if (findResult != m_behaviorTreeCache.end())
  151.         {
  152.                 BehaviorTreeTemplatePtr behaviorTreeTemplate = findResult->second;
  153.                 return BehaviorTreeInstancePtr(new BehaviorTreeInstance(
  154.                                                  behaviorTreeTemplate->defaultTimestampCollection,
  155.                                                  behaviorTreeTemplate->variableDeclarations.GetDefaults(),
  156.                                                  behaviorTreeTemplate,
  157.                                                  GetNodeFactory()));
  158.         }
  159.  
  160.         return BehaviorTreeInstancePtr();
  161. }
  162.  
  163. bool BehaviorTreeManager::LoadBehaviorTreeTemplate(const char* behaviorTreeName, XmlNodeRef behaviorTreeXmlNode, BehaviorTreeTemplate& behaviorTreeTemplate)
  164. {
  165. #if defined(DEBUG_MODULAR_BEHAVIOR_TREE)
  166.         behaviorTreeTemplate.mbtFilename = behaviorTreeName;
  167. #endif
  168.  
  169.         GetMetaExtensionFactory().CreateMetaExtensions(behaviorTreeTemplate.metaExtensionTable);
  170.  
  171.         if (XmlNodeRef metaExtensionsXml = behaviorTreeXmlNode->findChild("MetaExtensions"))
  172.         {
  173.                 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "MetaExtensions");
  174.                 behaviorTreeTemplate.metaExtensionTable.LoadFromXml(metaExtensionsXml);
  175.         }
  176.  
  177.         if (XmlNodeRef timestampsXml = behaviorTreeXmlNode->findChild("Timestamps"))
  178.         {
  179.                 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Timestamps");
  180.                 behaviorTreeTemplate.defaultTimestampCollection.LoadFromXml(timestampsXml);
  181.         }
  182.  
  183.         if (XmlNodeRef variablesXml = behaviorTreeXmlNode->findChild("Variables"))
  184.         {
  185.                 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Variables");
  186.                 behaviorTreeTemplate.variableDeclarations.LoadFromXML(variablesXml, behaviorTreeName);
  187.         }
  188.  
  189.         if (XmlNodeRef signalsXml = behaviorTreeXmlNode->findChild("SignalVariables"))
  190.         {
  191.                 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Signals");
  192.                 behaviorTreeTemplate.signalHandler.LoadFromXML(behaviorTreeTemplate.variableDeclarations, signalsXml, behaviorTreeName);
  193.         }
  194.  
  195.         LoadContext context(GetNodeFactory(), behaviorTreeName, behaviorTreeTemplate.variableDeclarations);
  196.         behaviorTreeTemplate.rootNode = XmlLoader().CreateBehaviorTreeRootNodeFromBehaviorTreeXml(behaviorTreeXmlNode, context);
  197.  
  198.         if (!behaviorTreeTemplate.rootNode)
  199.                 return false;
  200.  
  201.         return true;
  202. }
  203.  
  204. void BehaviorTreeManager::LoadFromDiskIntoCache(const char* behaviorTreeName)
  205. {
  206.         BehaviorTreeCache::iterator findResult = m_behaviorTreeCache.find(behaviorTreeName);
  207.         if (findResult != m_behaviorTreeCache.end())
  208.                 return;
  209.  
  210.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Other, 0, "Load Modular Behavior Tree From Disk: %s", behaviorTreeName);
  211.  
  212.         XmlNodeRef behaviorTreeXmlNode = XmlLoader().LoadBehaviorTreeXmlFile("Scripts/AI/BehaviorTrees/", behaviorTreeName);
  213.  
  214.         if (!behaviorTreeXmlNode)
  215.                 behaviorTreeXmlNode = XmlLoader().LoadBehaviorTreeXmlFile("libs/ai/behavior_trees/", behaviorTreeName);
  216.  
  217.         if (behaviorTreeXmlNode)
  218.         {
  219.                 BehaviorTreeTemplatePtr behaviorTreeTemplate = BehaviorTreeTemplatePtr(new BehaviorTreeTemplate());
  220.                 if (LoadBehaviorTreeTemplate(behaviorTreeName, behaviorTreeXmlNode, *(behaviorTreeTemplate.get())))
  221.                 {
  222.                         m_behaviorTreeCache.insert(BehaviorTreeCache::value_type(behaviorTreeName, behaviorTreeTemplate));
  223.                 }
  224.                 else
  225.                 {
  226.                         gEnv->pLog->LogError("Modular behavior tree '%s' failed to load.", behaviorTreeName);
  227.                 }
  228.         }
  229.         else
  230.         {
  231.                 gEnv->pLog->LogError("Failed to load behavior tree '%s'. Could not load the '%s.xml' file from the 'Scripts/AI/BehaviorTrees/' or 'libs/ai/behavior_trees/' folders", behaviorTreeName, behaviorTreeName);
  232.         }
  233. }
  234.  
  235. void BehaviorTreeManager::Reset()
  236. {
  237.         StopAllBehaviorTreeInstances();
  238.         m_behaviorTreeCache.clear();
  239.         m_nodeFactory->TrimNodeCreators();
  240.         m_nodeFactory->CleanUpBucketAllocator();
  241. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  242.         m_errorStatusTrees.clear();
  243. #endif // DEBUG_MODULAR_BEHAVIOR_TREE
  244.  
  245. #if defined(DEBUG_MODULAR_BEHAVIOR_TREE_WEB)
  246.         if (!m_bRegisteredAsDebugChannel)
  247.         {
  248.                 IGameWebDebugService* pWebDebugService = GetIGameWebDebugService();
  249.                 if (pWebDebugService)
  250.                 {
  251.                         pWebDebugService->AddChannel(this);
  252.                         m_bRegisteredAsDebugChannel = true;
  253.                 }
  254.         }
  255. #endif
  256. }
  257.  
  258. void BehaviorTreeManager::StopAllBehaviorTreeInstances()
  259. {
  260.         Instances::iterator it = m_instances.begin();
  261.         Instances::iterator end = m_instances.end();
  262.         for (; it != end; ++it)
  263.         {
  264.                 BehaviorTreeInstance& instance = *(it->second.get());
  265.                 const EntityId entityId = it->first;
  266.  
  267.                 BehaviorVariablesContext variables(
  268.                   instance.variables
  269.                   , instance.behaviorTreeTemplate->variableDeclarations
  270.                   , instance.variables.Changed()
  271.                   );
  272.  
  273.                 IEntity* entity = gEnv->pEntitySystem->GetEntity(entityId);
  274.                 assert(entity);
  275.  
  276.                 UpdateContext context(
  277.                   entityId
  278.                   , *entity
  279.                   , variables
  280.                   , instance.timestampCollection
  281.                   , instance.blackboard
  282. #ifdef USING_BEHAVIOR_TREE_LOG
  283.                   , instance.behaviorLog
  284. #endif
  285.                   );
  286.  
  287.                 instance.behaviorTreeTemplate->rootNode->Terminate(context);
  288.         }
  289.  
  290.         m_instances.clear();
  291. }
  292.  
  293. #ifdef CRYAISYSTEM_DEBUG
  294. void BehaviorTreeManager::DrawMemoryInformation()
  295. {
  296.         const float fontSize = 1.25f;
  297.         const float lineHeight = 11.5f * fontSize;
  298.         const float x = 10.0f;
  299.         float y = 30.0f;
  300.  
  301.         IAIDebugRenderer* renderer = gEnv->pAISystem->GetAIDebugRenderer();
  302.  
  303.         const size_t immutableSize = m_nodeFactory->GetSizeOfImmutableDataForAllAllocatedNodes();
  304.         const size_t runtimeSize = m_nodeFactory->GetSizeOfRuntimeDataForAllAllocatedNodes();
  305.  
  306.         renderer->Draw2dLabel(x, y, fontSize, Col_White, false, "MODULAR BEHAVIOR TREE STATISTICS");
  307.         y += lineHeight;
  308.         renderer->Draw2dLabel(x, y, fontSize, Col_White, false, "Immutable: %" PRISIZE_T " bytes", immutableSize);
  309.         y += lineHeight;
  310.         renderer->Draw2dLabel(x, y, fontSize, Col_White, false, "Runtime: %" PRISIZE_T " bytes", runtimeSize);
  311.         y += lineHeight;
  312. }
  313. #endif
  314.  
  315. bool BehaviorTreeManager::StartModularBehaviorTree(const EntityId entityId, const char* treeName)
  316. {
  317.         BehaviorTreeInstancePtr instance = CreateBehaviorTreeInstanceFromDiskCache(treeName);
  318.         return StartBehaviorInstance(entityId, instance, treeName);
  319. }
  320.  
  321. bool BehaviorTreeManager::StartModularBehaviorTreeFromXml(const EntityId entityId, const char* treeName, XmlNodeRef treeXml)
  322. {
  323.         BehaviorTreeInstancePtr instance = CreateBehaviorTreeInstanceFromXml(treeName, treeXml);
  324.         return StartBehaviorInstance(entityId, instance, treeName);
  325. }
  326.  
  327. bool BehaviorTreeManager::StartBehaviorInstance(const EntityId entityId, BehaviorTreeInstancePtr instance, const char* treeName)
  328. {
  329.         StopModularBehaviorTree(entityId);
  330.         if (instance.get())
  331.         {
  332.                 m_instances.insert(std::make_pair(entityId, instance));
  333. #ifdef USING_BEHAVIOR_TREE_EXECUTION_STACKS_FILE_LOG
  334.                 m_executionStackFileLoggerInstances.insert(std::make_pair(entityId, ExecutionStackFileLoggerPtr(new ExecutionStackFileLogger(entityId))));
  335. #endif
  336.                 return true;
  337.         }
  338.         else
  339.         {
  340.                 gEnv->pLog->LogError("Failed to start modular behavior tree '%s'.", treeName);
  341.                 return false;
  342.         }
  343. }
  344.  
  345. void BehaviorTreeManager::StopModularBehaviorTree(const EntityId entityId)
  346. {
  347.         Instances::iterator it = m_instances.find(entityId);
  348.         if (it != m_instances.end())
  349.         {
  350.                 BehaviorTreeInstance& instance = *(it->second.get());
  351.  
  352.                 BehaviorVariablesContext variables(
  353.                   instance.variables
  354.                   , instance.behaviorTreeTemplate->variableDeclarations
  355.                   , instance.variables.Changed()
  356.                   );
  357.  
  358.                 IEntity* entity = gEnv->pEntitySystem->GetEntity(entityId);
  359.                 assert(entity);
  360.  
  361.                 UpdateContext context(
  362.                   entityId
  363.                   , *entity
  364.                   , variables
  365.                   , instance.timestampCollection
  366.                   , instance.blackboard
  367. #ifdef USING_BEHAVIOR_TREE_LOG
  368.                   , instance.behaviorLog
  369. #endif
  370.                   );
  371.  
  372.                 instance.behaviorTreeTemplate->rootNode->Terminate(context);
  373.                 m_instances.erase(it);
  374.         }
  375.  
  376. #ifdef USING_BEHAVIOR_TREE_EXECUTION_STACKS_FILE_LOG
  377.         m_executionStackFileLoggerInstances.erase(entityId);
  378. #endif
  379. }
  380.  
  381. void BehaviorTreeManager::Update()
  382. {
  383.         EntityIdVector newErrorStatusTree;
  384.  
  385.         Instances::iterator it = m_instances.begin();
  386.         Instances::iterator end = m_instances.end();
  387.  
  388.         for (; it != end; ++it)
  389.         {
  390.                 const EntityId entityId = it->first;
  391.  
  392.                 IEntity* agentEntity = gEnv->pEntitySystem->GetEntity(entityId);
  393.                 assert(agentEntity);
  394.                 if (!agentEntity)
  395.                         continue;
  396.  
  397.                 CPipeUser* pipeUser = GetPipeUser(entityId);
  398.                 if (pipeUser && (!pipeUser->IsEnabled() || pipeUser->IsPaused()))
  399.                         continue;
  400.  
  401.                 BehaviorTreeInstance& instance = *(it->second.get());
  402.  
  403.                 BehaviorVariablesContext variables(instance.variables, instance.behaviorTreeTemplate->variableDeclarations, instance.variables.Changed());
  404.                 instance.variables.ResetChanged();
  405.  
  406. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  407.                 DebugTree debugTree;
  408. #endif // DEBUG_MODULAR_BEHAVIOR_TREE
  409.  
  410.                 UpdateContext updateContext(
  411.                   entityId
  412.                   , *agentEntity
  413.                   , variables
  414.                   , instance.timestampCollection
  415.                   , instance.blackboard
  416. #ifdef USING_BEHAVIOR_TREE_LOG
  417.                   , instance.behaviorLog
  418. #endif // USING_BEHAVIOR_TREE_LOG
  419. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  420.                   , &debugTree
  421. #endif // DEBUG_MODULAR_BEHAVIOR_TREE
  422.                   );
  423.  
  424.                 const Status behaviorStatus = instance.behaviorTreeTemplate->rootNode->Tick(updateContext);
  425.                 const bool bExecutionError = (behaviorStatus == Success) || (behaviorStatus == Failure);
  426.  
  427.                 IF_UNLIKELY (bExecutionError)
  428.                 {
  429.                         string message;
  430.                         message.Format("Modular Behavior Tree Error Status: The root node for entity '%s' %s. Having the root succeed or fail is considered undefined behavior and the tree should be designed in a way that the root node is always running.", agentEntity ? agentEntity->GetName() : "", (behaviorStatus == Success ? "SUCCEEDED" : "FAILED"));
  431.  
  432. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  433.                         DynArray<DebugNodePtr>::const_iterator it = debugTree.GetSucceededAndFailedNodes().begin();
  434.                         DynArray<DebugNodePtr>::const_iterator end = debugTree.GetSucceededAndFailedNodes().end();
  435.                         for (; it != end; ++it)
  436.                         {
  437.                                 const BehaviorTree::Node* node = static_cast<const BehaviorTree::Node*>((*it)->node);
  438.                                 message.append(stack_string().Format(" (%d) %s.", node->GetXmlLine(), node->GetCreator()->GetTypeName()).c_str());
  439.                         }
  440. #endif  // DEBUG_MODULAR_BEHAVIOR_TREE
  441.  
  442.                         gEnv->pLog->LogError("%s", message.c_str());
  443.  
  444.                         newErrorStatusTree.push_back(entityId);
  445.  
  446.                         continue;
  447.                 }
  448.  
  449. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  450.                 const bool debugThisAgent = (GetAISystem()->GetAgentDebugTarget() == entityId);
  451.                 if (debugThisAgent)
  452.                 {
  453.                         UpdateDebugVisualization(updateContext, entityId, debugTree, instance, agentEntity);
  454.                 }
  455.  
  456.                 if (gAIEnv.CVars.LogModularBehaviorTreeExecutionStacks == 1 && debugThisAgent || gAIEnv.CVars.LogModularBehaviorTreeExecutionStacks == 2)
  457.                 {
  458.                         UpdateExecutionStackLogging(updateContext, entityId, debugTree, instance);
  459.                 }
  460. #endif // DEBUG_MODULAR_BEHAVIOR_TREE
  461.  
  462. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE_WEB
  463.                 UpdateWebDebugChannel(entityId, updateContext, debugTree, instance, bExecutionError);
  464. #endif
  465.         }
  466.  
  467.         for (EntityIdVector::iterator it = newErrorStatusTree.begin(), end = newErrorStatusTree.end(); it != end; ++it)
  468.         {
  469. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  470.                 m_errorStatusTrees.push_back(*it);
  471. #endif // DEBUG_MODULAR_BEHAVIOR_TREE
  472.  
  473.                 StopModularBehaviorTree(*it);
  474.         }
  475.  
  476. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  477.         if (gAIEnv.CVars.DebugDraw > 0)
  478.         {
  479.                 for (EntityIdVector::iterator it = m_errorStatusTrees.begin(), end = m_errorStatusTrees.end(); it != end; ++it)
  480.                 {
  481.                         if (IEntity* entity = gEnv->pEntitySystem->GetEntity(*it))
  482.                         {
  483.                                 const float color[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
  484.                                 const Vec3 position = entity->GetPos() + Vec3(0.0f, 0.0f, 2.0f);
  485.                                 IRenderAuxText::DrawLabelEx(position, 1.5f, color, true, true, "Behavior tree error.");
  486.                         }
  487.                 }
  488.         }
  489. #endif // DEBUG_MODULAR_BEHAVIOR_TREE
  490.  
  491. }
  492.  
  493. size_t BehaviorTreeManager::GetTreeInstanceCount() const
  494. {
  495.         return m_instances.size();
  496. }
  497.  
  498. EntityId BehaviorTreeManager::GetTreeInstanceEntityIdByIndex(const size_t index) const
  499. {
  500.         assert(index < m_instances.size());
  501.         Instances::const_iterator it = m_instances.begin();
  502.         std::advance(it, index);
  503.         return it->first;
  504. }
  505.  
  506. BehaviorTreeInstance* BehaviorTreeManager::GetBehaviorTree(const EntityId entityId) const
  507. {
  508.         Instances::const_iterator it = m_instances.find(entityId);
  509.         if (it != m_instances.end())
  510.                 return it->second.get();
  511.         return NULL;
  512. }
  513.  
  514. Variables::Collection* BehaviorTreeManager::GetBehaviorVariableCollection_Deprecated(const EntityId entityId) const
  515. {
  516.         if (BehaviorTreeInstance* instance = GetBehaviorTree(entityId))
  517.                 return &instance->variables;
  518.  
  519.         return NULL;
  520. }
  521.  
  522. const Variables::Declarations* BehaviorTreeManager::GetBehaviorVariableDeclarations_Deprecated(const EntityId entityId) const
  523. {
  524.         if (BehaviorTreeInstance* instance = GetBehaviorTree(entityId))
  525.                 return &instance->behaviorTreeTemplate->variableDeclarations;
  526.  
  527.         return NULL;
  528. }
  529.  
  530. #if defined(DEBUG_MODULAR_BEHAVIOR_TREE_WEB)
  531. void BehaviorTreeManager::Subscribe(const TGameWebDebugClientId clientId, const EntityId entityId)
  532. {
  533.         m_webSubscribers[clientId] = entityId;
  534. }
  535.  
  536. void BehaviorTreeManager::Unsubscribe(const TGameWebDebugClientId clientId)
  537. {
  538.         m_webSubscribers.erase(clientId);
  539. }
  540. #endif
  541.  
  542. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE
  543. void BehaviorTreeManager::UpdateDebugVisualization(UpdateContext updateContext, const EntityId entityId, DebugTree debugTree, BehaviorTreeInstance& instance, IEntity* agentEntity)
  544. {
  545.         #ifdef USING_BEHAVIOR_TREE_VISUALIZER
  546.         BehaviorTree::TreeVisualizer treeVisualizer(updateContext);
  547.         treeVisualizer.Draw(
  548.           debugTree
  549.           , instance.behaviorTreeTemplate->mbtFilename
  550.           , agentEntity->GetName()
  551.                 #ifdef USING_BEHAVIOR_TREE_LOG
  552.           , instance.behaviorLog
  553.                 #endif // USING_BEHAVIOR_TREE_LOG
  554.           , instance.timestampCollection
  555.           , instance.blackboard
  556.                 #ifdef USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  557.           , instance.eventsLog
  558.                 #endif // USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  559.           );
  560.         #endif // USING_BEHAVIOR_TREE_VISUALIZER
  561.  
  562.         #ifdef DEBUG_VARIABLE_COLLECTION
  563.         Variables::DebugHelper::DebugDraw(true, instance.variables, instance.behaviorTreeTemplate->variableDeclarations);
  564.         #endif // DEBUG_VARIABLE_COLLECTION
  565.  
  566. }
  567. #endif // DEBUG_MODULAR_BEHAVIOR_TREE
  568.  
  569. #ifdef USING_BEHAVIOR_TREE_EXECUTION_STACKS_FILE_LOG
  570. void BehaviorTreeManager::UpdateExecutionStackLogging(UpdateContext updateContext, const EntityId entityId, DebugTree debugTree, BehaviorTreeInstance& instance)
  571. {
  572.         ExecutionStackFileLoggerInstances::const_iterator itTreeHistory = m_executionStackFileLoggerInstances.find(entityId);
  573.         if (itTreeHistory != m_executionStackFileLoggerInstances.end())
  574.         {
  575.                 ExecutionStackFileLogger* logger = itTreeHistory->second.get();
  576.                 logger->LogDebugTree(debugTree, updateContext, instance);
  577.         }
  578. }
  579. #endif
  580.  
  581. #ifdef DEBUG_MODULAR_BEHAVIOR_TREE_WEB
  582. void BehaviorTreeManager::UpdateWebDebugChannel(const EntityId entityId, UpdateContext& updateContext, DebugTree& debugTree, BehaviorTreeInstance& instance, const bool bExecutionError)
  583. {
  584.         if (!m_bRegisteredAsDebugChannel)
  585.                 return;
  586.  
  587.         TGameWebDebugClientId clientId = GAME_WEBDEBUG_INVALID_CLIENT_ID;
  588.         for (WebSubscribers::const_iterator it = m_webSubscribers.begin(); it != m_webSubscribers.end(); ++it)
  589.         {
  590.                 if (it->second != entityId)
  591.                         continue;
  592.  
  593.                 clientId = it->first;
  594.                 break;
  595.         }
  596.  
  597.         if (clientId == GAME_WEBDEBUG_INVALID_CLIENT_ID)
  598.                 return;
  599.  
  600.         IGameWebDebugService* pWebDebugService = GetIGameWebDebugService();
  601.         if (pWebDebugService)
  602.         {
  603.                 DebugTreeSerializer treeSerializer(instance, debugTree, updateContext, bExecutionError);
  604.                 DynArray<char> messageBuffer;
  605.                 Serialization::SaveJsonBuffer(messageBuffer, treeSerializer);
  606.  
  607.                 IGameWebDebugService::SMessage message;
  608.                 message.clientId = clientId;
  609.                 message.pData = messageBuffer.data();
  610.                 message.dataSize = messageBuffer.size();
  611.  
  612.                 pWebDebugService->Publish(message);
  613.         }
  614. }
  615. #endif
  616.  
  617. void BehaviorTreeManager::HandleEvent(const EntityId entityId, Event& event)
  618. {
  619.         assert(entityId);
  620.  
  621.         if (BehaviorTreeInstance* behaviorTreeInstance = GetBehaviorTree(entityId))
  622.         {
  623.                 behaviorTreeInstance->behaviorTreeTemplate->signalHandler.ProcessSignal(event.GetCRC(), behaviorTreeInstance->variables);
  624.                 behaviorTreeInstance->timestampCollection.HandleEvent(event.GetCRC());
  625.                 BehaviorTree::EventContext context(entityId);
  626.                 behaviorTreeInstance->behaviorTreeTemplate->rootNode->SendEvent(context, event);
  627. #ifdef USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  628.                 behaviorTreeInstance->eventsLog.AddMessage(event.GetName());
  629. #endif // USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  630.         }
  631. #ifdef USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  632.         else
  633.         {
  634.                 const char* entityName = "";
  635.                 if (IEntity* entity = gEnv->pEntitySystem->GetEntity(entityId))
  636.                         entityName = entity->GetName();
  637.  
  638.                 stack_string errorText;
  639.                 errorText.Format("BehaviorTreeManager: The event '%s' was not handled because the entity '%s' is not running a behavior tree.", event.GetName(), entityName);
  640.                 gEnv->pLog->LogError(errorText.c_str());
  641.         }
  642. #endif // USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  643. }
  644. }
  645.  
downloadBehaviorTreeManager.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