示例#1
0
 public void Save()
 {
     if (AssetDatabase.Contains(graph))
     {
         // EditorUtility.SetDirty(graph);
         graph.IsDirty = true;
         if (NodeEditorPreferences.GetSettings().autoSave)
         {
             AssetDatabase.SaveAssets();
         }
     }
     else
     {
         SaveAs();
     }
 }
示例#2
0
        /// <summary> Draw a connection as we are dragging it </summary>
        public void DrawDraggedConnection()
        {
            if (IsDraggingPort)
            {
                Color col = NodeEditorPreferences.GetTypeColor(draggedOutput.ValueType);

                if (!_portConnectionPoints.ContainsKey(draggedOutput))
                {
                    return;
                }
                col.a = 0.6f;
                Vector2 from = _portConnectionPoints[draggedOutput].center;
                Vector2 to   = Vector2.zero;
                for (int i = 0; i < draggedOutputReroutes.Count; i++)
                {
                    to = draggedOutputReroutes[i];
                    DrawConnection(from, to, col);
                    from = to;
                }
                to = draggedOutputTarget != null ? portConnectionPoints[draggedOutputTarget].center : WindowToGridPosition(Event.current.mousePosition);
                DrawConnection(from, to, col);

                Color bgcol = Color.black;
                Color frcol = col;
                bgcol.a = 0.6f;
                frcol.a = 0.6f;

                // Loop through reroute points again and draw the points
                for (int i = 0; i < draggedOutputReroutes.Count; i++)
                {
                    // Draw reroute point at position
                    Rect rect = new Rect(draggedOutputReroutes[i], new Vector2(16, 16));
                    rect.position = new Vector2(rect.position.x - 8, rect.position.y - 8);
                    rect          = GridToWindowRect(rect);

                    NodeEditorGUILayout.DrawPortHandle(rect, bgcol, frcol);
                }
            }
        }
示例#3
0
        public void SaveAs()
        {
            string path = EditorUtility.SaveFilePanelInProject("Save NodeGraph", "NewNodeGraph", "asset", "");

            if (string.IsNullOrEmpty(path))
            {
                return;
            }
            else
            {
                AnimationBaker.StateMachine.XNode.NodeGraph existingGraph = AssetDatabase.LoadAssetAtPath <AnimationBaker.StateMachine.XNode.NodeGraph>(path);
                if (existingGraph != null)
                {
                    AssetDatabase.DeleteAsset(path);
                }
                AssetDatabase.CreateAsset(graph, path);
                // EditorUtility.SetDirty(graph);
                graph.IsDirty = true;
                if (NodeEditorPreferences.GetSettings().autoSave)
                {
                    AssetDatabase.SaveAssets();
                }
            }
        }
