private void OnGUI()
        {
            if (m_btAsset != null)
            {
                Rect navHistoryRect = new Rect(0.0f, 0.0f, position.width, 20.0f);
                Rect optionsRect    = new Rect(position.width - 20.0f, 0.0f, 20.0f, 20.0f);
                Rect footerRect     = new Rect(0.0f, position.height - 18.0f, position.width, 20.0f);
                Rect canvasRect     = new Rect(0.0f, navHistoryRect.yMax, position.width, position.height - (footerRect.height + navHistoryRect.height));
                Rect debugRect      = new Rect(optionsRect.x - 60, 0.0f, 60.0f, 20.0f);

                BTEditorStyle.EnsureStyle();
                m_grid.DrawGUI(position.size);
                m_graph.DrawGUI(canvasRect);
                m_canvas.HandleEvents(canvasRect, position.size);
                m_hotkeyHandler.HandlerEvents();
                DrawNavigationHistory(navHistoryRect);
                DrawFooter(footerRect);
                DrawOptions(optionsRect);
                DrawDebug(debugRect);

                if (m_canvas.IsDebuging)
                {
                    OnRepaint();
                }
            }
        }
        private void DrawSelf()
        {
            string           label     = m_node.Title;
            BTGraphNodeStyle nodeStyle = BTEditorStyle.GetNodeStyle(m_node);
            Vector2          nodeSize  = BTEditorStyle.GetNodeSize(m_node);
            Rect             position  = new Rect(NodePosition + BTEditorCanvas.Current.Position, nodeSize);
            RunningStatus    status    = BTEditorCanvas.Current.IsDebuging ? GetNodeStatus(m_node) : RunningStatus.None;

            GUI.Box(position, "", nodeStyle.GetStyle(status, m_isSelected));

            int  iconSize    = 32;
            int  iconOffsetY = 7;
            Rect iconPos     = new Rect(position.x + (nodeSize.x - iconSize) / 2, position.y + (nodeSize.y - iconSize) / 2 - iconOffsetY, iconSize, iconSize);

            GUI.DrawTexture(iconPos, BTEditorStyle.GetNodeIcon(m_node));

            Rect titlePos = new Rect(position);

            titlePos.y = titlePos.y - 5;
            EditorGUI.LabelField(titlePos, label, BTEditorStyle.NodeTitleLabel);

            // show index of composite's children.
            if (Parent != null && Parent.Node is Composite)
            {
                Composite compNode    = Parent.Node as Composite;
                int       index       = compNode.GetIndex(m_node);
                Rect      nodeLeftPos = new Rect(position.x + 2, position.center.y - 8, 20, 16);
                EditorGUI.LabelField(nodeLeftPos, index.ToString(), EditorStyles.label);
            }

            if (m_node.Breakpoint != Breakpoint.None)
            {
                Rect imgPosition;
                if (m_node is NodeGroup)
                {
                    imgPosition = new Rect(position.x + 2, position.y + 2, 12, 12);
                }
                else
                {
                    imgPosition = new Rect(position.x + 2, position.y + 2, 12, 12);
                }

                GUI.DrawTexture(imgPosition, BTEditorStyle.Breakpoint);
            }

            // show obsolete icon
            if (BTNodeObsoleteFactory.IsObsolete(m_node))
            {
                int  obsSize     = 24;
                Rect obsoletePos = new Rect(position.x + nodeSize.x - obsSize - 5, position.y + 5, obsSize, obsSize);
                GUI.DrawTexture(obsoletePos, BTEditorStyle.WarningIcon);
            }
        }
 public override void OnInspectorGUI()
 {
     if (m_inspector != null)
     {
         BTEditorStyle.EnsureStyle();
         m_inspector.DrawGUI();
         Repaint();
     }
     else
     {
         EditorGUILayout.HelpBox("There are no values to display!", MessageType.Error);
     }
 }
        private void DrawTransitions()
        {
            Vector2            nodeSize   = BTEditorStyle.GetNodeSize(m_node);
            Rect               position   = new Rect(NodePosition + BTEditorCanvas.Current.Position, nodeSize);
            BTEditorTreeLayout treeLayout = BTEditorStyle.TreeLayout;

            foreach (var child in m_children)
            {
                Vector2       childNodeSize = BTEditorStyle.GetNodeSize(child.Node);
                Rect          childPosition = new Rect(child.Node.Position + BTEditorCanvas.Current.Position, childNodeSize);
                RunningStatus childStatus   = BTEditorCanvas.Current.IsDebuging ? GetNodeStatus(child.Node) : RunningStatus.None;
                Color         color         = BTEditorStyle.GetTransitionColor(childStatus);
                Vector2       nodeCenter    = position.center;
                Vector2       childCenter   = childPosition.center;

                if (treeLayout == BTEditorTreeLayout.Vertical)
                {
                    if (Mathf.Approximately(nodeCenter.y, childCenter.y) || Mathf.Approximately(nodeCenter.x, childCenter.x))
                    {
                        BTEditorUtils.DrawLine(nodeCenter, childCenter, color);
                    }
                    else
                    {
                        BTEditorUtils.DrawLine(nodeCenter, nodeCenter + Vector2.up * (childCenter.y - nodeCenter.y) / 2, color);

                        BTEditorUtils.DrawLine(nodeCenter + Vector2.up * (childCenter.y - nodeCenter.y) / 2,
                                               childCenter + Vector2.up * (nodeCenter.y - childCenter.y) / 2, color);

                        BTEditorUtils.DrawLine(childCenter, childCenter + Vector2.up * (nodeCenter.y - childCenter.y) / 2, color);
                    }
                }
                else if (treeLayout == BTEditorTreeLayout.Horizontal)
                {
                    //BTEditorUtils.DrawBezier(nodeCenter, childCenter, color);
                    Vector2 nodeRight = new Vector2(position.center.x + nodeSize.x / 2, position.center.y);
                    Vector2 childLeft = new Vector2(childPosition.center.x - childNodeSize.x / 2, childPosition.center.y);
                    BTEditorUtils.DrawBezier(nodeRight, childLeft, color);
                }
                else
                {
                    BTEditorUtils.DrawLine(nodeCenter, childCenter, color);
                }
            }
        }
        public BTEditorGraphNode OnInsertChild(int index, Type type)
        {
            if (type != null)
            {
                BehaviourNode node = BTUtils.CreateNode(type);
                if (node != null)
                {
                    Vector2 nodeSize = BTEditorStyle.GetNodeSize(m_node);
                    Vector2 nodePos  = NodePosition + nodeSize + new Vector2(50, 0);
                    nodePos.x = Mathf.Max(nodePos.x, 0.0f);
                    nodePos.y = Mathf.Max(nodePos.y, 0.0f);

                    // force horizontal
                    nodePos.y = NodePosition.y;

                    node.Position = nodePos;

                    return(OnInsertChild(index, node));
                }
            }

            return(null);
        }
        private void DrawConstraints()
        {
            if (m_node.Constraints.Count == 0)
            {
                return;
            }

            Vector2 nodeSize = BTEditorStyle.GetNodeSize(m_node);
            Rect    position = new Rect(NodePosition + BTEditorCanvas.Current.Position, nodeSize);

            Rect cnsFoldoutPos = new Rect(position.x - 15, position.y + position.height, 10, 10);

            m_node.IsConstraintsExpanded = EditorGUI.Foldout(cnsFoldoutPos, m_node.IsConstraintsExpanded, GUIContent.none);

            int constraintOffsetY = 3;

            if (!m_node.IsConstraintsExpanded)
            {
                Rect consLabelPos = new Rect(cnsFoldoutPos.x + 20, cnsFoldoutPos.y + constraintOffsetY, 100, 20);
                EditorGUI.LabelField(consLabelPos, "<color=white>Constraints</color>", BTEditorStyle.NodeConstraintLabel);
            }
            else
            {
                int bits = -1;
                if (BTDebugHelper.DebugContext != null && BTDebugHelper.CurrentDebugRootTree != null)
                {
                    long treeId = BTDebugHelper.CurrentDebugRootTree.guid;
                    if (BTDebugHelper.DebugContext._travelNodes.ContainsKey(treeId))
                    {
                        if (BTDebugHelper.DebugContext._travelNodes[treeId].Contains(m_node))
                        {
                            bits = BTDebugHelper.DebugContext.blackboard.GetInt(treeId, m_node.guid, "Constraints");
                        }
                    }
                }

                bool lastFailed = false;
                for (int i = 0; i < m_node.Constraints.Count; i++)
                {
                    Constraint constraint = m_node.Constraints[i];

                    Rect headerPos = position;
                    headerPos.y += nodeSize.y + i * 16 + constraintOffsetY;
                    Rect labelPos = new Rect(headerPos.x, headerPos.y, position.width + 100, 16);

                    string str = "";
                    if (bits != -1 && !lastFailed)
                    {
                        int v = (bits >> i) & 1;
                        if (v == 1)
                        {
                            str = string.Format(constraint.InvertResult ? "<color=green>! {0}</color>" : "<color=green>{0}</color>", constraint.Title);
                        }
                        else
                        {
                            lastFailed = true;
                            str        = string.Format(constraint.InvertResult ? "<color=red>! {0}</color>" : "<color=red>{0}</color>", constraint.Title);
                        }
                    }
                    else
                    {
                        str = string.Format(constraint.InvertResult ? "<color=white>! {0}</color>" : "<color=white>{0}</color>", constraint.Title);
                    }
                    EditorGUI.LabelField(labelPos, str, BTEditorStyle.NodeConstraintLabel);
                }
            }

            // show obsolete icon
            if (!BTNodeObsoleteFactory.IsObsolete(m_node))
            {
                for (int i = 0; i < m_node.Constraints.Count; i++)
                {
                    Constraint constraint = m_node.Constraints[i];
                    if (BTNodeObsoleteFactory.IsObsolete(constraint))
                    {
                        int  obsSize     = 24;
                        Rect obsoletePos = new Rect(position.x + nodeSize.x - obsSize - 5, position.y + 5, obsSize, obsSize);
                        GUI.DrawTexture(obsoletePos, BTEditorStyle.WarningIcon);
                        break;
                    }
                }
            }
        }
        private void HandleEvents()
        {
            Rect    position      = new Rect(NodePosition, BTEditorStyle.GetNodeSize(m_node));
            Vector2 mousePosition = BTEditorCanvas.Current.WindowSpaceToCanvasSpace(BTEditorCanvas.Current.Event.mousePosition);

            if (BTEditorCanvas.Current.Event.type == EventType.MouseDown && BTEditorCanvas.Current.Event.button == SELECT_MOUSE_BUTTON)
            {
                if (position.Contains(mousePosition))
                {
                    if (!m_isSelected)
                    {
                        m_graph.OnNodeSelect(this);
                    }

                    if (m_lastClickTime > 0)
                    {
                        if (Time.realtimeSinceStartup <= m_lastClickTime + DOUBLE_CLICK_THRESHOLD)
                        {
                            OnDoubleClicked();
                        }
                    }

                    m_lastClickTime = Time.realtimeSinceStartup;

                    m_canBeginDragging = !IsRoot;
                    BTEditorCanvas.Current.Event.Use();
                }
            }
            else if (BTEditorCanvas.Current.Event.type == EventType.MouseDown && BTEditorCanvas.Current.Event.button == CONTEXT_MOUSE_BUTTON)
            {
                if (position.Contains(mousePosition))
                {
                    ShowContextMenu();
                    BTEditorCanvas.Current.Event.Use();
                }
            }
            else if (BTEditorCanvas.Current.Event.type == EventType.MouseUp && BTEditorCanvas.Current.Event.button == SELECT_MOUSE_BUTTON)
            {
                if (m_isDragging)
                {
                    m_graph.OnNodeEndDrag(this);
                    BTEditorCanvas.Current.Event.Use();
                }
                m_canBeginDragging = false;
            }
            else if (BTEditorCanvas.Current.Event.type == EventType.MouseDrag && BTEditorCanvas.Current.Event.button == DRAG_MOUSE_BUTTON)
            {
                if (!m_graph.ReadOnly && !m_isDragging && m_canBeginDragging && position.Contains(mousePosition))
                {
                    m_graph.OnNodeBeginDrag(this, mousePosition);
                    BTEditorCanvas.Current.Event.Use();
                }
                else if (m_isDragging)
                {
                    m_graph.OnNodeDrag(this, mousePosition);
                    BTEditorCanvas.Current.Event.Use();
                }
            }
            else if (m_graph.SelectionBox.HasValue)
            {
                if (m_graph.SelectionBox.Value.Contains(position.center))
                {
                    if (!m_isSelected)
                    {
                        m_graph.OnNodeSelect(this);
                    }
                }
                else
                {
                    if (m_isSelected)
                    {
                        m_graph.OnNodeDeselect(this);
                    }
                }
            }
        }