//============= Copyright (c) Ludic GmbH, All rights reserved. ============== // // Purpose: Part of the My Behaviour Tree Code // //============================================================================= using System; using System.Collections; using System.Collections.Generic; using System.Xml.Serialization; using UnityEngine; namespace MyBT { [System.Serializable] public class NodeRuntimeData : IDisposable { [NonSerialized] protected Node node; [NonSerialized] protected NodeRuntimeData parentNodeRuntimeData; [NonSerialized] protected List childNodeRuntimeData = new List(); [SerializeField] public string logString = ""; [NonSerialized] public bool taskHasChanges = false; public IEnumerator tickExecuteEnumerator = null; // only used for debugging, no actual function public int currentIndex = -1; #if UNITY_EDITOR && false // debug version of result & state, slower [SerializeField] private NodeResult _nodeResult; public NodeResult nodeResult { get { return _nodeResult; } set { _nodeResult = value; if (node != null) if (node.debugInternalActive) Debug.Log(node.NodeLogger("nodeResultSet", $"set Node Result '{value}'")); } } [SerializeField] private NodeState _nodeState = NodeState.NotRunning; public NodeState nodeState { get { return _nodeState; } set { _nodeState = value; if (node != null) if (node.debugInternalActive) Debug.Log(node.NodeLogger("nodeStateSet", $"set Node State '{value}'")); } } #else // more performant solution for runtime public NodeResult nodeResult; public NodeState nodeState = NodeState.NotRunning; #endif public IEnumerator[] subTickExecuteEnumerators = null; public NodeResult[] childResults; public NodeRuntimeData (Node _node, NodeRuntimeData _parentNodeRuntimeData) { node = _node; parentNodeRuntimeData = _parentNodeRuntimeData; if (node.debugChangesActive) UnityEngine.Debug.Log(node.NodeLogger("NodeRuntimeData.Constructor", $"")); node.nodeRuntimeDataList.Add(this); // root has no parent if (parentNodeRuntimeData != null) { parentNodeRuntimeData.childNodeRuntimeData.Add(this); } } ~NodeRuntimeData() { if (node.debugChangesActive) UnityEngine.Debug.Log(node.NodeLogger("NodeRuntimeData.Destructor", $"")); Dispose(false); } public virtual void Destroy() { if ((node != null) && (node.debugInternalActive)) { Debug.Log($"NodeRuntimeData.Destroy {node}"); } else { }; // node can be null if (childNodeRuntimeData != null) { for (int i= childNodeRuntimeData.Count-1; i>-1; i--) { childNodeRuntimeData[i].Destroy(); } } if (node != null) { switch (node.GetType().ToString()) { case "MyBT.RunTreeNode": node.PreTick(NodeExecute.Abort, this); //cn2.node.Execute(this, NodeExecute.Abort); tickExecuteEnumerator.MoveNext(); if (node.debugInternalActive) Debug.Log(node.NodeLogger($"NodeRuntimeData.Destroy", $"childNode result {tickExecuteEnumerator.Current}")); node.PostTick(NodeExecute.Abort, this); break; case "MyBT.ActionNode": node.Execute(this, NodeExecute.Abort); break; case "MyBT.CompositeNode": node.PreTick(NodeExecute.Abort, this); if (tickExecuteEnumerator != null) { tickExecuteEnumerator.MoveNext(); } else if ((subTickExecuteEnumerators != null) && (subTickExecuteEnumerators.Length > 0)) { for (int j = 0; j < subTickExecuteEnumerators.Length; j++) { subTickExecuteEnumerators[j].MoveNext(); } } else { //Debug.LogWarning($"{node} has no tick or subTick enumerator"); } if (node.debugInternalActive) Debug.Log(node.NodeLogger($"NodeRuntimeData.Destroy", $"")); node.PostTick(NodeExecute.Abort, this); break; default: break; } node.nodeRuntimeDataList.Remove(this); } tickExecuteEnumerator = null; subTickExecuteEnumerators = null; nodeResult = NodeResult.Undefined; logString = ""; parentNodeRuntimeData = null; childNodeRuntimeData = new List(); node = null; } public virtual void Clear() { logString = ""; } // Flag: Has Dispose already been called? [System.NonSerialized] bool disposed = false; // Public implementation of Dispose pattern callable by consumers. public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // Protected implementation of Dispose pattern. protected virtual void Dispose(bool disposing) { if (disposed) return; if (disposing) { // Free any other managed objects here. Destroy(); } // Free any unmanaged objects here. // disposed = true; } } }