Esempio n. 1
0
        /// <summary>
        /// Deep copies the tree.
        /// Make sure that the original behaviour tree has its pre-orders calculated.
        /// </summary>
        /// <param name="originalBT"></param>
        /// <returns></returns>
        public static BehaviourTree Clone(BehaviourTree originalBT)
        {
            var cloneBt = Instantiate(originalBT);

            if (originalBT._blackboard)
            {
                cloneBt._blackboard = Instantiate(originalBT._blackboard);
            }

            cloneBt.allNodes.Clear();

            Action <BehaviourNode> copier = (originalNode) =>
            {
                var nodeCopy = Instantiate(originalNode);

                // Linke the root copy.
                if (originalBT.Root == originalNode)
                {
                    cloneBt.Root = nodeCopy;
                }

                // Nodes will be added in pre-order.
                nodeCopy.ClearTree();
                nodeCopy.Tree = cloneBt;
            };

            // Traversing in tree order will make sure that the runtime tree has its nodes properly sorted
            // in pre-order and will also make sure that dangling nodes are left out (unconnected nodes from the editor).
            TreeIterator <BehaviourNode> .Traverse(originalBT.Root, copier);

            // At this point the clone BT has its children in pre order order
            // and the original BT has pre-order indices calculated for each node.
            //
            // RELINK children and parent associations of the cloned nodes.
            // The clone node count is <= original node count because the editor may have dangling nodes.
            int maxCloneNodeCount = cloneBt.allNodes.Count;

            for (int i = 0; i < maxCloneNodeCount; ++i)
            {
                BehaviourNode originalNode   = originalBT.allNodes[i];
                BehaviourNode originalParent = originalNode.Parent;

                if (originalParent)
                {
                    BehaviourNode copyNode   = GetInstanceVersion(cloneBt, originalNode);
                    BehaviourNode copyParent = GetInstanceVersion(cloneBt, originalParent);

                    copyParent.ForceSetChild(copyNode);
                }
            }

            for (int i = 0; i < maxCloneNodeCount; ++i)
            {
                cloneBt.allNodes[i].OnCopy();
            }

            IncludeTreeReferences(cloneBt);

            return(cloneBt);
        }
Esempio n. 2
0
        /// <summary>
        /// Computes the pre and post orders of all nodes.
        /// </summary>
        public void CalculateTreeOrders()
        {
            ResetOrderIndices();

            int orderCounter = 0;

            Action <BehaviourNode> preOrder = (node) =>
            {
                node.preOrderIndex = orderCounter++;
            };

            TreeIterator <BehaviourNode> .Traverse(_root, preOrder);

            orderCounter = 0;


            Action <BehaviourNode> postOrder = (node) =>
            {
                node.postOrderIndex = orderCounter++;
            };

            TreeIterator <BehaviourNode> .Traverse(_root, postOrder, Traversal.PostOrder);


            Action <BehaviourNode, TreeIterator <BehaviourNode> > levelOrder = (node, itr) =>
            {
                node.levelOrder = itr.CurrentLevel;

                // This will end up with the highest level.
                Height = itr.CurrentLevel;
            };

            TreeIterator <BehaviourNode> .Traverse(_root, levelOrder, Traversal.LevelOrder);
        }
Esempio n. 3
0
        /// <summary>
        /// A helper method to traverse all nodes and execute an action per node.
        /// This method also passes the iterator doing the traversal.
        /// </summary>
        /// <param name="root">The traversal start.</param>
        /// <param name="onNext">The action to execute per node.</param>
        /// <param name="traversal">The type of DFS traversal.</param>
        public static void Traverse(T root, Action <T, TreeIterator <T> > onNext, Traversal traversal = Traversal.PreOrder)
        {
            var itr = new TreeIterator <T>(root, traversal);

            while (itr.HasNext())
            {
                var node = itr.Next();
                onNext(node, itr);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// A helper method to traverse all nodes and accumulate a value over the traversal.
        /// </summary>
        /// <typeparam name="TAccum"></typeparam>
        /// <param name="root"></param>
        /// <param name="accumulator">The function used to accumulate the value</param>
        /// <param name="initial">The starting value for the accumulation</param>
        /// <param name="traversal"></param>
        /// <returns></returns>
        public static TAccum Traverse <TAccum>(T root, Func <TAccum, T, TAccum> accumulator, TAccum initial, Traversal traversal = Traversal.PreOrder)
        {
            var itr = new TreeIterator <T>(root, traversal);

            while (itr.HasNext())
            {
                var node = itr.Next();
                initial = accumulator(initial, node);
            }

            return(initial);
        }
Esempio n. 5
0
        /// <summary>
        /// A pre-order traversal with the option to skip some nodes.
        /// </summary>
        /// <param name="root"></param>
        /// <param name="onNext"></param>
        /// <param name="skipFilter"></param>
        public static void Traverse(T root, Action <T> onNext, Func <T, bool> skipFilter)
        {
            if (skipFilter(root))
            {
                return;
            }

            var itr = new TreeIterator <T>(root);

            itr._skipFilter = skipFilter;

            while (itr.HasNext())
            {
                var node = itr.Next();
                onNext(node);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// A helper method to traverse all nodes and execute an action per node.
        /// </summary>
        /// <param name="root">The travseral start.</param>
        /// <param name="onNext">The action to execute per node.</param>
        /// <param name="traversal">The type of DFS traversal.</param>
        public static void Traverse(
            T root,
            Action <T> onNext,
            Traversal traversal = Traversal.PreOrder,
            TraversalSkip skip  = TraversalSkip.None)
        {
            var itr = new TreeIterator <T>(root, traversal);

            if (skip == TraversalSkip.Root)
            {
                itr.Next();
            }

            while (itr.HasNext())
            {
                var node = itr.Next();
                onNext(node);
            }
        }
Esempio n. 7
0
        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);
                }
            }
        }