Beispiel #1
0
        private void OnGUI()
        {
            if (firstFrame)
            {
                UpdatePositionToMouse();
                firstFrame = false;
            }
            GUI.SetNextControlName(inputControlName);
            input = EditorGUILayout.TextField(input);
            EditorGUI.FocusTextInControl(inputControlName);
            Event e = Event.current;

            // If input is empty, revert name to default instead
            if (input == null || input.Trim() == "")
            {
                if (GUILayout.Button("Revert to default") || (e.isKey && e.keyCode == KeyCode.Return))
                {
                    target.name = NodeEditorUtilities.NodeDefaultName(target.GetType());
                    NodeEditor.GetEditor((XNode.Node)target, NodeEditorWindow.current).OnRename();
                    AssetDatabase.SetMainObject((target as XNode.Node).graph, AssetDatabase.GetAssetPath(target));
                    AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
                    Close();
                    target.TriggerOnValidate();
                }
            }
            // Rename asset to input text
            else
            {
                if (GUILayout.Button("Apply") || (e.isKey && e.keyCode == KeyCode.Return))
                {
                    target.name = input;
                    NodeEditor.GetEditor((XNode.Node)target, NodeEditorWindow.current).OnRename();
                    AssetDatabase.SetMainObject((target as XNode.Node).graph, AssetDatabase.GetAssetPath(target));
                    AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
                    Close();
                    target.TriggerOnValidate();
                }
            }

            if (e.isKey && e.keyCode == KeyCode.Escape)
            {
                Close();
            }
        }
Beispiel #2
0
        /// <summary> Make a simple port field. </summary>
        public static void PortField(Vector2 position, XNode.NodePort port)
        {
            if (port == null)
            {
                return;
            }

            Rect rect = new Rect(position, new Vector2(16, 16));

            NodeEditor editor          = NodeEditor.GetEditor(port.node, NodeEditorWindow.current);
            Color      backgroundColor = editor.GetTint();
            Color      col             = NodeEditorWindow.current.graphEditor.GetPortColor(port);

            DrawPortHandle(rect, backgroundColor, col);

            // Register the handle position
            Vector2 portPos = rect.center;

            NodeEditor.portPositions[port] = portPos;
        }
Beispiel #3
0
        /// <summary> Show right-click context menu for selected nodes </summary>
        public void ShowNodeContextMenu()
        {
            GenericMenu contextMenu = new GenericMenu();

            // If only one node is selected
            if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node)
            {
                XNode.Node node = Selection.activeObject as XNode.Node;
                contextMenu.AddItem(new GUIContent("Move To Top"), false, () => MoveNodeToTop(node));
                contextMenu.AddItem(new GUIContent("Rename"), false, NodeEditor.GetEditor(node).InitiateRename);
            }

            contextMenu.AddItem(new GUIContent("Duplicate"), false, DublicateSelectedNodes);
            contextMenu.AddItem(new GUIContent("Remove"), false, RemoveSelectedNodes);

            // If only one node is selected
            if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node)
            {
                XNode.Node node = Selection.activeObject as XNode.Node;
                AddCustomContextMenuItems(contextMenu, node);
            }

            contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
        }
        public void Controls()
        {
            wantsMouseMove = true;
            Event e = Event.current;

            switch (e.type)
            {
            case EventType.DragUpdated:
            case EventType.DragPerform:
                DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
                if (e.type == EventType.DragPerform)
                {
                    DragAndDrop.AcceptDrag();
                    graphEditor.OnDropObjects(DragAndDrop.objectReferences);
                }
                break;

            case EventType.MouseMove:
                //Keyboard commands will not get correct mouse position from Event
                lastMousePosition = e.mousePosition;
                break;

            case EventType.ScrollWheel:
                float oldZoom = zoom;
                if (e.delta.y > 0)
                {
                    zoom += 0.1f * zoom;
                }
                else
                {
                    zoom -= 0.1f * zoom;
                }
                if (NodeEditorPreferences.GetSettings().zoomToMouse)
                {
                    panOffset += (1 - oldZoom / zoom) * (WindowToGridPosition(e.mousePosition) + panOffset);
                }
                break;

            case EventType.MouseDrag:
                if (e.button == 0)
                {
                    if (IsDraggingPort)
                    {
                        if (IsHoveringPort && hoveredPort.IsInput && draggedOutput.CanConnectTo(hoveredPort))
                        {
                            if (!draggedOutput.IsConnectedTo(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 XNode.Node)
                            {
                                XNode.Node node    = Selection.objects[i] as XNode.Node;
                                Vector2    initial = node.position;
                                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;
                                }

                                // Offset portConnectionPoints instantly if a node is dragged so they aren't delayed by a frame.
                                Vector2 offset = node.position - initial;
                                if (offset.sqrMagnitude > 0)
                                {
                                    foreach (XNode.NodePort output in node.Outputs)
                                    {
                                        Rect rect;
                                        if (portConnectionPoints.TryGetValue(output, out rect))
                                        {
                                            rect.position += offset;
                                            portConnectionPoints[output] = rect;
                                        }
                                    }

                                    foreach (XNode.NodePort input in node.Inputs)
                                    {
                                        Rect rect;
                                        if (portConnectionPoints.TryGetValue(input, out rect))
                                        {
                                            rect.position += offset;
                                            portConnectionPoints[input] = rect;
                                        }
                                    }
                                }
                            }
                        }
                        // Move selected reroutes with offset
                        for (int i = 0; i < selectedReroutes.Count; i++)
                        {
                            Vector2 pos = mousePos + dragOffset[Selection.objects.Length + i];
                            if (gridSnap)
                            {
                                pos.x = (Mathf.Round(pos.x / 16) * 16);
                                pos.y = (Mathf.Round(pos.y / 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)
                {
                    panOffset += e.delta * zoom;
                    isPanning  = true;
                }
                break;

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

                    if (IsHoveringPort)
                    {
                        if (hoveredPort.IsOutput)
                        {
                            draggedOutput     = hoveredPort;
                            autoConnectOutput = hoveredPort;
                        }
                        else
                        {
                            hoveredPort.VerifyConnections();
                            autoConnectOutput = null;
                            if (hoveredPort.IsConnected)
                            {
                                XNode.Node     node   = hoveredPort.node;
                                XNode.NodePort output = hoveredPort.Connection;
                                int            outputConnectionIndex = output.GetConnectionIndex(hoveredPort);
                                draggedOutputReroutes = output.GetReroutePoints(outputConnectionIndex);
                                hoveredPort.Disconnect(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);
                        }

                        // Cache double click state, but only act on it in MouseUp - Except ClickCount only works in mouseDown.
                        isDoubleClick = (e.clickCount == 2);

                        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;
                        }
                    }
                }
                break;

            case EventType.MouseUp:
                if (e.button == 0)
                {
                    //Port drag release
                    if (IsDraggingPort)
                    {
                        //If connection is valid, save it
                        if (draggedOutputTarget != null)
                        {
                            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.GetConnectionIndex(draggedOutputTarget);
                            if (connectionIndex != -1)
                            {
                                draggedOutput.GetReroutePoints(connectionIndex).AddRange(draggedOutputReroutes);
                                if (NodeEditor.onUpdateNode != null)
                                {
                                    NodeEditor.onUpdateNode(node);
                                }
                                EditorUtility.SetDirty(graph);
                            }
                        }
                        // Open context menu for auto-connection
                        else if (NodeEditorPreferences.GetSettings().dragToCreate&& autoConnectOutput != null)
                        {
                            GenericMenu menu = new GenericMenu();
                            graphEditor.AddContextMenuItems(menu);
                            menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
                        }
                        //Release dragged connection
                        draggedOutput       = null;
                        draggedOutputTarget = null;
                        EditorUtility.SetDirty(graph);
                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }
                    else if (currentActivity == NodeActivity.DragNode)
                    {
                        IEnumerable <XNode.Node> nodes = Selection.objects.Where(x => x is XNode.Node).Select(x => x as XNode.Node);
                        foreach (XNode.Node node in nodes)
                        {
                            EditorUtility.SetDirty(node);
                        }
                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }
                    else if (!IsHoveringNode)
                    {
                        // If click outside node, release field focus
                        if (!isPanning)
                        {
                            EditorGUI.FocusTextInControl(null);
                            EditorGUIUtility.editingTextField = false;
                        }
                        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);

                        // Double click to center node
                        if (isDoubleClick)
                        {
                            Vector2 nodeDimension = nodeSizes.ContainsKey(hoveredNode) ? nodeSizes[hoveredNode] / 2 : Vector2.zero;
                            panOffset = -hoveredNode.position - nodeDimension;
                        }
                    }

                    // 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);
                            }
                            autoConnectOutput = null;
                            GenericMenu menu = new GenericMenu();
                            NodeEditor.GetEditor(hoveredNode, this).AddContextMenuItems(menu);
                            menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
                            e.Use();     // Fixes copy/paste context menu appearing in Unity 5.6.6f2 - doesn't occur in 2018.3.2f1 Probably needs to be used in other places.
                        }
                        else if (!IsHoveringNode)
                        {
                            autoConnectOutput = null;
                            GenericMenu menu = new GenericMenu();
                            graphEditor.AddContextMenuItems(menu);
                            menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
                        }
                    }
                    isPanning = false;
                }
                // Reset DoubleClick
                isDoubleClick = false;
                break;

            case EventType.KeyDown:
                if (EditorGUIUtility.editingTextField)
                {
                    break;
                }
                else if (e.keyCode == KeyCode.F)
                {
                    Home();
                }
                if (NodeEditorUtilities.IsMac())
                {
                    if (e.keyCode == KeyCode.Return)
                    {
                        RenameSelectedNode();
                    }
                }
                else
                {
                    if (e.keyCode == KeyCode.F2)
                    {
                        RenameSelectedNode();
                    }
                }
                if (e.keyCode == KeyCode.A)
                {
                    if (Selection.objects.Any(x => graph.nodes.Contains(x as XNode.Node)))
                    {
                        foreach (XNode.Node node in graph.nodes)
                        {
                            DeselectNode(node);
                        }
                    }
                    else
                    {
                        foreach (XNode.Node node in graph.nodes)
                        {
                            SelectNode(node, true);
                        }
                    }
                    Repaint();
                }
                break;

            case EventType.ValidateCommand:
            case EventType.ExecuteCommand:
                if (e.commandName == "SoftDelete")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        RemoveSelectedNodes();
                    }
                    e.Use();
                }
                else if (NodeEditorUtilities.IsMac() && e.commandName == "Delete")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        RemoveSelectedNodes();
                    }
                    e.Use();
                }
                else if (e.commandName == "Duplicate")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        DuplicateSelectedNodes();
                    }
                    e.Use();
                }
                else if (e.commandName == "Copy")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        CopySelectedNodes();
                    }
                    e.Use();
                }
                else if (e.commandName == "Paste")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        PasteNodes(WindowToGridPosition(lastMousePosition));
                    }
                    e.Use();
                }
                Repaint();
                break;

            case EventType.Ignore:
                // If release mouse outside window
                if (e.rawType == EventType.MouseUp && currentActivity == NodeActivity.DragGrid)
                {
                    Repaint();
                    currentActivity = NodeActivity.Idle;
                }
                break;
            }
        }
