void OnGUI()
        {
            if (Tree == null)
            {
                Viewer.DrawStaticGrid(position.size);
                Viewer.DrawMode();
                Editor.EditorMode = BonsaiEditor.Mode.Edit;
            }

            else
            {
                // Make sure to build a canvas for an active tree.
                if (Editor.Canvas == null)
                {
                    BuildCanvas();
                }

                CanvasTransform t = Transform;
                Editor.PollInput(Event.current, t, CanvasInputRect);
                Viewer.Draw(t);
            }

            DrawToolbar();
            UpdateWindowTitle();
        }
        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);
        }
Exemple #3
0
        public void HandleMouseEvents(
            Event e,
            CanvasTransform transform,
            IReadOnlyList <BonsaiNode> nodes,
            Rect inputRect)
        {
            // Mouse must be inside the editor canvas.
            if (!inputRect.Contains(e.mousePosition))
            {
                CanvasLostFocus(this, EventArgs.Empty);
                return;
            }

            HandleClickActions(transform, nodes, e);

            if (EditInputEnabled)
            {
                HandleEditorShortcuts(e);

                if (e.type == EventType.ContextClick)
                {
                    HandleContextInput(transform, nodes);
                    e.Use();
                }
            }
        }
Exemple #4
0
 public static void DrawLineCanvasSpace(CanvasTransform t, Vector2 start, Vector2 end, Color color, float width)
 {
     start = t.CanvasToScreenSpace(start);
     end   = t.CanvasToScreenSpace(end);
     if (t.IsScreenAxisLineInView(start, end))
     {
         DrawLineScreenSpace(start, end, color, width);
     }
 }
        public void Draw(CanvasTransform t)
        {
            if (Event.current.type == EventType.Repaint)
            {
                DrawGrid(t);
                DrawMode();
            }

            DrawCanvasContents(t);
        }
Exemple #6
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 DrawNodes(CanvasTransform t)
 {
     if (editorMode == BonsaiEditor.Mode.Edit)
     {
         DrawNodesInEditMode(t);
     }
     else
     {
         DrawNodesInViewMode(t);
     }
 }
Exemple #8
0
 private void HandleContextInput(CanvasTransform t, IReadOnlyList <BonsaiNode> nodes)
 {
     if (selection.IsMultiSelection)
     {
         HandleMultiContext();
     }
     else
     {
         HandleSingleContext(t, nodes);
     }
 }
        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);
            }
        }
        // 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));
                }
            }
        }
        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);
                }
            }
        }
        private void DrawCanvasContents(CanvasTransform t)
        {
            var canvasRect = new Rect(Vector2.zero, t.size);

            ScaleUtility.BeginScale(canvasRect, ZoomScale, BonsaiWindow.toolbarHeight);

            CustomDraw?.Invoke(t);
            DrawConnections(t);
            DrawNodes(t);

            ScaleUtility.EndScale(canvasRect, ZoomScale, BonsaiWindow.toolbarHeight);

            // Overlays and independent of zoom.
            CustomOverlayDraw?.Invoke();
        }
Exemple #13
0
        /// <summary>
        /// Get the first node detected under the mouse. Ports are counted as port of the check.
        /// </summary>
        /// <returns></returns>
        private static BonsaiNode NodeUnderMouse(CanvasTransform transform, IReadOnlyList <BonsaiNode> nodes)
        {
            // Iterate in reverse so the last drawn node (top) receives input first.
            for (int i = nodes.Count - 1; i >= 0; i--)
            {
                BonsaiNode node = nodes[i];
                if (IsUnderMouse(transform, node.ContentRectClick) ||
                    IsUnderMouse(transform, node.InputRect) ||
                    IsUnderMouse(transform, node.OutputRect))
                {
                    return(node);
                }
            }

            return(null);
        }
Exemple #14
0
        private void HandleSingleContext(CanvasTransform t, IReadOnlyList <BonsaiNode> nodes)
        {
            BonsaiNode node = NodeUnderMouse(t, nodes);

            if (node != null)
            {
                NodeContextClick?.Invoke(this, node);
                CreateSingleSelectionContextMenu(node).ShowAsContext();
            }

            else
            {
                CanvasContextClick?.Invoke(this, EventArgs.Empty);
                ShowCreateNodeMenu();
            }
        }
