public override void OnStart() { int count = ChildCount(); ChildStatuses = new Status[count]; // Set the branch iterators. Branch iterators have this parallel node as their root. // Offset level order by +1 since the parallel parent is not included in branch traversal. BranchIterators = Enumerable .Range(0, count) .Select(i => new BehaviourIterator(Tree, levelOrder + 1)) .ToArray(); // Assign the branch iterator to nodes not under any parallel nodes. // Children under parallel nodes will have iterators assigned by the local parallel parent. // Each branch under a parallel node use their own branch iterator. for (int i = 0; i < count; i++) { BehaviourIterator branchIterator = BranchIterators[i]; foreach (BehaviourNode node in TreeTraversal.PreOrderSkipChildren(GetChildAt(i), n => n is ParallelComposite)) { node.Iterator = branchIterator; } } }
public void Interrupt(BehaviourNode subroot, bool bFullInterrupt = false) { // Interrupt this subtree. subroot.Iterator.StepBackInterrupt(subroot, bFullInterrupt); // Look for parallel nodes under the subroot. // Since the parallel count is usually small, we // can just do a linear iteration to interrupt multiple // parallel nodes. for (int pIndex = 0; pIndex < _parallelNodeCount; ++pIndex) { Parallel p = _parallelNodes[pIndex]; if (IsUnderSubtree(subroot, p)) { for (int itrIndex = 0; itrIndex < p.ChildCount(); ++itrIndex) { BehaviourIterator itr = p.GetIterator(itrIndex); // Only interrupt running iterators. if (itr.IsRunning) { // Get the child of the parallel node, and interrupt the child subtree. int childIndex = itr.FirstInTraversal; BehaviourNode firstNode = allNodes[childIndex]; itr.StepBackInterrupt(firstNode.Parent, bFullInterrupt); } } } } }
// Helper method to pre-process the tree before calling Start on nodes. // Mainly does caching and sets node index orders. private void PreProcess() { SetPostandLevelOrders(); mainIterator = new BehaviourIterator(this, 0); activeTimers = new Utility.UpdateList <Utility.Timer>(); SetRootIteratorReferences(); }
/// <summary> /// Processes the tree to calculate certain properties like node priorities, /// caching observers, and syncinc parallel iterators. /// The root must be set. /// </summary> private void preProcess() { if (_root == null) { Debug.Log("The tree must have a valid root in order to be pre-processed"); return; } CalculateTreeOrders(); _mainIterator = new BehaviourIterator(this, 0); // Setup a new list for the observer nodes. _observerAborts = new List <ConditionalAbort>(); cacheObservers(); syncIterators(); }
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); } } }