/// <summary> /// Deep copies the tree. /// </summary> /// <param name="sourceTree">The source tree to clone.</param> /// <returns>The cloned tree.</returns> public static BehaviourTree Clone(BehaviourTree sourceTree) { // The tree clone will be blank to start. We will duplicate blackboard and nodes. var cloneBt = CreateInstance <BehaviourTree>(); cloneBt.name = sourceTree.name; if (sourceTree.blackboard) { cloneBt.blackboard = Instantiate(sourceTree.blackboard); } // Source tree nodes should already be in pre-order. cloneBt.SetNodes(sourceTree.Nodes.Select(n => Instantiate(n))); // Relink children and parents for the cloned nodes. int maxCloneNodeCount = cloneBt.allNodes.Length; for (int i = 0; i < maxCloneNodeCount; ++i) { BehaviourNode nodeSource = sourceTree.allNodes[i]; BehaviourNode copyNode = GetInstanceVersion(cloneBt, nodeSource); if (copyNode.IsComposite()) { var copyComposite = copyNode as Composite; copyComposite.SetChildren( Enumerable.Range(0, nodeSource.ChildCount()) .Select(childIndex => GetInstanceVersion(cloneBt, nodeSource.GetChildAt(childIndex))) .ToArray()); } else if (copyNode.IsDecorator() && nodeSource.ChildCount() == 1) { var copyDecorator = copyNode as Decorator; copyDecorator.SetChild(GetInstanceVersion(cloneBt, nodeSource.GetChildAt(0)));; } } foreach (BehaviourNode node in cloneBt.allNodes) { node.OnCopy(); } return(cloneBt); }
private BehaviourNode PreOrderNext() { BehaviourNode current = traversal.Pop(); for (int i = current.ChildCount() - 1; i >= 0; --i) { BehaviourNode child = current.GetChildAt(i); traversal.Push(child); } return(current); }
private BehaviourNode PopNode() { int index = traversal.Pop(); BehaviourNode node = tree.Nodes[index]; if (node.IsComposite()) { for (int i = 0; i < node.ChildCount(); i++) { node.GetChildAt(i).OnCompositeParentExit(); } } node.OnExit(); return(node); }
private void SyncIterators() { SyncParallelIterators(); _root._iterator = _mainIterator; BehaviourIterator itr = _mainIterator; var parallelRoots = new Stack <BehaviourNode>(); // This function handles assigning the iterator and skipping nodes. // The parallel root uses the same iterator as its parent, but the children // of the parallel node use their own iterator. Func <BehaviourNode, bool> skipAndAssign = (node) => { node._iterator = itr; bool bIsParallel = node as Parallel != null; if (bIsParallel) { parallelRoots.Push(node); } return(bIsParallel); }; Action <BehaviourNode> nothing = (node) => { }; // Assign the main iterator to nodes not under any parallel nodes. TreeIterator <BehaviourNode> .Traverse(_root, nothing, skipAndAssign); while (parallelRoots.Count != 0) { BehaviourNode parallel = parallelRoots.Pop(); // Do passes for each child, using the sub iterator associated with that child. for (int i = 0; i < parallel.ChildCount(); ++i) { itr = (parallel as Parallel).GetIterator(i); TreeIterator <BehaviourNode> .Traverse(parallel.GetChildAt(i), nothing, skipAndAssign); } } }