Beispiel #5
0
        private void DrawNodes()
        {
            Event e = Event.current;

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

            //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 Siccity.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>();

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

            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;
                }
                Siccity.XNode.Node node = graph.nodes[n];

                NodeEditor nodeEditor = NodeEditor.GetEditor(node);
                NodeEditor.portPositions = new Dictionary <Siccity.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();

                //Apply
                nodeEditor.serializedObject.ApplyModifiedProperties();

                //If user changed a value, notify other scripts through onUpdateNode
                if (EditorGUI.EndChangeCheck())
                {
                    if (NodeEditor.onUpdateNode != null)
                    {
                        NodeEditor.onUpdateNode(node);
                    }
                }

                if (e.type == EventType.Repaint)
                {
                    nodeWidths.Add(node, nodeEditor.GetWidth());

                    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);
                        portConnectionPoints.Add(kvp.Key, rect);
                    }
                }

                GUILayout.EndVertical();
                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)
                    {
                        Vector2 startPos = GridToWindowPositionNoClipped(dragBoxStart);
                        Vector2 size     = mousePos - startPos;
                        if (size.x < 0)
                        {
                            startPos.x += size.x; size.x = Mathf.Abs(size.x);
                        }
                        if (size.y < 0)
                        {
                            startPos.y += size.y; size.y = Mathf.Abs(size.y);
                        }
                        Rect r = new Rect(startPos, size);
                        if (windowRect.Overlaps(r))
                        {
                            preSelection.Add(node);
                        }
                    }

                    //Check if we are hovering any of this nodes ports
                    //Check input ports
                    foreach (Siccity.XNode.NodePort input in node.Inputs)
                    {
                        //Check if port rect is available
                        if (!portConnectionPoints.ContainsKey(input))
                        {
                            continue;
                        }
                        Rect r = GridToWindowRect(portConnectionPoints[input]);
                        if (r.Contains(mousePos))
                        {
                            hoveredPort = input;
                        }
                    }
                    //Check all output ports
                    foreach (Siccity.XNode.NodePort output in node.Outputs)
                    {
                        //Check if port rect is available
                        if (!portConnectionPoints.ContainsKey(output))
                        {
                            continue;
                        }
                        Rect r = GridToWindowRect(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);
                }
            }
        }