示例#4
0
        private void DrawNodes()
        {
            Event e = Event.current;

            if (e.type == EventType.Layout)
            {
                selectionCache = new List <UnityEngine.Object>(Selection.objects);
            }

            //Active node is hashed before and after node GUI to detect changes
            int nodeHash = 0;

            System.Reflection.MethodInfo onValidate = null;
            if (Selection.activeObject != null && Selection.activeObject is AnimationBaker.StateMachine.XNode.Node)
            {
                onValidate = Selection.activeObject.GetType().GetMethod("OnValidate");
                if (onValidate != null)
                {
                    nodeHash = Selection.activeObject.GetHashCode();
                }
            }

            BeginZoomed(position, zoom);

            Vector2 mousePos = Event.current.mousePosition;

            if (e.type != EventType.Layout)
            {
                hoveredNode = null;
                hoveredPort = null;
            }

            List <UnityEngine.Object> preSelection = preBoxSelection != null ? new List <UnityEngine.Object>(preBoxSelection) : new List <UnityEngine.Object>();

            // Selection box stuff
            Vector2 boxStartPos = GridToWindowPositionNoClipped(dragBoxStart);
            Vector2 boxSize     = mousePos - boxStartPos;

            if (boxSize.x < 0)
            {
                boxStartPos.x += boxSize.x; boxSize.x = Mathf.Abs(boxSize.x);
            }
            if (boxSize.y < 0)
            {
                boxStartPos.y += boxSize.y; boxSize.y = Mathf.Abs(boxSize.y);
            }
            Rect selectionBox = new Rect(boxStartPos, boxSize);

            //Save guiColor so we can revert it
            Color guiColor = GUI.color;

            if (e.type == EventType.Layout)
            {
                culledNodes = new List <AnimationBaker.StateMachine.XNode.Node>();
            }
            for (int n = 0; n < graph.nodes.Count; n++)
            {
                // Skip null nodes. The user could be in the process of renaming scripts, so removing them at this point is not advisable.
                if (graph.nodes[n] == null)
                {
                    continue;
                }
                if (n >= graph.nodes.Count)
                {
                    return;
                }
                AnimationBaker.StateMachine.XNode.Node node = graph.nodes[n];

                NodeEditor nodeEditor = NodeEditor.GetEditor(node);

                // Culling
                if (e.type == EventType.Layout)
                {
                    // Cull unselected nodes outside view
                    if (!Selection.Contains(node) && ShouldBeCulled(nodeEditor))
                    {
                        culledNodes.Add(node);
                        continue;
                    }
                }
                else if (culledNodes.Contains(node))
                {
                    continue;
                }

                if (e.type == EventType.Repaint)
                {
                    _portConnectionPoints = _portConnectionPoints.Where(x => x.Key.node != node).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
                }

                NodeEditor.portPositions = new Dictionary <AnimationBaker.StateMachine.XNode.NodePort, Vector2>();

                //Get node position
                Vector2 nodePos = GridToWindowPositionNoClipped(node.position);

                GUILayout.BeginArea(new Rect(nodePos, new Vector2(nodeEditor.GetWidth(), 4000)));

                bool selected = selectionCache.Contains(graph.nodes[n]);

                if (selected)
                {
                    GUIStyle style          = new GUIStyle(NodeEditorResources.styles.nodeBody);
                    GUIStyle highlightStyle = new GUIStyle(NodeEditorResources.styles.nodeHighlight);
                    highlightStyle.padding = style.padding;
                    style.padding          = new RectOffset();
                    GUI.color = nodeEditor.GetTint();
                    GUILayout.BeginVertical(new GUIStyle(style));
                    GUI.color = NodeEditorPreferences.GetSettings().highlightColor;
                    GUILayout.BeginVertical(new GUIStyle(highlightStyle));
                }
                else
                {
                    GUIStyle style = NodeEditorResources.styles.nodeBody;
                    GUI.color = nodeEditor.GetTint();
                    GUILayout.BeginVertical(new GUIStyle(style));
                }

                GUI.color = guiColor;
                EditorGUI.BeginChangeCheck();

                //Draw node contents
                nodeEditor.OnNodeGUI();

                //If user changed a value, notify other scripts through onUpdateNode
                if (EditorGUI.EndChangeCheck())
                {
                    if (NodeEditor.onUpdateNode != null)
                    {
                        NodeEditor.onUpdateNode(node);
                    }
                    // EditorUtility.SetDirty(node);
                    node.IsDirty = true;
                    nodeEditor.serializedObject.ApplyModifiedProperties();
                }

                GUILayout.EndVertical();

                //Cache data about the node for next frame
                if (e.type == EventType.Repaint)
                {
                    Vector2 size = GUILayoutUtility.GetLastRect().size;
                    if (nodeSizes.ContainsKey(node))
                    {
                        nodeSizes[node] = size;
                    }
                    else
                    {
                        nodeSizes.Add(node, size);
                    }

                    foreach (var kvp in NodeEditor.portPositions)
                    {
                        Vector2 portHandlePos = kvp.Value;
                        portHandlePos += node.position;
                        Rect rect = new Rect(portHandlePos.x - 8, portHandlePos.y - 8, 16, 16);
                        if (portConnectionPoints.ContainsKey(kvp.Key))
                        {
                            portConnectionPoints[kvp.Key] = rect;
                        }
                        else
                        {
                            portConnectionPoints.Add(kvp.Key, rect);
                        }
                    }
                }

                if (selected)
                {
                    GUILayout.EndVertical();
                }

                if (e.type != EventType.Layout)
                {
                    //Check if we are hovering this node
                    Vector2 nodeSize   = GUILayoutUtility.GetLastRect().size;
                    Rect    windowRect = new Rect(nodePos, nodeSize);
                    if (windowRect.Contains(mousePos))
                    {
                        hoveredNode = node;
                    }

                    //If dragging a selection box, add nodes inside to selection
                    if (currentActivity == NodeActivity.DragGrid)
                    {
                        if (windowRect.Overlaps(selectionBox))
                        {
                            preSelection.Add(node);
                        }
                    }

                    //Check if we are hovering any of this nodes ports
                    //Check input ports
                    foreach (AnimationBaker.StateMachine.XNode.NodePort input in node.Inputs)
                    {
                        //Check if port rect is available
                        if (!portConnectionPoints.ContainsKey(input))
                        {
                            continue;
                        }
                        Rect r = GridToWindowRectNoClipped(portConnectionPoints[input]);
                        if (r.Contains(mousePos))
                        {
                            hoveredPort = input;
                        }
                    }
                    //Check all output ports
                    foreach (AnimationBaker.StateMachine.XNode.NodePort output in node.Outputs)
                    {
                        //Check if port rect is available
                        if (!portConnectionPoints.ContainsKey(output))
                        {
                            continue;
                        }
                        Rect r = GridToWindowRectNoClipped(portConnectionPoints[output]);
                        if (r.Contains(mousePos))
                        {
                            hoveredPort = output;
                        }
                    }
                }

                GUILayout.EndArea();
            }

            if (e.type != EventType.Layout && currentActivity == NodeActivity.DragGrid)
            {
                Selection.objects = preSelection.ToArray();
            }
            EndZoomed(position, zoom);

            //If a change in hash is detected in the selected node, call OnValidate method.
            //This is done through reflection because OnValidate is only relevant in editor,
            //and thus, the code should not be included in build.
            if (nodeHash != 0)
            {
                if (onValidate != null && nodeHash != Selection.activeObject.GetHashCode())
                {
                    onValidate.Invoke(Selection.activeObject, null);
                }
            }
        }
