using System.Collections; using System.Collections.Generic; using UnityEngine; using XNode; using RPGCreationKit.BehaviourTree; using UnityEditor; namespace RPGCreationKit.BehaviourTree { [CreateNodeMenu("RPGCK_BehaviourTree/Parallel", order = 1)] [System.Serializable] public class ParallelNode : BTNode { [Output(ShowBackingValue.Never, ConnectionType.Multiple, TypeConstraint.None)] public BTNode outputs; public bool stopIfChildFails = false; public bool stopIfChildSucceed = false; // Use this for initialization protected override void Init() { base.Init(); } public override void ReorderChild() { List endPorts = GetOutputPort("outputs").GetConnections(); List nodes = new List(); for (int i = 0; i < endPorts.Count; i++) nodes.Add((endPorts[i].node as BTNode)); nodes.Sort(SortInGraphYPos); for (int i = 0; i < nodes.Count; i++) { BTNode btNode = nodes[i] as BTNode; btNode.indexInSequence = i; } } // Return the correct value of an output port when requested public override object GetValue(NodePort port) { return null; // Replace this } public override NodeState Execute() { m_NodeState = NodeState.Running; if (m_NodeState == NodeState.Success || m_NodeState == NodeState.Failure) if (hasEvaluated == true) return m_NodeState; bool anyChildStillRunning = false; List endPorts = GetOutputPort("outputs").GetConnections(); for (int i = 0; i < endPorts.Count; i++) { BTNode node = (endPorts[i].node as BTNode); // If it's a parallel and a node has finished, restart it without waiting if ((node.hasEvaluated && (node.m_NodeState == NodeState.Success || node.m_NodeState == NodeState.Failure))) { node.hasEvaluated = false; node.ReEvaluate(); } else if (node.hasEvaluated) continue; switch ((endPorts[i].node as BTNode).Execute()) { case NodeState.Failure: if (stopIfChildFails) { m_NodeState = NodeState.Failure; for (int j = 0; j < endPorts.Count; j++) (endPorts[j].node as BTNode).m_NodeState = NodeState.Failure; return m_NodeState; } continue; case NodeState.Success: continue; case NodeState.Running: m_NodeState = NodeState.Running; anyChildStillRunning = true; continue; default: m_NodeState = NodeState.Running; return m_NodeState; } } m_NodeState = (anyChildStillRunning) ? NodeState.Running : NodeState.Success; if (m_NodeState == NodeState.Success) hasEvaluated = true; return m_NodeState; } public override void ReEvaluate() { if (m_NodeState != NodeState.Running) { base.ReEvaluate(); hasEvaluated = false; List endPorts = GetOutputPort("outputs").GetConnections(); for (int i = 0; i < endPorts.Count; i++) { (endPorts[i].node as BTNode).ReEvaluate(); } } } public override void OnCreateConnection(NodePort from, NodePort to) { base.OnCreateConnection(from, to); #if UNITY_EDITOR EditorApplication.delayCall += ReorderChild; #endif } public override void OnRemoveConnection(NodePort port) { if (port.fieldName == "input") indexInSequence = -1; else if (port.fieldName == "outputs") { #if UNITY_EDITOR EditorApplication.delayCall += ReorderChild; #endif } } public override void OnStart() { } } }