Beispiel #6
0
        private void DrawNodes()
        {
            Event e = Event.current;

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

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

            BeginZoomed(position, zoom, topPadding);

            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;

            List <XNode.NodePort> removeEntries = new List <XNode.NodePort>();

            if (e.type == EventType.Layout)
            {
                culledNodes = new List <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;
                }
                XNode.Node node = graph.nodes[n];

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

                if (e.type == EventType.Repaint)
                {
                    removeEntries.Clear();
                    foreach (var kvp in _portConnectionPoints)
                    {
                        if (kvp.Key.node == node)
                        {
                            removeEntries.Add(kvp.Key);
                        }
                    }
                    foreach (var k in removeEntries)
                    {
                        _portConnectionPoints.Remove(k);
                    }
                }

                NodeEditor nodeEditor = NodeEditor.GetEditor(node, this);

                NodeEditor.portPositions.Clear();

                // Set default label width. This is potentially overridden in OnBodyGUI
                EditorGUIUtility.labelWidth = 84;

                //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(nodeEditor.GetBodyStyle());
                    GUIStyle highlightStyle = new GUIStyle(nodeEditor.GetBodyHighlightStyle());
                    highlightStyle.padding = style.padding;
                    style.padding          = new RectOffset();
                    GUI.color = nodeEditor.GetTint();
                    GUILayout.BeginVertical(style);
                    GUI.color = NodeEditorPreferences.GetSettings().highlightColor;
                    GUILayout.BeginVertical(new GUIStyle(highlightStyle));
                }
                else
                {
                    GUIStyle style = new GUIStyle(nodeEditor.GetBodyStyle());
                    GUI.color = nodeEditor.GetTint();
                    GUILayout.BeginVertical(style);
                }

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

                //Draw node contents
                nodeEditor.OnHeaderGUI();

                //if (zoom < 2)
                //{
                nodeEditor.OnBodyGUI();

                //}



                //If user changed a value, notify other scripts through onUpdateNode
                if (EditorGUI.EndChangeCheck())
                {
                    if (NodeEditor.onUpdateNode != null)
                    {
                        NodeEditor.onUpdateNode(node);
                    }
                    EditorUtility.SetDirty(node);
                    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);
                        portConnectionPoints[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 (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 (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, topPadding);

            //If a change in 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 (onValidate != null && EditorGUI.EndChangeCheck())
            {
                onValidate.Invoke(Selection.activeObject, null);
            }
        }
        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.IsConnectedTo(hoveredPort))
                            {
                                draggedOutputTarget = hoveredPort;
                            }
                        }
                        else
                        {
                            draggedOutputTarget = null;
                        }
                        Repaint();
                    }
                    else if (currentActivity == NodeActivity.HoldHeader || currentActivity == NodeActivity.DragHeader)
                    {
                        for (int i = 0; i < Selection.objects.Length; i++)
                        {
                            if (Selection.objects[i] is XNode.Node)
                            {
                                XNode.Node node = Selection.objects[i] as XNode.Node;
                                node.position = WindowToGridPosition(e.mousePosition) + dragOffset[i];
                                bool gridSnap = NodeEditorPreferences.GetSettings().gridSnap;
                                if (e.control)
                                {
                                    gridSnap = !gridSnap;
                                }
                                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;
                                }
                            }
                        }
                        currentActivity = NodeActivity.DragHeader;
                        Repaint();
                    }
                    else if (currentActivity == NodeActivity.HoldGrid)
                    {
                        currentActivity = NodeActivity.DragGrid;
                        preBoxSelection = Selection.objects;
                        dragBoxStart    = WindowToGridPosition(e.mousePosition);
                        Repaint();
                    }
                    else if (currentActivity == NodeActivity.DragGrid)
                    {
                        foreach (XNode.Node node in graph.nodes)
                        {
                        }
                        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;
                }
                break;

            case EventType.MouseDown:
                Repaint();
                if (e.button == 0)
                {
                    if (IsHoveringPort)
                    {
                        if (hoveredPort.IsOutput)
                        {
                            draggedOutput = hoveredPort;
                        }
                        else
                        {
                            hoveredPort.VerifyConnections();
                            if (hoveredPort.IsConnected)
                            {
                                XNode.Node     node   = hoveredPort.node;
                                XNode.NodePort output = hoveredPort.Connection;
                                hoveredPort.Disconnect(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);
                        }
                        else if (e.control || e.shift)
                        {
                            DeselectNode(hoveredNode);
                        }
                        e.Use();
                        currentActivity = NodeActivity.HoldHeader;
                        dragOffset      = new Vector2[Selection.objects.Length];
                        for (int i = 0; i < dragOffset.Length; i++)
                        {
                            if (Selection.objects[i] is XNode.Node)
                            {
                                XNode.Node node = Selection.objects[i] as XNode.Node;
                                dragOffset[i] = node.position - WindowToGridPosition(e.mousePosition);
                            }
                        }
                    }
                    // If mousedown on grid background, deselect all
                    else if (!IsHoveringNode)
                    {
                        currentActivity = NodeActivity.HoldGrid;
                        if (!e.control && !e.shift)
                        {
                            Selection.activeObject = null;
                        }
                    }
                }
                break;

            case EventType.MouseUp:
                if (e.button == 0)
                {
                    //Port drag release
                    if (IsDraggingPort)
                    {
                        //If connection is valid, save it
                        if (draggedOutputTarget != null)
                        {
                            XNode.Node node = draggedOutputTarget.node;
                            if (graph.nodes.Count != 0)
                            {
                                draggedOutput.Connect(draggedOutputTarget);
                            }
                            if (NodeEditor.onUpdateNode != null)
                            {
                                NodeEditor.onUpdateNode(node);
                            }
                            EditorUtility.SetDirty(graph);
                        }
                        //Release dragged connection
                        draggedOutput       = null;
                        draggedOutputTarget = null;
                        EditorUtility.SetDirty(graph);
                        AssetDatabase.SaveAssets();
                    }
                    else if (currentActivity == NodeActivity.DragHeader)
                    {
                        AssetDatabase.SaveAssets();
                    }
                    else if (!IsHoveringNode)
                    {
                        // If click outside node, release field focus
                        if (!isPanning)
                        {
                            // I've got no idea which of these do what, so we'll just reset all of it.
                            GUIUtility.hotControl             = 0;
                            GUIUtility.keyboardControl        = 0;
                            EditorGUIUtility.editingTextField = false;
                            EditorGUIUtility.keyboardControl  = 0;
                            EditorGUIUtility.hotControl       = 0;
                        }
                        AssetDatabase.SaveAssets();
                    }

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

                    Repaint();
                    currentActivity = NodeActivity.Idle;
                }
                else if (e.button == 1)
                {
                    if (!isPanning)
                    {
                        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();
                }
                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;
            }
        }
Beispiel #8
0
        /// <summary> Make a field for a serialized property. Manual node port override. </summary>
        public static void PropertyField(SerializedProperty property, GUIContent label, XNode.NodePort port, bool includeChildren = true, params GUILayoutOption[] options)
        {
            if (property == null)
            {
                throw new NullReferenceException();
            }

            // If property is not a port, display a regular property field
            if (port == null)
            {
                EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
            }
            else
            {
                Rect rect = new Rect();

                List <PropertyAttribute> propertyAttributes = NodeEditorUtilities.GetCachedPropertyAttribs(port.node.GetType(), property.name);

                // If property is an input, display a regular property field and put a port handle on the left side
                if (port.direction == XNode.NodePort.IO.Input)
                {
                    // Get data from [Input] attribute
                    XNode.Node.ShowBackingValue showBacking = XNode.Node.ShowBackingValue.Unconnected;
                    XNode.Node.InputAttribute   inputAttribute;
                    bool dynamicPortList = false;
                    if (NodeEditorUtilities.GetCachedAttrib(port.node.GetType(), property.name, out inputAttribute))
                    {
                        dynamicPortList = inputAttribute.dynamicPortList;
                        showBacking     = inputAttribute.backingValue;
                    }

                    bool usePropertyAttributes = dynamicPortList ||
                                                 showBacking == XNode.Node.ShowBackingValue.Never ||
                                                 (showBacking == XNode.Node.ShowBackingValue.Unconnected && port.IsConnected);

                    float spacePadding = 0;
                    foreach (var attr in propertyAttributes)
                    {
                        if (attr is SpaceAttribute)
                        {
                            if (usePropertyAttributes)
                            {
                                GUILayout.Space((attr as SpaceAttribute).height);
                            }
                            else
                            {
                                spacePadding += (attr as SpaceAttribute).height;
                            }
                        }
                        else if (attr is HeaderAttribute)
                        {
                            if (usePropertyAttributes)
                            {
                                //GUI Values are from https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/ScriptAttributeGUI/Implementations/DecoratorDrawers.cs
                                Rect position = GUILayoutUtility.GetRect(0, (EditorGUIUtility.singleLineHeight * 1.5f) - EditorGUIUtility.standardVerticalSpacing); //Layout adds standardVerticalSpacing after rect so we subtract it.
                                position.yMin += EditorGUIUtility.singleLineHeight * 0.5f;
                                position       = EditorGUI.IndentedRect(position);
                                GUI.Label(position, (attr as HeaderAttribute).header, EditorStyles.boldLabel);
                            }
                            else
                            {
                                spacePadding += EditorGUIUtility.singleLineHeight * 1.5f;
                            }
                        }
                    }

                    if (dynamicPortList)
                    {
                        Type type = GetType(property);
                        XNode.Node.ConnectionType connectionType = inputAttribute != null ? inputAttribute.connectionType : XNode.Node.ConnectionType.Multiple;
                        DynamicPortList(property.name, type, property.serializedObject, port.direction, connectionType);
                        return;
                    }
                    switch (showBacking)
                    {
                    case XNode.Node.ShowBackingValue.Unconnected:
                        // Display a label if port is connected
                        if (port.IsConnected)
                        {
                            EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName));
                        }
                        // Display an editable property field if port is not connected
                        else
                        {
                            EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
                        }
                        break;

                    case XNode.Node.ShowBackingValue.Never:
                        // Display a label
                        EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName));
                        break;

                    case XNode.Node.ShowBackingValue.Always:
                        // Display an editable property field
                        EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
                        break;
                    }

                    rect          = GUILayoutUtility.GetLastRect();
                    rect.position = rect.position - new Vector2(16, -spacePadding);
                    // If property is an output, display a text label and put a port handle on the right side
                }
                else if (port.direction == XNode.NodePort.IO.Output)
                {
                    // Get data from [Output] attribute
                    XNode.Node.ShowBackingValue showBacking = XNode.Node.ShowBackingValue.Unconnected;
                    XNode.Node.OutputAttribute  outputAttribute;
                    bool dynamicPortList = false;
                    if (NodeEditorUtilities.GetCachedAttrib(port.node.GetType(), property.name, out outputAttribute))
                    {
                        dynamicPortList = outputAttribute.dynamicPortList;
                        showBacking     = outputAttribute.backingValue;
                    }

                    bool usePropertyAttributes = dynamicPortList ||
                                                 showBacking == XNode.Node.ShowBackingValue.Never ||
                                                 (showBacking == XNode.Node.ShowBackingValue.Unconnected && port.IsConnected);

                    float spacePadding = 0;
                    foreach (var attr in propertyAttributes)
                    {
                        if (attr is SpaceAttribute)
                        {
                            if (usePropertyAttributes)
                            {
                                GUILayout.Space((attr as SpaceAttribute).height);
                            }
                            else
                            {
                                spacePadding += (attr as SpaceAttribute).height;
                            }
                        }
                        else if (attr is HeaderAttribute)
                        {
                            if (usePropertyAttributes)
                            {
                                //GUI Values are from https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/ScriptAttributeGUI/Implementations/DecoratorDrawers.cs
                                Rect position = GUILayoutUtility.GetRect(0, (EditorGUIUtility.singleLineHeight * 1.5f) - EditorGUIUtility.standardVerticalSpacing); //Layout adds standardVerticalSpacing after rect so we subtract it.
                                position.yMin += EditorGUIUtility.singleLineHeight * 0.5f;
                                position       = EditorGUI.IndentedRect(position);
                                GUI.Label(position, (attr as HeaderAttribute).header, EditorStyles.boldLabel);
                            }
                            else
                            {
                                spacePadding += EditorGUIUtility.singleLineHeight * 1.5f;
                            }
                        }
                    }

                    if (dynamicPortList)
                    {
                        Type type = GetType(property);
                        XNode.Node.ConnectionType connectionType = outputAttribute != null ? outputAttribute.connectionType : XNode.Node.ConnectionType.Multiple;
                        DynamicPortList(property.name, type, property.serializedObject, port.direction, connectionType);
                        return;
                    }
                    switch (showBacking)
                    {
                    case XNode.Node.ShowBackingValue.Unconnected:
                        // Display a label if port is connected
                        if (port.IsConnected)
                        {
                            EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName), NodeEditorResources.OutputPort, GUILayout.MinWidth(30));
                        }
                        // Display an editable property field if port is not connected
                        else
                        {
                            EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
                        }
                        break;

                    case XNode.Node.ShowBackingValue.Never:
                        // Display a label
                        EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName), NodeEditorResources.OutputPort, GUILayout.MinWidth(30));
                        break;

                    case XNode.Node.ShowBackingValue.Always:
                        // Display an editable property field
                        EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
                        break;
                    }

                    rect          = GUILayoutUtility.GetLastRect();
                    rect.position = rect.position + new Vector2(rect.width, spacePadding);
                }

                rect.size = new Vector2(16, 16);

                NodeEditor editor          = NodeEditor.GetEditor(port.node, NodeEditorWindow.current);
                Color      backgroundColor = editor.GetTint();
                Color      col             = NodeEditorWindow.current.graphEditor.GetPortColor(port);
                DrawPortHandle(rect, backgroundColor, col);

                // Register the handle position
                Vector2 portPos = rect.center;
                NodeEditor.portPositions[port] = portPos;
            }
        }
