#if GRAPH_DESIGNER
/// ---------------------------------------------
/// Behavior Designer
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.BehaviorDesigner.Runtime.Utility
{
using System;
using Unity.Entities;
using UnityEngine;
///
/// Bridges the public runtime assembly to the ECS execution systems.
///
public interface IBehaviorTreeExecutionController
{
void AddCleanupSystems(World world, ComponentSystemGroup behaviorTreeSystemGroup);
void AddReevaluateSystem(World world, ComponentSystemGroup beforeTraversalSystemGroup);
void AddTaskObjectSystem(World world, ComponentSystemGroup traversalTaskSystemGroup);
Type TaskObjectReevaluateSystemType { get; }
bool CompleteTraversal(World world, EntityManager entityManager);
void CompleteEvaluation(World world, EntityManager entityManager, bool stopRunning);
bool IsActive(World world, EntityManager entityManager);
}
///
/// Runtime access point for the Behavior Designer ECS execution systems.
///
public static class BehaviorTreeExecution
{
private const string c_ControllerTypeName = "Opsive.BehaviorDesigner.Runtime.Utility.BehaviorTreeExecutionController, Opsive.BehaviorDesigner.Runtime.Systems";
private static IBehaviorTreeExecutionController s_Controller;
private static bool s_ControllerResolveFailed;
///
/// Registers the execution controller implementation.
///
/// The controller implementation.
public static void Register(IBehaviorTreeExecutionController controller)
{
s_Controller = controller;
s_ControllerResolveFailed = false;
}
///
/// Adds the core cleanup systems to the behavior tree group.
///
/// The ECS world.
/// The behavior tree system group.
public static void AddCleanupSystems(World world, ComponentSystemGroup behaviorTreeSystemGroup)
{
if (!EnsureController()) {
return;
}
s_Controller.AddCleanupSystems(world, behaviorTreeSystemGroup);
}
///
/// Adds the reevaluation system to the before-traversal group.
///
/// The ECS world.
/// The before-traversal group.
public static void AddReevaluateSystem(World world, ComponentSystemGroup beforeTraversalSystemGroup)
{
if (!EnsureController()) {
return;
}
s_Controller.AddReevaluateSystem(world, beforeTraversalSystemGroup);
}
///
/// Adds the TaskObject system to the traversal task group.
///
/// The ECS world.
/// The traversal task group.
public static void AddTaskObjectSystem(World world, ComponentSystemGroup traversalTaskSystemGroup)
{
if (!EnsureController()) {
return;
}
s_Controller.AddTaskObjectSystem(world, traversalTaskSystemGroup);
}
///
/// Returns the TaskObject reevaluation system type.
///
public static Type TaskObjectReevaluateSystemType
{
get
{
return EnsureController() ? s_Controller.TaskObjectReevaluateSystemType : null;
}
}
///
/// Completes one traversal loop and returns true if another evaluation pass should run.
///
/// The ECS world.
/// The entity manager.
/// True if the traversal group should evaluate again.
public static bool CompleteTraversal(World world, EntityManager entityManager)
{
return EnsureController() && s_Controller.CompleteTraversal(world, entityManager);
}
///
/// Completes the evaluation system.
///
/// The ECS world.
/// The entity manager.
/// Is the traversal group stopping?
public static void CompleteEvaluation(World world, EntityManager entityManager, bool stopRunning)
{
if (!EnsureController()) {
return;
}
s_Controller.CompleteEvaluation(world, entityManager, stopRunning);
}
///
/// Returns true if any behavior tree is still active.
///
/// The ECS world.
/// The entity manager.
/// True if any behavior tree is still active.
public static bool IsActive(World world, EntityManager entityManager)
{
return EnsureController() && s_Controller.IsActive(world, entityManager);
}
///
/// Ensures the execution controller is available.
///
/// True if the controller is available.
private static bool EnsureController()
{
if (s_Controller != null) {
return true;
}
if (s_ControllerResolveFailed) {
return false;
}
var controllerType = Type.GetType(c_ControllerTypeName);
if (controllerType == null) {
Debug.LogError("Behavior Designer could not find the Runtime.Systems assembly. The package must include Opsive.BehaviorDesigner.Runtime.Systems for ECS behavior tree execution.");
s_ControllerResolveFailed = true;
return false;
}
s_Controller = Activator.CreateInstance(controllerType) as IBehaviorTreeExecutionController;
if (s_Controller != null) {
return true;
}
Debug.LogError($"Behavior Designer could not create the execution controller type {c_ControllerTypeName}.");
s_ControllerResolveFailed = true;
return false;
}
}
}
#endif