示例#5
0
        /// <summary> Draws all connections </summary>
        public void DrawConnections()
        {
            Vector2 mousePos = Event.current.mousePosition;
            List <RerouteReference> selection = preBoxSelectionReroute != null ? new List <RerouteReference>(preBoxSelectionReroute) : new List <RerouteReference>();

            hoveredReroute = new RerouteReference();

            Color col = GUI.color;

            foreach (AnimationBaker.StateMachine.XNode.Node node in graph.nodes)
            {
                //If a null node is found, return. This can happen if the nodes associated script is deleted. It is currently not possible in Unity to delete a null asset.
                if (node == null)
                {
                    continue;
                }

                // Draw full connections and output > reroute
                foreach (AnimationBaker.StateMachine.XNode.NodePort output in node.Outputs)
                {
                    //Needs cleanup. Null checks are ugly
                    if (!portConnectionPoints.ContainsKey(output))
                    {
                        continue;
                    }

                    Color connectionColor = Color.red;

                    for (int k = 0; k < output.ConnectionCount; k++)
                    {
                        AnimationBaker.StateMachine.XNode.NodePort input = output.GetConnectionPort(k);

                        var connection = output.Connections[k];
                        if (graph.isPlaying)
                        {
                            if (!connection.Cleared)
                            {
                                connectionColor = Color.grey;
                            }
                            else
                            {
                                connectionColor = Color.green;
                            }
                        }

                        // var connection = output.GetConnection(input);

                        // if (connection != null)
                        // {
                        //     // Debug.Log(connection.rules.Count);
                        // }

                        // Error handling
                        if (input == null)
                        {
                            continue;                //If a script has been updated and the port doesn't exist, it is removed and null is returned. If this happens, return.
                        }
                        if (!input.IsConnectedToPort(output))
                        {
                            input.Connect(output);
                        }
                        if (!_portConnectionPoints.ContainsKey(input))
                        {
                            continue;
                        }

                        Vector2        from          = _portConnectionPoints[output].center;
                        Vector2        to            = Vector2.zero;
                        List <Vector2> reroutePoints = output.GetReroutePoints(k);
                        // Loop through reroute points and draw the path
                        for (int i = 0; i < reroutePoints.Count; i++)
                        {
                            to = reroutePoints[i];
                            DrawConnection(from, to, connectionColor);
                            from = to;
                        }
                        to = _portConnectionPoints[input].center;
                        DrawConnection(from, to, connectionColor);

                        // Loop through reroute points again and draw the points
                        for (int i = 0; i < reroutePoints.Count; i++)
                        {
                            RerouteReference rerouteRef = new RerouteReference(output, k, i);
                            // Draw reroute point at position
                            Rect rect = new Rect(reroutePoints[i], new Vector2(12, 12));
                            rect.position = new Vector2(rect.position.x - 6, rect.position.y - 6);
                            rect          = GridToWindowRect(rect);

                            // Draw selected reroute points with an outline
                            if (selectedReroutes.Contains(rerouteRef))
                            {
                                GUI.color = NodeEditorPreferences.GetSettings().highlightColor;
                                GUI.DrawTexture(rect, NodeEditorResources.dotOuter);
                            }

                            GUI.color = connectionColor;
                            GUI.DrawTexture(rect, NodeEditorResources.dot);
                            if (rect.Overlaps(selectionBox))
                            {
                                selection.Add(rerouteRef);
                            }
                            if (rect.Contains(mousePos))
                            {
                                hoveredReroute = rerouteRef;
                            }
                        }
                    }
                }
            }
            GUI.color = col;
            if (Event.current.type != EventType.Layout && currentActivity == NodeActivity.DragGrid)
            {
                selectedReroutes = selection;
            }
        }