Beispiel #9
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.IsConnectedTo(hoveredPort))
                            {
                                draggedOutputTarget = hoveredPort;
                            }
                        }
                        else
                        {
                            draggedOutputTarget = null;
                        }
                        Repaint();
                    }
                    else if (IsDraggingNode)
                    {
                        draggedNode.position = WindowToGridPosition(e.mousePosition) + dragOffset;
                        Repaint();
                    }
                }
                else if (e.button == 1)
                {
                    panOffset += e.delta * zoom;
                    isPanning  = true;
                }
                break;

            case EventType.KeyDown:
                if (GUIUtility.keyboardControl == 0)
                {
                    break;
                }
                else if (e.keyCode == KeyCode.F)
                {
                    Home();
                }
                break;

            case EventType.MouseDown:
                Repaint();
                if (e.button == 0)
                {
                    SelectNode(hoveredNode);
                    if (IsHoveringPort)
                    {
                        if (hoveredPort.IsOutput)
                        {
                            draggedOutput = hoveredPort;
                        }
                        else
                        {
                            hoveredPort.VerifyConnections();
                            if (hoveredPort.IsConnected)
                            {
                                Node     node   = hoveredPort.node;
                                NodePort output = hoveredPort.Connection;
                                hoveredPort.Disconnect(output);
                                draggedOutput       = output;
                                draggedOutputTarget = hoveredPort;
                                if (NodeEditor.onUpdateNode != null)
                                {
                                    NodeEditor.onUpdateNode(node);
                                }
                            }
                        }
                    }
                    else if (IsHoveringNode && IsHoveringTitle(hoveredNode))
                    {
                        draggedNode = hoveredNode;
                        dragOffset  = hoveredNode.position - WindowToGridPosition(e.mousePosition);
                    }
                }
                break;

            case EventType.MouseUp:
                if (e.button == 0)
                {
                    //Port drag release
                    if (IsDraggingPort)
                    {
                        //If connection is valid, save it
                        if (draggedOutputTarget != null)
                        {
                            Node node = draggedOutputTarget.node;
                            if (graph.nodes.Count != 0)
                            {
                                draggedOutput.Connect(draggedOutputTarget);
                            }
                            if (NodeEditor.onUpdateNode != null)
                            {
                                NodeEditor.onUpdateNode(node);
                            }
                            EditorUtility.SetDirty(graph);
                        }
                        //Release dragged connection
                        draggedOutput       = null;
                        draggedOutputTarget = null;
                        EditorUtility.SetDirty(graph);
                        Repaint();
                        AssetDatabase.SaveAssets();
                    }
                    else if (IsDraggingNode)
                    {
                        draggedNode = null;
                        AssetDatabase.SaveAssets();
                    }
                    else if (GUIUtility.hotControl != 0)
                    {
                        AssetDatabase.SaveAssets();
                    }
                }
                else if (e.button == 1)
                {
                    if (!isPanning)
                    {
                        ShowContextMenu();
                    }
                    isPanning = false;
                }
                break;
            }
        }