Exemple #15
0
        private void HandleClickActions(CanvasTransform t, IReadOnlyList <BonsaiNode> nodes, Event e)
        {
            if (IsClickAction(e))
            {
                if (quickClicksCount == 0)
                {
                    doubleClickTimer.Start();
                }

                clickTimer.Start();
                MouseDown?.Invoke(this, CreateInputEvent(t, nodes));
            }

            else if (IsUnlickAction(e))
            {
                BonsaiInputEvent inputEvent = CreateInputEvent(t, nodes);

                // A node click is registered if below a time threshold.
                if (clickTimer.Enabled)
                {
                    Click?.Invoke(this, inputEvent);
                }

                // Collect quick, consecutive clicks.
                if (doubleClickTimer.Enabled)
                {
                    quickClicksCount++;
                }

                // Double click event occured.
                if (quickClicksCount >= 2)
                {
                    DoubleClick?.Invoke(this, inputEvent);
                    doubleClickTimer.Stop();
                    quickClicksCount = 0;
                }

                clickTimer.Stop();
                MouseUp?.Invoke(this, inputEvent);
            }
        }
Exemple #16
0
        private static BonsaiInputEvent CreateInputEvent(CanvasTransform transform, IReadOnlyList <BonsaiNode> nodes)
        {
            bool       isInputFocused  = false;
            bool       isOutputFocused = false;
            BonsaiNode node            = NodeUnderMouse(transform, nodes);

            if (node != null)
            {
                isInputFocused  = IsInputUnderMouse(transform, node);
                isOutputFocused = IsOutputUnderMouse(transform, node);
            }

            return(new BonsaiInputEvent
            {
                transform = transform,
                canvasMousePostion = MousePosition(transform),
                node = node,
                isInputFocused = isInputFocused,
                isOutputFocused = isOutputFocused
            });
        }
Exemple #17
0
        public static void DrawNode(
            CanvasTransform t,
            BonsaiNode node,
            Color statusColor)
        {
            // Convert the node rect from canvas to screen space.
            Rect screenRect = node.RectPositon;

            screenRect.position = t.CanvasToScreenSpace(screenRect.position);

            // Remember the original color that way it is reset when the function exits.
            Color originalColor = GUI.color;

            DrawNodeBackground(screenRect, statusColor);

            // The node contents are grouped together within the node body.
            GUI.BeginGroup(screenRect);

            // Make the body of node local to the group coordinate space.
            Rect localRect = node.RectPositon;

            localRect.position = Vector2.zero;

            // Draw the contents inside the node body, automatically laid out.
            GUILayout.BeginArea(localRect, GUIStyle.none);

            DrawNodeTypeBackground(node);
            DrawExitStatus(node);
            DrawNodeContent(node);
            DrawBreakpoint(node);
            DrawPreOrderIndex(node);

            GUILayout.EndArea();

            GUI.EndGroup();
            GUI.color = originalColor;
        }
        private void DrawGrid(CanvasTransform t)
        {
            var canvasRect = new Rect(Vector2.zero, t.size);

            Drawer.DrawGrid(canvasRect, Preferences.gridTexture, ZoomScale, panOffset);
        }
