private void SingleNodeAction(object sender, BonsaiInput.NodeContext actionType)
        {
            switch (actionType)
            {
            case BonsaiInput.NodeContext.SetAsRoot:
                Canvas.SetRoot(NodeSelection.SingleSelectedNode);
                break;

            case BonsaiInput.NodeContext.Duplicate:
                EditorNodeCreation.DuplicateSingle(Canvas, NodeSelection.SingleSelectedNode);
                break;

            case BonsaiInput.NodeContext.FormatTree:
                BonsaiNode root = NodeSelection.SingleSelectedNode;
                Formatter.PositionNodesNicely(root, root.Center);
                break;

            case BonsaiInput.NodeContext.Delete:
                RemoveSelectedNodes();
                break;

            case BonsaiInput.NodeContext.AddBreakPoint:
                SetBreakPoint(NodeSelection.SingleSelectedNode, true);
                break;

            case BonsaiInput.NodeContext.DeleteBreakPoint:
                SetBreakPoint(NodeSelection.SingleSelectedNode, false);
                break;
            }

            UpdateAbortableSelection();
        }
        public void ToggleSelecion(BonsaiNode node)
        {
            if (IsNodeSelected(node))
            {
                selectedNodes.Remove(node);
            }
            else
            {
                selectedNodes.Add(node);
            }

            if (IsSingleSelection)
            {
                BonsaiNode selectedNode = SingleSelectedNode;
                Selection.objects      = null;
                Selection.activeObject = selectedNode.Behaviour;
                SingleSelected?.Invoke(this, selectedNode);
                //SelectReferencedNodes(selectedNode);
            }

            else if (IsMultiSelection)
            {
                Selection.objects = selectedNodes.Select(n => n.Behaviour).ToArray();
            }
        }
示例#3
0
        /// <summary>
        /// Formats the tree to look nicely.
        /// </summary>
        public static void PositionNodesNicely(BonsaiNode root, Vector2 anchor)
        {
            // Sort parent-child connections so formatter uses latest changes.
            foreach (BonsaiNode node in TreeTraversal.PreOrder(root))
            {
                node.SortChildren();
            }

            var positioning = new FormatPositioning();

            foreach (BonsaiNode node in TreeTraversal.PostOrder(root))
            {
                PositionHorizontal(node, positioning);
            }

            foreach (BonsaiNode node in TreeTraversal.PreOrder(root))
            {
                PositionVertical(node);
            }

            // Move the entire subtree to the anchor.
            Vector2 offset = EditorSingleDrag.StartDrag(root, root.Center);

            EditorSingleDrag.SetSubtreePosition(root, anchor, offset);
        }
        public void PollInput(Event e, CanvasTransform t, Rect inputRect)
        {
            if (lastCreatedNodeToPosition != null)
            {
                lastCreatedNodeToPosition.Center = BonsaiInput.MousePosition(t);
                lastCreatedNodeToPosition        = null;
            }

            if (e.type == EventType.MouseDrag)
            {
                if (MotionAction != null)
                {
                    MotionAction(t);
                    OnCanvasChanged();
                }
            }

            if (BonsaiInput.IsPanAction(e))
            {
                Pan(e.delta);
                OnCanvasChanged();
            }

            if (BonsaiInput.IsZoomAction(e))
            {
                Zoom(e.delta.y);
                OnCanvasChanged();
            }

            Input.HandleMouseEvents(e, t, Canvas.Nodes, inputRect);
        }
        private void StartSingleDrag(BonsaiInputEvent startEvent)
        {
            BonsaiNode node   = startEvent.node;
            Vector2    offset = EditorSingleDrag.StartDrag(node, startEvent.canvasMousePostion);

            MotionAction = (CanvasTransform t) => EditorSingleDrag.Drag(node, BonsaiInput.MousePosition(t), offset);
        }
        private Color NodeStatusColor(BonsaiNode node)
        {
            if (!node.Behaviour.IsValid())
            {
                return(Color.red);
            }

            if (IsNodeObserving(node))
            {
                return(Preferences.evaluateColor);
            }
            else if (IsNodeRunning(node))
            {
                return(Preferences.runningColor);
            }
            else if (NodeSelection.IsNodeSelected(node))
            {
                return(Preferences.selectedColor);
            }
            //else if (NodeSelection.IsReferenced(node))
            //{
            //    return Preferences.referenceColor;
            //}
            else if (abortableSelected.Contains(node))
            {
                return(Preferences.abortColor);
            }
            else if (Canvas.Root == node)
            {
                return(Preferences.rootSymbolColor);
            }

            return(Preferences.defaultNodeBackgroundColor);
        }