Beispiel #10
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)
                        {
                            if (hoveredPort.IsInput)
                            {
                                if (!draggedOutput.IsConnectedTo(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 XNode.Node)
                            {
                                XNode.Node node    = Selection.objects[i] as XNode.Node;
                                Vector2    initial = node.position;
                                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;
                                }

                                // Offset portConnectionPoints instantly if a node is dragged so they aren't delayed by a frame.
                                Vector2 offset = node.position - initial;
                                if (offset.sqrMagnitude > 0)
                                {
                                    foreach (XNode.NodePort output in node.Outputs)
                                    {
                                        Rect rect;
                                        if (portConnectionPoints.TryGetValue(output, out rect))
                                        {
                                            rect.position += offset;
                                            portConnectionPoints[output] = rect;
                                        }
                                    }

                                    foreach (XNode.NodePort input in node.Inputs)
                                    {
                                        Rect rect;
                                        if (portConnectionPoints.TryGetValue(input, out rect))
                                        {
                                            rect.position += offset;
                                            portConnectionPoints[input] = rect;
                                        }
                                    }
                                }
                            }
                        }
                        // Move selected reroutes with offset
                        for (int i = 0; i < selectedReroutes.Count; i++)
                        {
                            Vector2 pos = mousePos + dragOffset[Selection.objects.Length + i];
                            if (gridSnap)
                            {
                                pos.x = (Mathf.Round(pos.x / 16) * 16);
                                pos.y = (Mathf.Round(pos.y / 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;
                }
                break;

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

                    if (IsHoveringPort)
                    {
                        if (hoveredPort.IsOutput)
                        {
                            draggedOutput = hoveredPort;
                        }
                        else
                        {
                            hoveredPort.VerifyConnections();
                            if (hoveredPort.IsConnected)
                            {
                                XNode.Node     node   = hoveredPort.node;
                                XNode.NodePort output = hoveredPort.Connection;
                                int            outputConnectionIndex = output.GetConnectionIndex(hoveredPort);
                                draggedOutputReroutes = output.GetReroutePoints(outputConnectionIndex);
                                hoveredPort.Disconnect(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 (e.clickCount == 2)
                        {
                            // Add a new node on double click
                            // Start by making it the "ObjectSelector" node
                            var pos    = WindowToGridPosition(Event.current.mousePosition);
                            var offset = new Vector2(-110, -30);
                            ObjectSelectorEditor.Position = pos + offset;
                            CreateNode(typeof(ObjectSelector), pos + offset);
                            e.Use();
                        }
                    }
                }
                break;

            case EventType.MouseUp:
                if (e.button == 0)
                {
                    //Port drag release
                    if (IsDraggingPort)
                    {
                        //If connection is valid, save it
                        if (draggedOutputTarget != null)
                        {
                            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.GetConnectionIndex(draggedOutputTarget);
                            if (connectionIndex != -1)
                            {
                                draggedOutput.GetReroutePoints(connectionIndex).AddRange(draggedOutputReroutes);
                                if (NodeEditor.onUpdateNode != null)
                                {
                                    NodeEditor.onUpdateNode(node);
                                }
                                EditorUtility.SetDirty(graph);
                            }
                        }
                        //Release dragged connection
                        draggedOutput       = null;
                        draggedOutputTarget = null;
                        EditorUtility.SetDirty(graph);
                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }
                    else if (currentActivity == NodeActivity.DragNode)
                    {
                        IEnumerable <XNode.Node> nodes = Selection.objects.Where(x => x is XNode.Node).Select(x => x as XNode.Node);
                        foreach (XNode.Node node in nodes)
                        {
                            EditorUtility.SetDirty(node);
                        }
                        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 (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX && e.commandName == "Delete")
                {
                    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;
            }
        }
        /// <summary> Make a field for a serialized property. Manual node port override. </summary>
        public static void PropertyField(SerializedProperty property, GUIContent label, XNode.NodePort port, bool includeChildren = true, params GUILayoutOption[] options)
        {
            if (property == null)
            {
                throw new NullReferenceException();
            }

            // If property is not a port, display a regular property field
            if (port == null)
            {
                EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
            }
            else
            {
                Rect rect = new Rect();

                float          spacePadding = 0;
                SpaceAttribute spaceAttribute;
                if (NodeEditorUtilities.GetCachedAttrib(port.node.GetType(), property.name, out spaceAttribute))
                {
                    spacePadding = spaceAttribute.height;
                }

                // If property is an input, display a regular property field and put a port handle on the left side
                if (port.direction == XNode.NodePort.IO.Input)
                {
                    // Get data from [Input] attribute
                    XNode.Node.ShowBackingValue showBacking = XNode.Node.ShowBackingValue.Unconnected;
                    XNode.Node.InputAttribute   inputAttribute;
                    bool dynamicPortList = false;
                    if (NodeEditorUtilities.GetCachedAttrib(port.node.GetType(), property.name, out inputAttribute))
                    {
                        dynamicPortList = inputAttribute.dynamicPortList;
                        showBacking     = inputAttribute.backingValue;
                    }

                    //Call GUILayout.Space if Space attribute is set and we are NOT drawing a PropertyField
                    bool useLayoutSpace = dynamicPortList ||
                                          showBacking == XNode.Node.ShowBackingValue.Never ||
                                          (showBacking == XNode.Node.ShowBackingValue.Unconnected && port.IsConnected);
                    if (spacePadding > 0 && useLayoutSpace)
                    {
                        GUILayout.Space(spacePadding);
                        spacePadding = 0;
                    }

                    if (dynamicPortList)
                    {
                        Type type = GetType(property);
                        XNode.Node.ConnectionType connectionType = inputAttribute != null ? inputAttribute.connectionType : XNode.Node.ConnectionType.Multiple;
                        DynamicPortList(property.name, type, property.serializedObject, port.direction, connectionType);
                        return;
                    }
                    switch (showBacking)
                    {
                    case XNode.Node.ShowBackingValue.Unconnected:
                        // Display a label if port is connected
                        if (port.IsConnected)
                        {
                            EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName));
                        }
                        // Display an editable property field if port is not connected
                        else
                        {
                            EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
                        }
                        break;

                    case XNode.Node.ShowBackingValue.Never:
                        // Display a label
                        EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName));
                        break;

                    case XNode.Node.ShowBackingValue.Always:
                        // Display an editable property field
                        EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
                        break;
                    }

                    rect          = GUILayoutUtility.GetLastRect();
                    rect.position = rect.position - new Vector2(16, -spacePadding);
                    // If property is an output, display a text label and put a port handle on the right side
                }
                else if (port.direction == XNode.NodePort.IO.Output)
                {
                    // Get data from [Output] attribute
                    XNode.Node.ShowBackingValue showBacking = XNode.Node.ShowBackingValue.Unconnected;
                    XNode.Node.OutputAttribute  outputAttribute;
                    bool dynamicPortList = false;
                    if (NodeEditorUtilities.GetCachedAttrib(port.node.GetType(), property.name, out outputAttribute))
                    {
                        dynamicPortList = outputAttribute.dynamicPortList;
                        showBacking     = outputAttribute.backingValue;
                    }

                    //Call GUILayout.Space if Space attribute is set and we are NOT drawing a PropertyField
                    bool useLayoutSpace = dynamicPortList ||
                                          showBacking == XNode.Node.ShowBackingValue.Never ||
                                          (showBacking == XNode.Node.ShowBackingValue.Unconnected && port.IsConnected);
                    if (spacePadding > 0 && useLayoutSpace)
                    {
                        GUILayout.Space(spacePadding);
                        spacePadding = 0;
                    }

                    if (dynamicPortList)
                    {
                        Type type = GetType(property);
                        XNode.Node.ConnectionType connectionType = outputAttribute != null ? outputAttribute.connectionType : XNode.Node.ConnectionType.Multiple;
                        DynamicPortList(property.name, type, property.serializedObject, port.direction, connectionType);
                        return;
                    }
                    switch (showBacking)
                    {
                    case XNode.Node.ShowBackingValue.Unconnected:
                        // Display a label if port is connected
                        if (port.IsConnected)
                        {
                            EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName), NodeEditorResources.OutputPort, GUILayout.MinWidth(30));
                        }
                        // Display an editable property field if port is not connected
                        else
                        {
                            EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
                        }
                        break;

                    case XNode.Node.ShowBackingValue.Never:
                        // Display a label
                        EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName), NodeEditorResources.OutputPort, GUILayout.MinWidth(30));
                        break;

                    case XNode.Node.ShowBackingValue.Always:
                        // Display an editable property field
                        EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30));
                        break;
                    }

                    rect          = GUILayoutUtility.GetLastRect();
                    rect.position = rect.position + new Vector2(rect.width, spacePadding);
                }

                rect.size = new Vector2(16, 16);

                NodeEditor editor          = NodeEditor.GetEditor(port.node, NodeEditorWindow.current);
                Color      backgroundColor = editor.GetTint();
                Color      col             = NodeEditorWindow.current.graphEditor.GetPortColor(port);
                DrawPortHandle(rect, backgroundColor, col);

                // Register the handle position
                Vector2 portPos = rect.center;
                NodeEditor.portPositions[port] = portPos;
            }
        }