Exemple #19
0
        public static void DrawNodeConnections(CanvasTransform t, BonsaiNode node)
        {
            if (node.ChildCount() == 0)
            {
                return;
            }

            var prefs = BonsaiPreferences.Instance;

            Color connectionColor = prefs.defaultConnectionColor;
            float connectionWidth = prefs.defaultConnectionWidth;

            if (node.Behaviour.StatusEditorResult == BTNode.EStatusEditor.Running)
            {
                connectionColor = prefs.runningStatusColor;
                connectionWidth = prefs.runningConnectionWidth;
            }

            // Start the Y anchor coord at the tip of the Output port.
            float yoffset = node.RectPositon.yMax;

            // Calculate the anchor position.
            float anchorX = node.RectPositon.center.x;
            float anchorY = (yoffset + node.GetNearestInputY()) / 2f;

            // Anchor line, between the first and last child.

            // Find the min and max X coords between the children and the parent.
            node.GetBoundsX(out float anchorLineStartX, out float anchorLineEndX);

            // Get start and end positions of the anchor line (The common line where the parent and children connect).
            var anchorLineStart = new Vector2(anchorLineStartX, anchorY);
            var anchorLineEnd   = new Vector2(anchorLineEndX, anchorY);

            // The tip where the parent starts its line to connect to the anchor line.
            var parentAnchorTip = new Vector2(anchorX, yoffset);

            // The point where the parent connects to the anchor line.
            var parentAnchorLineConnection = new Vector2(anchorX, anchorY);

            // Draw the lines from the calculated positions.
            DrawLineCanvasSpace(
                t,
                parentAnchorTip,
                parentAnchorLineConnection,
                connectionColor,
                connectionWidth);

            DrawLineCanvasSpace(
                t,
                anchorLineStart,
                anchorLineEnd,
                prefs.defaultConnectionColor,
                prefs.defaultConnectionWidth);

            foreach (BonsaiNode child in node.Children)
            {
                // Get the positions to draw a line between the node and the anchor line.
                Vector2 center = child.InputRect.center;
                var     anchorLineConnection = new Vector2(center.x, anchorY);

                // The node is running, hightlight the connection.
                if (child.Behaviour.StatusEditorResult == BTNode.EStatusEditor.Running)
                {
                    DrawLineCanvasSpace(
                        t,
                        center,
                        anchorLineConnection,
                        prefs.runningStatusColor,
                        prefs.runningConnectionWidth);

                    // Hightlight the portion of the anchorline between the running child and parent node.
                    DrawLineCanvasSpace(
                        t,
                        anchorLineConnection,
                        parentAnchorLineConnection,
                        prefs.runningStatusColor,
                        prefs.runningConnectionWidth);
                }
                else
                {
                    // The node is not running, draw a default connection.
                    DrawLineCanvasSpace(
                        t,
                        anchorLineConnection,
                        center,
                        prefs.defaultConnectionColor,
                        prefs.defaultConnectionWidth);
                }
            }
        }
Exemple #20
0
 public static void DrawLineCanvasSpace(CanvasTransform t, Vector2 start, Vector2 end, Color color)
 {
     start = t.CanvasToScreenSpace(start);
     end   = t.CanvasToScreenSpace(end);
     DrawLineScreenSpace(start, end, color);
 }
Exemple #21
0
 /// <summary>
 /// Returns the mouse position in canvas space.
 /// </summary>
 /// <returns></returns>
 public static Vector2 MousePosition(CanvasTransform transform)
 {
     return(transform.ScreenToCanvasSpace(Event.current.mousePosition));
 }
Exemple #22
0
 /// <summary>
 /// Tests if the rect is under the mouse.
 /// </summary>
 /// <param name="r"></param>
 /// <returns></returns>
 public static bool IsUnderMouse(CanvasTransform transform, Rect r)
 {
     return(r.Contains(MousePosition(transform)));
 }
Exemple #23
0
 /// <summary>
 /// Get the ouput for the node if under the mouse.
 /// </summary>
 /// <param name="node"></param>
 /// <returns></returns>
 private static bool IsOutputUnderMouse(CanvasTransform t, BonsaiNode node)
 {
     return(node.HasOutput && IsUnderMouse(t, node.OutputRect));
 }
Exemple #24
0
 /// <summary>
 /// Get the input for the node if under the mouse.
 /// </summary>
 /// <param name="node"></param>
 /// <returns></returns>
 private static bool IsInputUnderMouse(CanvasTransform t, BonsaiNode node)
 {
     return(IsUnderMouse(t, node.InputRect));
 }
Exemple #25
0
 public static void DrawPort(CanvasTransform t, Rect portRect)
 {
     // Convert the body rect from canvas to screen space.
     portRect.position = t.CanvasToScreenSpace(portRect.position);
     GUI.DrawTexture(portRect, BonsaiPreferences.Instance.portTexture, ScaleMode.StretchToFill);
 }