示例#7
0
        public static void DrawExitStatus(BonsaiNode node)
        {
            // Draw the exit status in the top right corner.
            float statusSize  = BonsaiPreferences.Instance.statusIconSize;
            Rect  contentRect = node.ContentRect;
            var   rect        = new Rect(contentRect.xMin, contentRect.yMin, statusSize, statusSize);

            var prefs  = BonsaiPreferences.Instance;
            var status = node.Behaviour.StatusEditorResult;

            if (status == BTNode.EStatusEditor.Success)
            {
                DrawTexture(rect, prefs.successSymbol, prefs.successColor);
            }

            else if (status == BTNode.EStatusEditor.Failure)
            {
                DrawTexture(rect, prefs.failureSymbol, prefs.failureColor);
            }

            else if (status == BTNode.EStatusEditor.Aborted)
            {
                DrawTexture(rect, prefs.failureSymbol, prefs.abortedColor);
            }

            else if (status == BTNode.EStatusEditor.Interruption)
            {
                DrawTexture(rect, prefs.failureSymbol, prefs.interruptedColor);
            }
        }
        // Creates and adds an editor node to the canvas.
        private BonsaiNode AddEditorNode(bool hasOutput, Texture icon = null)
        {
            var node = BonsaiNode.Create(hasOutput, icon);

            nodes.Add(node);

            return(node);
        }
        private BonsaiNode ReconstructEditorNode(BTNode behaviour)
        {
            BonsaiNode node = CreateNode(behaviour);

            node.Behaviour = behaviour;
            node.Position  = behaviour.nodePosition;
            return(node);
        }
        public void PushToEnd(BonsaiNode node)
        {
            bool bRemoved = nodes.Remove(node);

            if (bRemoved)
            {
                nodes.Add(node);
            }
        }
示例#11
0
        public static BonsaiNode DuplicateSingle(BonsaiCanvas canvas, BonsaiNode original)
        {
            BonsaiNode duplicate = canvas.CreateNode(original.Behaviour.GetType());

            // Duplicate nodes are placed offset from the original.
            duplicate.Position = original.Position + Vector2.one * 40f;

            return(duplicate);
        }
 private static void GetCompositeParent(BonsaiNode aborter, out BonsaiNode compositeParent, out BonsaiNode directChild)
 {
     directChild     = aborter;
     compositeParent = aborter.Parent;
     while (compositeParent != null && !compositeParent.Behaviour.IsComposite())
     {
         directChild     = compositeParent;
         compositeParent = compositeParent.Parent;
     }
 }
示例#13
0
        public static void DrawPorts(CanvasTransform t, BonsaiNode node)
        {
            // There is always an input port.
            DrawPort(t, node.InputRect);

            if (node.HasOutput)
            {
                DrawPort(t, node.OutputRect);
            }
        }
        private void DrawNodesInEditMode(CanvasTransform t)
        {
            var nodes = Canvas.Nodes;

            for (int i = 0; i < nodes.Count; i++)
            {
                BonsaiNode node = nodes[i];
                Drawer.DrawNode(t, node, NodeStatusColor(node));
                Drawer.DrawPorts(t, node);
            }
        }
        public void SetSingleSelection(BonsaiNode newSingleSelected)
        {
            selectedNodes.Clear();
            selectedNodes.Add(newSingleSelected);
#if UNITY_2019_1_OR_NEWER
            Selection.objects = null;
#endif
            Selection.activeObject = newSingleSelected.Behaviour;
            SingleSelected?.Invoke(this, newSingleSelected);
            //SelectReferencedNodes(newSingleSelected);
        }
        public void UpdateAbortableSelection(BonsaiNode node)
        {
            abortableSelected.Clear();

            var aborter = node.Behaviour as BTDecorator;

            if (aborter)
            {
                abortableSelected = new HashSet <BonsaiNode>(Abortables(node, aborter.abortType));
            }
        }
        public void UpdateNodeGUI(BTNode behaviour)
        {
            BonsaiNode node = Canvas.Nodes.FirstOrDefault(n => n.Behaviour == behaviour);

            if (node != null)
            {
                node.UpdateGui();
                node.Center = MathExtensions.SnapPosition(node.Center, SnapStep);
            }

            UpdateAbortableSelection();
        }
示例#18
0
 // Render the background color scheme for the node type.
 public static void DrawNodeTypeBackground(BonsaiNode node)
 {
     GUI.DrawTexture(
         node.ContentRect,
         BonsaiPreferences.Instance.nodeGradient,
         ScaleMode.StretchToFill,
         true,
         0f,
         NodeTypeColor(node),
         0f,
         4f);
 }
        // Reconstruct editor nodes from the tree.
        private Dictionary <BTNode, BonsaiNode> ReconstructEditorNodes(IEnumerable <BTNode> behaviours)
        {
            var nodeMap = new Dictionary <BTNode, BonsaiNode>();

            foreach (BTNode behaviour in behaviours)
            {
                BonsaiNode node = ReconstructEditorNode(behaviour);
                nodeMap.Add(behaviour, node);
            }

            return(nodeMap);
        }
 public void SetRoot(BonsaiNode newRoot)
 {
     if (newRoot.Parent == null)
     {
         Root = newRoot;
         //Undo.RecordObject(Root, "Set Root");
     }
     else
     {
         Debug.LogWarning("Root cannot be a child.");
     }
 }
        private void SetBreakPoint(BonsaiNode seletedNode, bool breakpoint)
        {
            if (seletedNode == null)
            {
                return;
            }
            if (seletedNode.Behaviour == null)
            {
                return;
            }

            seletedNode.Behaviour.BreakPoint = breakpoint;
        }