Beispiel #12
0
        private void DrawNodes()
        {
            Event e = Event.current;

            if (e.type == EventType.Repaint)
            {
                portConnectionPoints.Clear();
                nodeWidths.Clear();
            }

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

            System.Reflection.MethodInfo onValidate = null;
            if (selectedNode != null)
            {
                onValidate = selectedNode.GetType().GetMethod("OnValidate");
                if (onValidate != null)
                {
                    nodeHash = selectedNode.GetHashCode();
                }
            }

            BeginZoomed(position, zoom);

            Vector2 mousePos = Event.current.mousePosition;

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

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

            for (int n = 0; n < graph.nodes.Count; n++)
            {
                while (graph.nodes[n] == null)
                {
                    graph.nodes.RemoveAt(n);
                }
                if (n >= graph.nodes.Count)
                {
                    return;
                }
                Node node = graph.nodes[n];

                NodeEditor nodeEditor = NodeEditor.GetEditor(node);
                NodeEditor.portPositions = new Dictionary <NodePort, Vector2>();

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

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

                GUIStyle style = NodeEditorResources.styles.nodeBody;
                GUI.color = nodeEditor.GetTint();
                GUILayout.BeginVertical(new GUIStyle(style));
                GUI.color = guiColor;
                EditorGUI.BeginChangeCheck();

                //Draw node contents
                nodeEditor.OnNodeGUI();

                //Apply
                nodeEditor.serializedObject.ApplyModifiedProperties();

                //If user changed a value, notify other scripts through onUpdateNode
                if (EditorGUI.EndChangeCheck())
                {
                    if (NodeEditor.onUpdateNode != null)
                    {
                        NodeEditor.onUpdateNode(node);
                    }
                }

                if (e.type == EventType.Repaint)
                {
                    nodeWidths.Add(node, nodeEditor.GetWidth());

                    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);
                        portConnectionPoints.Add(kvp.Key, rect);
                    }
                }

                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;
                    }

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

                GUILayout.EndArea();
            }

            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 (selectedNode != null)
            {
                if (onValidate != null && nodeHash != selectedNode.GetHashCode())
                {
                    onValidate.Invoke(selectedNode, null);
                }
            }
        }