示例#6
0
        /// <summary> Draw a bezier from startpoint to endpoint, both in grid coordinates </summary>
        public void DrawConnection(Vector2 startPoint, Vector2 endPoint, Color col)
        {
            startPoint = GridToWindowPosition(startPoint);
            endPoint   = GridToWindowPosition(endPoint);

            switch (NodeEditorPreferences.GetSettings().noodleType)
            {
            case NodeEditorPreferences.NoodleType.Curve:
                Vector2 startTangent = startPoint;
                if (startPoint.x < endPoint.x)
                {
                    startTangent.x = Mathf.LerpUnclamped(startPoint.x, endPoint.x, 0.7f);
                }
                else
                {
                    startTangent.x = Mathf.LerpUnclamped(startPoint.x, endPoint.x, -0.7f);
                }

                Vector2 endTangent = endPoint;
                if (startPoint.x > endPoint.x)
                {
                    endTangent.x = Mathf.LerpUnclamped(endPoint.x, startPoint.x, -0.7f);
                }
                else
                {
                    endTangent.x = Mathf.LerpUnclamped(endPoint.x, startPoint.x, 0.7f);
                }
                Handles.DrawBezier(startPoint, endPoint, startTangent, endTangent, col, null, 4);
                break;

            case NodeEditorPreferences.NoodleType.Line:
                Handles.color = col;
                Handles.DrawAAPolyLine(5, startPoint, endPoint);
                break;

            case NodeEditorPreferences.NoodleType.Angled:
                Handles.color = col;
                if (startPoint.y <= endPoint.y - (50 / zoom))
                {
                    float   midpoint = (startPoint.y + endPoint.y) * 0.5f;
                    Vector2 start_1  = startPoint;
                    Vector2 end_1    = endPoint;
                    start_1.y = midpoint;
                    end_1.y   = midpoint;
                    Handles.DrawAAPolyLine(5, startPoint, start_1);
                    Handles.DrawAAPolyLine(5, start_1, end_1);
                    Handles.DrawAAPolyLine(5, end_1, endPoint);
                }
                else
                {
                    float   midpoint = (startPoint.y + endPoint.y) * 0.5f;
                    Vector2 start_1  = startPoint;
                    Vector2 end_1    = endPoint;
                    start_1.x += 25 / zoom;
                    end_1.x   -= 25 / zoom;
                    Vector2 start_2 = start_1;
                    Vector2 end_2   = end_1;
                    start_2.y = midpoint;
                    end_2.y   = midpoint;
                    Handles.DrawAAPolyLine(5, startPoint, start_1);
                    Handles.DrawAAPolyLine(5, start_1, start_2);
                    Handles.DrawAAPolyLine(5, start_2, end_2);
                    Handles.DrawAAPolyLine(5, end_2, end_1);
                    Handles.DrawAAPolyLine(5, end_1, endPoint);
                }
                break;
            }
        }