示例#22
0
        private void PopulateDecoratorNodes(GenericMenu menu, BonsaiNode node)
        {
            var decorators = BonsaiEditor.RegisteredBehaviourNodeTypes.Where(t => t.IsSubclassOf(typeof(BTAuxiliary)) && !t.IsAbstract);

            foreach (var subclass in decorators)
            {
                menu.AddItem(new GUIContent("Decorator/" + subclass.Name), false, () =>
                {
                    CreateNodeRequest?.Invoke("Decorator", subclass);
                    TypeChanged?.Invoke(this, node);
                });
            }
        }
示例#23
0
        // A "branch list" is a tree branch where nodes only have a single child.
        // e.g. Decorator -> Decorator -> Decorator -> Task
        private static float MaxWidthForBranchList(BonsaiNode leaf)
        {
            float maxWidth = leaf.Size.x;
            var   parent   = leaf.Parent;

            while (parent != null && parent.ChildCount() == 1)
            {
                maxWidth = Mathf.Max(maxWidth, parent.Size.x);
                parent   = parent.Parent;
            }

            return(maxWidth);
        }
        // Does not render ports in view mode since nodes cannot be changed.
        private void DrawNodesInViewMode(CanvasTransform t)
        {
            var nodes = Canvas.Nodes;

            for (int i = 0; i < nodes.Count; i++)
            {
                BonsaiNode node = nodes[i];
                if (t.InView(node.RectPositon))
                {
                    Drawer.DrawNode(t, node, NodeStatusColor(node));
                }
            }
        }
        public void Remove(BonsaiNode node)
        {
            if (nodes.Remove(node))
            {
                // Clear root since it was removed.
                if (node == Root)
                {
                    Root = null;
                }

                node.Destroy();
            }
        }
        /// <summary>
        /// Highlights nodes that are being re-evaluated, like abort nodes.
        /// </summary>
        /// <param name="node"></param>
        private bool IsNodeObserving(BonsaiNode node)
        {
            BTNode           behaviour = node.Behaviour;
            BehaviorIterator itr       = behaviour.Iterator;

            if (itr != null && itr.IsRunning)
            {
                var aborter = behaviour as BTDecorator;
                return(aborter && aborter.IsObserving);
            }

            return(false);
        }
示例#27
0
        private void PopulateTypeConversions(GenericMenu menu, BonsaiNode node)
        {
            Type coreType       = BonsaiEditor.CoreType(node.Behaviour);
            var  behaviourTypes = BonsaiEditor.RegisteredBehaviourNodeTypes;

            foreach (Type subclass in behaviourTypes.Where(t => t.IsSubclassOf(coreType) && !t.IsAbstract))
            {
                menu.AddItem(new GUIContent("Change Type/" + subclass.Name), false, () =>
                {
                    EditorChangeNodeType.ChangeType(node, subclass);
                    TypeChanged?.Invoke(this, node);
                });
            }
        }
        private void DrawConnections(CanvasTransform t)
        {
            var nodes = Canvas.Nodes;

            for (int i = 0; i < nodes.Count; i++)
            {
                BonsaiNode node = nodes[i];

                if (node.HasOutput)
                {
                    Drawer.DrawNodeConnections(t, node);
                }
            }
        }
示例#29
0
 /// <summary>
 /// draw breakpoint icon of this node
 /// </summary>
 /// <param name="node"></param>
 private static void DrawBreakpoint(BonsaiNode node)
 {
     if (node.Behaviour.BreakPoint)
     {
         GUI.DrawTexture(
             node.BreakpointRect,
             BonsaiPreferences.Instance.breakPoint,
             ScaleMode.StretchToFill,
             true,
             0f,
             Color.red,
             0f,
             4f);
     }
 }
示例#30
0
        private static void PositionVertical(BonsaiNode node)
        {
            BonsaiNode parent = node.Parent;

            if (parent != null)
            {
                float ySeperation = parent.ChildCount() == 1
          ? FormatPositioning.yLevelSeparation / 2f
          : FormatPositioning.yLevelSeparation;

                float x = node.Position.x;
                float y = parent.Position.y + parent.Size.y + ySeperation;
                node.Position = new Vector2(x, y);
            }
        }