Beispiel #13
0
        public void Controls()
        {
            this.wantsMouseMove = true;
            var e = Event.current;

            switch (e.type)
            {
            case EventType.DragUpdated:
            case EventType.DragPerform:
                DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
                if (e.type == EventType.DragPerform)
                {
                    DragAndDrop.AcceptDrag();
                    this.graphEditor.OnDropObjects(DragAndDrop.objectReferences);
                }

                break;

            case EventType.MouseMove:
                //Keyboard commands will not get correct mouse position from Event
                this.lastMousePosition = e.mousePosition;
                break;

            case EventType.ScrollWheel:
                var oldZoom = this.zoom;
                if (e.delta.y > 0)
                {
                    this.zoom += 0.1f * this.zoom;
                }
                else
                {
                    this.zoom -= 0.1f * this.zoom;
                }
                if (NodeEditorPreferences.GetSettings().zoomToMouse)
                {
                    this.panOffset += (1 - oldZoom / this.zoom) * (this.WindowToGridPosition(e.mousePosition) + this.panOffset);
                }
                break;

            case EventType.MouseDrag:
                switch (e.button)
                {
                case 0:
                {
                    if (this.IsDraggingPort)
                    {
                        // Set target even if we can't connect, so as to prevent auto-conn menu from opening erroneously
                        if (this.IsHoveringPort && this.hoveredPort.IsInput && !this.draggedOutput.IsConnectedTo(this.hoveredPort))
                        {
                            this.draggedOutputTarget = this.hoveredPort;
                        }
                        else
                        {
                            this.draggedOutputTarget = null;
                        }

                        this.Repaint();
                    }
                    else if (currentActivity == NodeActivity.HoldNode)
                    {
                        this.RecalculateDragOffsets(e);
                        currentActivity = NodeActivity.DragNode;
                        this.Repaint();
                    }

                    switch (currentActivity)
                    {
                    case NodeActivity.DragNode:
                    {
                        // Holding ctrl inverts grid snap
                        var gridSnap = NodeEditorPreferences.GetSettings().gridSnap;
                        if (e.control)
                        {
                            gridSnap = !gridSnap;
                        }

                        var mousePos = this.WindowToGridPosition(e.mousePosition);
                        // Move selected nodes with offset
                        for (var i = 0; i < Selection.objects.Length; i++)
                        {
                            if (!(Selection.objects[i] is xNode.Node node))
                            {
                                continue;
                            }

                            Undo.RecordObject(node, "Moved Node");
                            var initial = node.position;
                            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;
                            }

                            // Offset portConnectionPoints instantly if a node is dragged so they aren't delayed by a frame.
                            var offset = node.position - initial;
                            if (!(offset.sqrMagnitude > 0))
                            {
                                continue;
                            }

                            foreach (var output in node.Outputs)
                            {
                                if (this.portConnectionPoints.TryGetValue(output, out var rect))
                                {
                                    rect.position += offset;
                                    this.portConnectionPoints[output] = rect;
                                }
                            }

                            foreach (var input in node.Inputs)
                            {
                                if (this.portConnectionPoints.TryGetValue(input, out var rect))
                                {
                                    rect.position += offset;
                                    this.portConnectionPoints[input] = rect;
                                }
                            }
                        }

                        // Move selected reroutes with offset
                        for (var i = 0; i < this.selectedReroutes.Count; i++)
                        {
                            var pos = mousePos + dragOffset[Selection.objects.Length + i];
                            if (gridSnap)
                            {
                                pos.x = (Mathf.Round(pos.x / 16) * 16);
                                pos.y = (Mathf.Round(pos.y / 16) * 16);
                            }

                            this.selectedReroutes[i].SetPoint(pos);
                        }

                        this.Repaint();
                        break;
                    }

                    case NodeActivity.HoldGrid:
                        currentActivity             = NodeActivity.DragGrid;
                        this.preBoxSelection        = Selection.objects;
                        this.preBoxSelectionReroute = this.selectedReroutes.ToArray();
                        this.dragBoxStart           = this.WindowToGridPosition(e.mousePosition);
                        this.Repaint();
                        break;

                    case NodeActivity.DragGrid:
                    {
                        var boxStartPos = this.GridToWindowPosition(this.dragBoxStart);
                        var 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);
                        }

                        this.selectionBox = new Rect(boxStartPos, boxSize);
                        this.Repaint();
                        break;
                    }
                    }

                    break;
                }

                case 1:
                case 2:
                {
                    //check drag threshold for larger screens
                    if (e.delta.magnitude > this.dragThreshold)
                    {
                        this.panOffset += e.delta * this.zoom;
                        isPanning       = true;
                    }

                    break;
                }
                }

                break;

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

                    if (this.IsHoveringPort)
                    {
                        if (this.hoveredPort.IsOutput)
                        {
                            this.draggedOutput     = this.hoveredPort;
                            this.autoConnectOutput = this.hoveredPort;
                        }
                        else
                        {
                            this.hoveredPort.VerifyConnections();
                            this.autoConnectOutput = null;
                            if (this.hoveredPort.IsConnected)
                            {
                                var node   = this.hoveredPort.node;
                                var output = this.hoveredPort.Connection;
                                var outputConnectionIndex = output.GetConnectionIndex(this.hoveredPort);
                                this.draggedOutputReroutes = output.GetReroutePoints(outputConnectionIndex);
                                this.hoveredPort.Disconnect(output);
                                this.draggedOutput       = output;
                                this.draggedOutputTarget = this.hoveredPort;
                                if (NodeEditor.onUpdateNode != null)
                                {
                                    NodeEditor.onUpdateNode(node);
                                }
                            }
                        }
                    }
                    else if (this.IsHoveringNode && this.IsHoveringTitle(this.hoveredNode))
                    {
                        // If mousedown on node header, select or deselect
                        if (!Selection.Contains(this.hoveredNode))
                        {
                            this.SelectNode(this.hoveredNode, e.control || e.shift);
                            if (!e.control && !e.shift)
                            {
                                this.selectedReroutes.Clear();
                            }
                        }
                        else if (e.control || e.shift)
                        {
                            this.DeselectNode(this.hoveredNode);
                        }

                        // Cache double click state, but only act on it in MouseUp - Except ClickCount only works in mouseDown.
                        this.isDoubleClick = (e.clickCount == 2);

                        e.Use();
                        currentActivity = NodeActivity.HoldNode;
                    }
                    else if (this.IsHoveringReroute)
                    {
                        // If reroute isn't selected
                        if (!this.selectedReroutes.Contains(this.hoveredReroute))
                        {
                            // Add it
                            if (e.control || e.shift)
                            {
                                this.selectedReroutes.Add(this.hoveredReroute);
                            }
                            // Select it
                            else
                            {
                                this.selectedReroutes = new List <RerouteReference>()
                                {
                                    this.hoveredReroute
                                };
                                Selection.activeObject = null;
                            }
                        }
                        // Deselect
                        else if (e.control || e.shift)
                        {
                            this.selectedReroutes.Remove(this.hoveredReroute);
                        }

                        e.Use();
                        currentActivity = NodeActivity.HoldNode;
                    }
                    // If mousedown on grid background, deselect all
                    else if (!this.IsHoveringNode)
                    {
                        currentActivity = NodeActivity.HoldGrid;
                        if (!e.control && !e.shift)
                        {
                            this.selectedReroutes.Clear();
                            Selection.activeObject = null;
                        }
                    }
                }

                break;

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

                            // ConnectionIndex can be -1 if the connection is removed instantly after creation
                            var connectionIndex = this.draggedOutput.GetConnectionIndex(this.draggedOutputTarget);
                            if (connectionIndex != -1)
                            {
                                this.draggedOutput.GetReroutePoints(connectionIndex).AddRange(this.draggedOutputReroutes);
                                if (NodeEditor.onUpdateNode != null)
                                {
                                    NodeEditor.onUpdateNode(node);
                                }
                                EditorUtility.SetDirty(this.graph);
                            }
                        }
                        // Open context menu for auto-connection if there is no target node
                        else if (this.draggedOutputTarget == null && NodeEditorPreferences.GetSettings().dragToCreate&& this.autoConnectOutput != null)
                        {
                            var menu = new GenericMenu();
                            this.graphEditor.AddContextMenuItems(menu);
                            menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
                        }

                        //Release dragged connection
                        this.draggedOutput       = null;
                        this.draggedOutputTarget = null;
                        EditorUtility.SetDirty(this.graph);
                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }
                    else if (currentActivity == NodeActivity.DragNode)
                    {
                        var nodes = Selection.objects.Where(x => x is xNode.Node).Select(x => x as xNode.Node);
                        foreach (var node in nodes)
                        {
                            EditorUtility.SetDirty(node);
                        }
                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }
                    else if (!this.IsHoveringNode)
                    {
                        // If click outside node, release field focus
                        if (!isPanning)
                        {
                            EditorGUI.FocusTextInControl(null);
                            EditorGUIUtility.editingTextField = false;
                        }

                        if (NodeEditorPreferences.GetSettings().autoSave)
                        {
                            AssetDatabase.SaveAssets();
                        }
                    }

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

                        // Double click to center node
                        if (this.isDoubleClick)
                        {
                            var nodeDimension = this.nodeSizes.ContainsKey(this.hoveredNode)
                                    ? this.nodeSizes[this.hoveredNode] / 2
                                    : Vector2.zero;
                            this.panOffset = -this.hoveredNode.position - nodeDimension;
                        }
                    }

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

                    this.Repaint();
                    currentActivity = NodeActivity.Idle;
                }
                else if (e.button == 1 || e.button == 2)
                {
                    if (!isPanning)
                    {
                        if (this.IsDraggingPort)
                        {
                            this.draggedOutputReroutes.Add(this.WindowToGridPosition(e.mousePosition));
                        }
                        else if (currentActivity == NodeActivity.DragNode && Selection.activeObject == null && this.selectedReroutes.Count == 1)
                        {
                            this.selectedReroutes[0].InsertPoint(this.selectedReroutes[0].GetPoint());
                            this.selectedReroutes[0] = new RerouteReference(this.selectedReroutes[0].port, this.selectedReroutes[0].connectionIndex, this.selectedReroutes[0].pointIndex + 1);
                        }
                        else if (this.IsHoveringReroute)
                        {
                            this.ShowRerouteContextMenu(this.hoveredReroute);
                        }
                        else if (this.IsHoveringPort)
                        {
                            this.ShowPortContextMenu(this.hoveredPort);
                        }
                        else if (this.IsHoveringNode && this.IsHoveringTitle(this.hoveredNode))
                        {
                            if (!Selection.Contains(this.hoveredNode))
                            {
                                this.SelectNode(this.hoveredNode, false);
                            }
                            this.autoConnectOutput = null;
                            var menu = new GenericMenu();
                            NodeEditor.GetEditor(this.hoveredNode, this).AddContextMenuItems(menu);
                            menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
                            e.Use();     // Fixes copy/paste context menu appearing in Unity 5.6.6f2 - doesn't occur in 2018.3.2f1 Probably needs to be used in other places.
                        }
                        else if (!this.IsHoveringNode)
                        {
                            this.autoConnectOutput = null;
                            var menu = new GenericMenu();
                            this.graphEditor.AddContextMenuItems(menu);
                            menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
                        }
                    }

                    isPanning = false;
                }

                // Reset DoubleClick
                this.isDoubleClick = false;
                break;

            case EventType.KeyDown:
                if (EditorGUIUtility.editingTextField)
                {
                    break;
                }
                else if (e.keyCode == KeyCode.F)
                {
                    this.Home();
                }
                if (NodeEditorUtilities.IsMac())
                {
                    if (e.keyCode == KeyCode.Return)
                    {
                        this.RenameSelectedNode();
                    }
                }
                else
                {
                    if (e.keyCode == KeyCode.F2)
                    {
                        this.RenameSelectedNode();
                    }
                }

                if (e.keyCode == KeyCode.A)
                {
                    if (Selection.objects.Any(x => this.graph.nodes.Contains(x as xNode.Node)))
                    {
                        foreach (var node in this.graph.nodes)
                        {
                            this.DeselectNode(node);
                        }
                    }
                    else
                    {
                        foreach (var node in this.graph.nodes)
                        {
                            this.SelectNode(node, true);
                        }
                    }

                    this.Repaint();
                }

                break;

            case EventType.ValidateCommand:
            case EventType.ExecuteCommand:
                if (e.commandName == "SoftDelete")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        this.RemoveSelectedNodes();
                    }
                    e.Use();
                }
                else if (NodeEditorUtilities.IsMac() && e.commandName == "Delete")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        this.RemoveSelectedNodes();
                    }
                    e.Use();
                }
                else if (e.commandName == "Duplicate")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        this.DuplicateSelectedNodes();
                    }
                    e.Use();
                }
                else if (e.commandName == "Copy")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        this.CopySelectedNodes();
                    }
                    e.Use();
                }
                else if (e.commandName == "Paste")
                {
                    if (e.type == EventType.ExecuteCommand)
                    {
                        this.PasteNodes(this.WindowToGridPosition(this.lastMousePosition));
                    }
                    e.Use();
                }

                this.Repaint();
                break;

            case EventType.Ignore:
                // If release mouse outside window
                if (e.rawType == EventType.MouseUp && currentActivity == NodeActivity.DragGrid)
                {
                    this.Repaint();
                    currentActivity = NodeActivity.Idle;
                }

                break;
            }
        }
Beispiel #14
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.IsConnectedTo(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 XNode.Node)
                            {
                                XNode.Node node = Selection.objects[i] as 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;
                }
                break;

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

                    if (IsHoveringPort)
                    {
                        if (hoveredPort.IsOutput)
                        {
                            draggedOutput = hoveredPort;
                        }
                        else
                        {
                            hoveredPort.VerifyConnections();
                            if (hoveredPort.IsConnected)
                            {
                                XNode.Node     node   = hoveredPort.node;
                                XNode.NodePort output = hoveredPort.Connection;
                                int            outputConnectionIndex = output.GetConnectionIndex(hoveredPort);
                                draggedOutputReroutes = output.GetReroutePoints(outputConnectionIndex);
                                hoveredPort.Disconnect(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;
                        }
                    }
                }
                break;

            case EventType.MouseUp:
                if (e.button == 0)
                {
                    //Port drag release
                    if (IsDraggingPort)
                    {
                        //If connection is valid, save it
                        if (draggedOutputTarget != null)
                        {
                            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.GetConnectionIndex(draggedOutputTarget);
                            if (connectionIndex != -1)
                            {
                                draggedOutput.GetReroutePoints(connectionIndex).AddRange(draggedOutputReroutes);
                                if (NodeEditor.onUpdateNode != null)
                                {
                                    NodeEditor.onUpdateNode(node);
                                }
                                EditorUtility.SetDirty(graph);
                            }
                        }
                        //Release dragged connection
                        draggedOutput       = null;
                        draggedOutputTarget = null;
                        EditorUtility.SetDirty(graph);
                        AssetDatabase.SaveAssets();
                    }
                    else if (currentActivity == NodeActivity.DragNode)
                    {
                        AssetDatabase.SaveAssets();
                    }
                    else if (!IsHoveringNode)
                    {
                        // If click outside node, release field focus
                        if (!isPanning)
                        {
                            // I've got no idea which of these do what, so we'll just reset all of it.
                            GUIUtility.hotControl             = 0;
                            GUIUtility.keyboardControl        = 0;
                            EditorGUIUtility.editingTextField = false;
                            EditorGUIUtility.keyboardControl  = 0;
                            EditorGUIUtility.hotControl       = 0;
                        }
                        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)
                {
                    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();
                }
                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;
            }
        }