示例#7
0
        public void Controls()
        {
            wantsMouseMove = true;
            Event e = Event.current;

            switch (e.type)
            {
            case EventType.MouseMove:
                break;

            case EventType.ScrollWheel:
                if (e.delta.y > 0)
                {
                    zoom += 0.1f * zoom;
                }
                else
                {
                    zoom -= 0.1f * zoom;
                }
                break;

            case EventType.MouseDrag:
                if (e.button == 0)
                {
                    if (IsDraggingPort)
                    {
                        if (IsHoveringPort && hoveredPort.IsInput)
                        {
                            if (!draggedOutput.IsConnectedToPort(hoveredPort))
                            {
                                draggedOutputTarget = hoveredPort;
                            }
                        }
                        else
                        {
                            draggedOutputTarget = null;
                        }
                        Repaint();
                    }
                    else if (currentActivity == NodeActivity.HoldNode)
                    {
                        RecalculateDragOffsets(e);
                        currentActivity = NodeActivity.DragNode;
                        Repaint();
                    }
                    if (currentActivity == NodeActivity.DragNode)
                    {
                        // Holding ctrl inverts grid snap
                        bool gridSnap = NodeEditorPreferences.GetSettings().gridSnap;
                        if (e.control)
                        {
                            gridSnap = !gridSnap;
                        }

                        Vector2 mousePos = WindowToGridPosition(e.mousePosition);
                        // Move selected nodes with offset
                        for (int i = 0; i < Selection.objects.Length; i++)
                        {
                            if (Selection.objects[i] is AnimationBaker.StateMachine.XNode.Node)
                            {
                                AnimationBaker.StateMachine.XNode.Node node = Selection.objects[i] as AnimationBaker.StateMachine.XNode.Node;
                                node.position = mousePos + dragOffset[i];
                                if (gridSnap)
                                {
                                    node.position.x = (Mathf.Round((node.position.x + 8) / 16) * 16) - 8;
                                    node.position.y = (Mathf.Round((node.position.y + 8) / 16) * 16) - 8;
                                }
                            }
                        }
                        // Move selected reroutes with offset
                        for (int i = 0; i < selectedReroutes.Count; i++)
                        {
                            Vector2 pos = mousePos + dragOffset[Selection.objects.Length + i];
                            pos.x -= 8;
                            pos.y -= 8;
                            if (gridSnap)
                            {
                                pos.x = (Mathf.Round((pos.x + 8) / 16) * 16);
                                pos.y = (Mathf.Round((pos.y + 8) / 16) * 16);
                            }
                            selectedReroutes[i].SetPoint(pos);
                        }
                        Repaint();
                    }
                    else if (currentActivity == NodeActivity.HoldGrid)
                    {
                        currentActivity        = NodeActivity.DragGrid;
                        preBoxSelection        = Selection.objects;
                        preBoxSelectionReroute = selectedReroutes.ToArray();
                        dragBoxStart           = WindowToGridPosition(e.mousePosition);
                        Repaint();
                    }
                    else if (currentActivity == NodeActivity.DragGrid)
                    {
                        Vector2 boxStartPos = GridToWindowPosition(dragBoxStart);
                        Vector2 boxSize     = e.mousePosition - boxStartPos;
                        if (boxSize.x < 0)
                        {
                            boxStartPos.x += boxSize.x; boxSize.x = Mathf.Abs(boxSize.x);
                        }
                        if (boxSize.y < 0)
                        {
                            boxStartPos.y += boxSize.y; boxSize.y = Mathf.Abs(boxSize.y);
                        }
                        selectionBox = new Rect(boxStartPos, boxSize);
                        Repaint();
                    }
                }
                else if (e.button == 1 || e.button == 2)
                {
                    Vector2 tempOffset = panOffset;
                    tempOffset += e.delta * zoom;
                    // Round value to increase crispyness of UI text
                    tempOffset.x       = Mathf.Round(tempOffset.x);
                    tempOffset.y       = Mathf.Round(tempOffset.y);
                    panOffset          = tempOffset;
                    isPanning          = true;
                    graph.dragPosition = panOffset;
                }
                break;

            case EventType.MouseDown:
                Repaint();
                if (e.button == 0)
                {
                    draggedOutputReroutes.Clear();

                    if (IsHoveringPort)
                    {
                        if (hoveredPort.IsOutput)
                        {
                            draggedOutput = hoveredPort;
                        }
                        else
                        {
                            hoveredPort.VerifyConnections();
                            if (hoveredPort.IsConnected)
                            {
                                AnimationBaker.StateMachine.XNode.Node     node   = hoveredPort.node;
                                AnimationBaker.StateMachine.XNode.NodePort output = hoveredPort.Connection;
                                int outputConnectionIndex = output.GetConnectionPortIndex(hoveredPort);
                                draggedOutputReroutes = output.GetReroutePoints(outputConnectionIndex);
                                hoveredPort.DisconnectPort(output);
                                draggedOutput       = output;
                                draggedOutputTarget = hoveredPort;
                                if (NodeEditor.onUpdateNode != null)
                                {
                                    NodeEditor.onUpdateNode(node);
                                }
                            }
                        }
                    }
                    else if (IsHoveringNode && IsHoveringTitle(hoveredNode))
                    {
                        // If mousedown on node header, select or deselect
                        if (!Selection.Contains(hoveredNode))
                        {
                            SelectNode(hoveredNode, e.control || e.shift);
                            if (!e.control && !e.shift)
                            {
                                selectedReroutes.Clear();
                            }
                        }
                        else if (e.control || e.shift)
                        {
                            DeselectNode(hoveredNode);
                        }
                        e.Use();
                        currentActivity = NodeActivity.HoldNode;
                    }
                    else if (IsHoveringReroute)
                    {
                        // If reroute isn't selected
                        if (!selectedReroutes.Contains(hoveredReroute))
                        {
                            // Add it
                            if (e.control || e.shift)
                            {
                                selectedReroutes.Add(hoveredReroute);
                            }
                            // Select it
                            else
                            {
                                selectedReroutes = new List <RerouteReference>()
                                {
                                    hoveredReroute
                                };
                                Selection.activeObject = null;
                            }
                        }
                        // Deselect
                        else if (e.control || e.shift)
                        {
                            selectedReroutes.Remove(hoveredReroute);
                        }
                        e.Use();
                        currentActivity = NodeActivity.HoldNode;
                    }
                    // If mousedown on grid background, deselect all
                    else if (!IsHoveringNode)
                    {
                        currentActivity = NodeActivity.HoldGrid;
                        if (!e.control && !e.shift)
                        {
                            selectedReroutes.Clear();
                            Selection.activeObject = null;
                            if (Selection.activeObject != graph)
                            {
                                Selection.activeObject = graph;
                            }
                        }
                    }
                }
                break;

            case EventType.MouseUp:
                if (e.button == 0)
                {
                    //Port drag release
                    if (IsDraggingPort)
                    {
                        //If connection is valid, save it
                        if (draggedOutputTarget != null)
                        {
                            AnimationBaker.StateMachine.XNode.Node node = draggedOutputTarget.node;
                            if (graph.nodes.Count != 0)
                            {
                                draggedOutput.Connect(draggedOutputTarget);
                            }

                            // ConnectionIndex can be -1 if the connection is removed instantly after creation
                            int connectionIndex = draggedOutput.GetConnectionPortIndex(draggedOutputTarget);
                            if (connectionIndex != -1)
                            {
                                draggedOutput.GetReroutePoints(connectionIndex).AddRange(draggedOutputReroutes);
                                if (NodeEditor.onUpdateNode != null)
                                {
                                    NodeEditor.onUpdateNode(node);
                                }
                                // EditorUtility.SetDirty(graph);
                                graph.IsDirty = true;
                            }
                        }
                        //Release dragged connection
                        draggedOutput       = null;
                        draggedOutputTarget = null;
                        // EditorUtility.SetDirty(graph);
                        graph.IsDirty = true;
                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }
                    else if (currentActivity == NodeActivity.DragNode)
                    {
                        IEnumerable <AnimationBaker.StateMachine.XNode.Node> nodes = Selection.objects.Where(x => x is AnimationBaker.StateMachine.XNode.Node).Select(x => x as AnimationBaker.StateMachine.XNode.Node);
                        foreach (AnimationBaker.StateMachine.XNode.Node node in nodes)
                        {
                            node.IsDirty = true;
                        }
                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }
                    else if (!IsHoveringNode)
                    {
                        // If click outside node, release field focus
                        if (!isPanning)
                        {
                            EditorGUI.FocusTextInControl(null);
                        }
                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }

                    // If click node header, select it.
                    if (currentActivity == NodeActivity.HoldNode && !(e.control || e.shift))
                    {
                        selectedReroutes.Clear();
                        SelectNode(hoveredNode, false);
                    }

                    // If click reroute, select it.
                    if (IsHoveringReroute && !(e.control || e.shift))
                    {
                        selectedReroutes = new List <RerouteReference>()
                        {
                            hoveredReroute
                        };
                        Selection.activeObject = null;
                    }

                    Repaint();
                    currentActivity = NodeActivity.Idle;
                }
                else if (e.button == 1 || e.button == 2)
                {
                    if (!isPanning)
                    {
                        if (IsDraggingPort)
                        {
                            draggedOutputReroutes.Add(WindowToGridPosition(e.mousePosition));
                        }
                        else if (currentActivity == NodeActivity.DragNode && Selection.activeObject == null && selectedReroutes.Count == 1)
                        {
                            selectedReroutes[0].InsertPoint(selectedReroutes[0].GetPoint());
                            selectedReroutes[0] = new RerouteReference(selectedReroutes[0].port, selectedReroutes[0].connectionIndex, selectedReroutes[0].pointIndex + 1);
                        }
                        // else if (IsHoveringReroute)
                        // {
                        //     ShowRerouteContextMenu(hoveredReroute);
                        // }
                        // else if (IsHoveringPort)
                        // {
                        //     ShowPortContextMenu(hoveredPort);
                        // }
                        // else if (IsHoveringNode && IsHoveringTitle(hoveredNode))
                        // {
                        //     if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode, false);
                        //     ShowNodeContextMenu();
                        // }
                        // else if (!IsHoveringNode)
                        // {
                        //     ShowGraphContextMenu();
                        // }
                    }
                    isPanning = false;
                }
                break;

            case EventType.KeyDown:
                if (EditorGUIUtility.editingTextField)
                {
                    break;
                }
                else if (e.keyCode == KeyCode.F)
                {
                    Home();
                }
                if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX)
                {
                    if (e.keyCode == KeyCode.Return)
                    {
                        RenameSelectedNode();
                    }
                }
                else
                {
                    if (e.keyCode == KeyCode.F2)
                    {
                        RenameSelectedNode();
                    }
                }
                break;

            case EventType.ValidateCommand:
                if (e.commandName == "SoftDelete")
                {
                    RemoveSelectedNodes();
                }
                else if (e.commandName == "Duplicate")
                {
                    DublicateSelectedNodes();
                }
                Repaint();
                break;

            case EventType.Ignore:
                // If release mouse outside window
                if (e.rawType == EventType.MouseUp && currentActivity == NodeActivity.DragGrid)
                {
                    Repaint();
                    currentActivity = NodeActivity.Idle;
                }
                break;
            }
        }
 public virtual Color GetTypeColor(Type type)
 {
     return(NodeEditorPreferences.GetTypeColor(type));
 }
 public virtual Texture2D GetSecondaryGridTexture()
 {
     return(NodeEditorPreferences.GetSettings().crossTexture);
 }
 public virtual Texture2D GetGridTexture()
 {
     return(NodeEditorPreferences.GetSettings().gridTexture);
 }