Beispiel #15
0
        //private EntityActionNode eaNode;
        //private EntityConditionNode ecNode;
        void RenderDialogNodeGUI(NodeEditor nodeEditor, XNode.Node node)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.BeginVertical();
            dn = node as DialogNode;
            if (dn != null)
            {
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                if (dn.showDialogText = EditorGUILayout.Foldout(dn.showDialogText, "Dialog"))
                {
                    EditorGUILayout.LabelField("Dialog");
                    EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                    dn.dialog.text = EditorGUILayout.TextArea(dn.dialog.text, EditorStyles.wordWrappedLabel, GUILayout.MinHeight(60), GUILayout.MaxWidth(180));
                    EditorGUILayout.EndVertical();
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                if (dn.Options = EditorGUILayout.Foldout(dn.Options, "Options"))
                {
                    EditorGUILayout.LabelField("Talk ID");
                    dn.dialog.TalkID = EditorGUILayout.IntSlider(dn.dialog.TalkID, 0, 6);
                    dn.dialog.clip   = (AudioClip)EditorGUILayout.ObjectField("Audio", dn.dialog.clip, typeof(AudioClip), false);
                    if (dn.dialog.hasEvent = EditorGUILayout.Toggle("Event", dn.dialog.hasEvent))
                    {
                        dn.dialog.eventID = EditorGUILayout.IntField("Event ID", dn.dialog.eventID);
                    }
                    dn.dialog.isEntry = EditorGUILayout.Toggle("Is Entry", dn.dialog.isEntry);
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                if (dn.showDialogCondition = EditorGUILayout.Foldout(dn.showDialogCondition, "Conditions"))
                {
                    if (dn.dialog.conditions == null)
                    {
                        dn.dialog.conditions = new DialogObject.DialogCondition();
                    }
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.Space();
                    EditorGUILayout.BeginVertical();
                    EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                    dn.dialog.conditions.isOneTime = EditorGUILayout.Toggle("One Shot", dn.dialog.conditions.isOneTime);
                    if (dn.dialog.conditions.isOneTime && string.IsNullOrEmpty(dn.dialog.conditions.oneTimeID))
                    {
                        dn.dialog.conditions.oneTimeID = ToolKit.GetUniqueID();
                    }
                    EditorGUILayout.EndVertical();
                    EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                    if (dn.showDialogVar = EditorGUILayout.Foldout(dn.showDialogVar, "Global Var"))
                    {
                        EditorGUILayout.LabelField(dn.dialog.conditions.varID);
                        if (GUILayout.Button("Set Var"))
                        {
                            ObjectPicker.GetObject(ObjectPicker.ObjectType.Variable, dn.SetDialogVar);
                        }
                        dn.dialog.conditions.varState = EditorGUILayout.Toggle("State", dn.dialog.conditions.varState);
                    }
                    EditorGUILayout.EndVertical();

                    EditorGUILayout.EndVertical();
                    EditorGUILayout.EndHorizontal();
                }
                EditorGUILayout.EndVertical();

                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
                if (GUILayout.Button("Add", EditorStyles.toolbarButton))
                {
                    dn.AddResponse();
                }
                if (GUILayout.Button("Remove", EditorStyles.toolbarButton))
                {
                    dn.RemoveResponse();
                }
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                {
                    int i = 0;
                    if (dn.selectedResponse > dn.dialog.responses.Length - 1)
                    {
                        dn.selectedResponse = -1;
                    }
                    foreach (DialogObject.DialogResponse response in dn.dialog.responses)
                    {
                        EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                        EditorGUILayout.BeginHorizontal();
                        string s = "";
                        if (!string.IsNullOrEmpty(response.response))
                        {
                            s = TruncateLongString(response.response, 16);
                        }
                        else
                        {
                            s = "Response " + i.ToString();
                        }
                        if (GUILayout.Button(s, EditorStyles.foldout))
                        {
                            if (dn.selectedResponse == i)
                            {
                                dn.selectedResponse = -1;
                            }
                            else
                            {
                                dn.selectedResponse = i;
                            }
                        }
                        nodeEditor.OnNodeGUI(i);
                        EditorGUILayout.EndHorizontal();
                        if (dn.selectedResponse == i)
                        {
                            if (dn.dialog.responses != null && dn.dialog.responses.Length > 0 && dn.selectedResponse >= 0)
                            {
                                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                                dn.dialog.responses[dn.selectedResponse].response = EditorGUILayout.TextArea(dn.dialog.responses[dn.selectedResponse].response, EditorStyles.wordWrappedLabel, GUILayout.MinHeight(60), GUILayout.MaxWidth(180));
                                EditorGUILayout.EndVertical();
                                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                                dn.responseOptions = EditorGUILayout.Foldout(dn.responseOptions, "Options");
                                if (dn.responseOptions)
                                {
                                    dn.conditionOptions = false;
                                    dn.dialog.responses[dn.selectedResponse].eventID = EditorGUILayout.IntField("Event", dn.dialog.responses[dn.selectedResponse].eventID);
                                }
                                EditorGUILayout.EndVertical();
                                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                                dn.conditionOptions = EditorGUILayout.Foldout(dn.conditionOptions, "Conditions");
                                if (dn.conditionOptions)
                                {
                                    dn.responseOptions = false;
                                    if (dn.dialog.responses[dn.selectedResponse].conditions == null)
                                    {
                                        dn.dialog.responses[dn.selectedResponse].conditions = new DialogObject.DialogCondition();
                                    }
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.Space();
                                    EditorGUILayout.BeginVertical();
                                    EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                                    dn.dialog.responses[dn.selectedResponse].conditions.isOneTime = EditorGUILayout.Toggle("One Shot", dn.dialog.responses[dn.selectedResponse].conditions.isOneTime);
                                    if (dn.dialog.responses[dn.selectedResponse].conditions.isOneTime && string.IsNullOrEmpty(dn.dialog.responses[dn.selectedResponse].conditions.oneTimeID))
                                    {
                                        dn.dialog.responses[dn.selectedResponse].conditions.oneTimeID = ToolKit.GetUniqueID();
                                    }
                                    EditorGUILayout.EndVertical();
                                    EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                                    if (dn.showVar = EditorGUILayout.Foldout(dn.showVar, "Global Var"))
                                    {
                                        EditorGUILayout.LabelField(dn.dialog.responses[dn.selectedResponse].conditions.varID);
                                        if (GUILayout.Button("Set Var"))
                                        {
                                            //ObjectPicker.GetObject(ObjectPicker.ObjectType.Variable, dn.SetVar);
                                            Debug.Log("Get/set vars");
                                        }
                                        dn.dialog.responses[dn.selectedResponse].conditions.varState = EditorGUILayout.Toggle("State", dn.dialog.responses[dn.selectedResponse].conditions.varState);
                                    }
                                    EditorGUILayout.EndVertical();
                                    EditorGUILayout.EndVertical();
                                    EditorGUILayout.EndHorizontal();
                                }
                                EditorGUILayout.EndVertical();
                            }
                        }
                        i++;
                        EditorGUILayout.EndVertical();
                    }
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.EndVertical();
                EditorUtility.SetDirty(dn);
            }
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndHorizontal();
        }