Example #1
0
 /// <summary> Make a field for a serialized property. Automatically displays relevant node port. </summary>
 public static void PropertyField(SerializedProperty property, GUIContent label, bool includeChildren = true, params GUILayoutOption[] options)
 {
     if (property == null)
     {
         throw new NullReferenceException();
     }
     Siccity.XNode.Node     node = property.serializedObject.targetObject as Siccity.XNode.Node;
     Siccity.XNode.NodePort port = node.GetPort(property.name);
     PropertyField(property, label, port, includeChildren);
 }
Example #2
0
        /// <summary> Make a simple port field. </summary>
        public static void PortField(GUIContent label, Siccity.XNode.NodePort port, params GUILayoutOption[] options)
        {
            if (port == null)
            {
                return;
            }
            if (label == null)
            {
                EditorGUILayout.LabelField(ObjectNames.NicifyVariableName(port.fieldName), options);
            }
            else
            {
                EditorGUILayout.LabelField(label, options);
            }
            Rect rect = GUILayoutUtility.GetLastRect();

            if (port.direction == Siccity.XNode.NodePort.IO.Input)
            {
                rect.position = rect.position - new Vector2(16, 0);
            }
            else if (port.direction == Siccity.XNode.NodePort.IO.Output)
            {
                rect.position = rect.position + new Vector2(rect.width, 0);
            }
            rect.size = new Vector2(16, 16);

            Color backgroundColor = new Color32(90, 97, 105, 255);

            if (NodeEditorWindow.nodeTint.ContainsKey(port.node.GetType()))
            {
                backgroundColor *= NodeEditorWindow.nodeTint[port.node.GetType()];
            }
            Color col = NodeEditorWindow.current.graphEditor.GetTypeColor(port.ValueType);

            DrawPortHandle(rect, backgroundColor, col);

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

            if (NodeEditor.portPositions.ContainsKey(port))
            {
                NodeEditor.portPositions[port] = portPos;
            }
            else
            {
                NodeEditor.portPositions.Add(port, portPos);
            }
        }
Example #3
0
        /// <summary> Draws all connections </summary>
        public void DrawConnections()
        {
            foreach (Siccity.XNode.Node node in graph.nodes)
            {
                //If a null node is found, return. This can happen if the nodes associated script is deleted. It is currently not possible in Unity to delete a null asset.
                if (node == null)
                {
                    continue;
                }

                foreach (Siccity.XNode.NodePort output in node.Outputs)
                {
                    //Needs cleanup. Null checks are ugly
                    if (!portConnectionPoints.ContainsKey(output))
                    {
                        continue;
                    }
                    Vector2 from = _portConnectionPoints[output].center;
                    for (int k = 0; k < output.ConnectionCount; k++)
                    {
                        Siccity.XNode.NodePort input = output.GetConnection(k);
                        if (input == null)
                        {
                            continue;                //If a script has been updated and the port doesn't exist, it is removed and null is returned. If this happens, return.
                        }
                        if (!input.IsConnectedTo(output))
                        {
                            input.Connect(output);
                        }
                        if (!_portConnectionPoints.ContainsKey(input))
                        {
                            continue;
                        }
                        Vector2 to = _portConnectionPoints[input].center;
                        Color   connectionColor = graphEditor.GetTypeColor(output.ValueType);
                        DrawConnection(from, to, connectionColor);
                    }
                }
            }
        }
Example #4
0
        /// <summary> Dublicate selected nodes and select the dublicates </summary>
        public void DublicateSelectedNodes() {
            UnityEngine.Object[] newNodes = new UnityEngine.Object[Selection.objects.Length];
            Dictionary<Siccity.XNode.Node, Siccity.XNode.Node> substitutes = new Dictionary<Siccity.XNode.Node, Siccity.XNode.Node>();
            for (int i = 0; i < Selection.objects.Length; i++) {
                if (Selection.objects[i] is Siccity.XNode.Node) {
                    Siccity.XNode.Node srcNode = Selection.objects[i] as Siccity.XNode.Node;
                    if (srcNode.graph != graph) continue; // ignore nodes selected in another graph
                    Siccity.XNode.Node newNode = graph.CopyNode(srcNode);
                    substitutes.Add(srcNode, newNode);
                    newNode.position = srcNode.position + new Vector2(30, 30);
                    newNodes[i] = newNode;
                }
            }

            // Walk through the selected nodes again, recreate connections, using the new nodes
            for (int i = 0; i < Selection.objects.Length; i++) {
                if (Selection.objects[i] is Siccity.XNode.Node) {
                    Siccity.XNode.Node srcNode = Selection.objects[i] as Siccity.XNode.Node;
                    if (srcNode.graph != graph) continue; // ignore nodes selected in another graph
                    foreach (Siccity.XNode.NodePort port in srcNode.Ports) {
                        for (int c = 0; c < port.ConnectionCount; c++) {
                            Siccity.XNode.NodePort inputPort = port.direction == Siccity.XNode.NodePort.IO.Input ? port : port.GetConnection(c);
                            Siccity.XNode.NodePort outputPort = port.direction == Siccity.XNode.NodePort.IO.Output ? port : port.GetConnection(c);

                            if (substitutes.ContainsKey(inputPort.node) && substitutes.ContainsKey(outputPort.node)) {
                                Siccity.XNode.Node newNodeIn = substitutes[inputPort.node];
                                Siccity.XNode.Node newNodeOut = substitutes[outputPort.node];
                                newNodeIn.UpdateStaticPorts();
                                newNodeOut.UpdateStaticPorts();
                                inputPort = newNodeIn.GetInputPort(inputPort.fieldName);
                                outputPort = newNodeOut.GetOutputPort(outputPort.fieldName);
                            }
                            if (!inputPort.IsConnectedTo(outputPort)) inputPort.Connect(outputPort);
                        }
                    }
                }
            }
            Selection.objects = newNodes;
        }
Example #5
0
        /// <summary> Make a field for a serialized property. Manual node port override. </summary>
        public static void PropertyField(SerializedProperty property, GUIContent label, Siccity.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();

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

                    switch (showBacking)
                    {
                    case Siccity.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 Siccity.XNode.Node.ShowBackingValue.Never:
                        // Display a label
                        EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName));
                        break;

                    case Siccity.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, 0);
                    // If property is an output, display a text label and put a port handle on the right side
                }
                else if (port.direction == Siccity.XNode.NodePort.IO.Output)
                {
                    // Get data from [Output] attribute
                    Siccity.XNode.Node.ShowBackingValue showBacking = Siccity.XNode.Node.ShowBackingValue.Unconnected;
                    Siccity.XNode.Node.OutputAttribute  outputAttribute;
                    if (NodeEditorUtilities.GetAttrib(port.node.GetType(), property.name, out outputAttribute))
                    {
                        showBacking = outputAttribute.backingValue;
                    }

                    switch (showBacking)
                    {
                    case Siccity.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 Siccity.XNode.Node.ShowBackingValue.Never:
                        // Display a label
                        EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName), NodeEditorResources.OutputPort, GUILayout.MinWidth(30));
                        break;

                    case Siccity.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, 0);
                }

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

                Color backgroundColor = new Color32(90, 97, 105, 255);
                if (NodeEditorWindow.nodeTint.ContainsKey(port.node.GetType()))
                {
                    backgroundColor *= NodeEditorWindow.nodeTint[port.node.GetType()];
                }
                Color col = NodeEditorWindow.current.graphEditor.GetTypeColor(port.ValueType);
                DrawPortHandle(rect, backgroundColor, col);

                // Register the handle position
                Vector2 portPos = rect.center;
                if (NodeEditor.portPositions.ContainsKey(port))
                {
                    NodeEditor.portPositions[port] = portPos;
                }
                else
                {
                    NodeEditor.portPositions.Add(port, portPos);
                }
            }
        }
Example #6
0
 /// <summary> Make a field for a serialized property. Manual node port override. </summary>
 public static void PropertyField(SerializedProperty property, Siccity.XNode.NodePort port, bool includeChildren = true, params GUILayoutOption[] options)
 {
     PropertyField(property, null, port, includeChildren, options);
 }
Example #7
0
 /// <summary> Make a simple port field. </summary>
 public static void PortField(Siccity.XNode.NodePort port, params GUILayoutOption[] options)
 {
     PortField(null, port, options);
 }
Example #8
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.HoldHeader || currentActivity == NodeActivity.DragHeader) {
                            for (int i = 0; i < Selection.objects.Length; i++) {
                                if (Selection.objects[i] is Siccity.XNode.Node) {
                                    Siccity.XNode.Node node = Selection.objects[i] as Siccity.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 (Siccity.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) {
                                    Siccity.XNode.Node node = hoveredPort.node;
                                    Siccity.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 Siccity.XNode.Node) {
                                    Siccity.XNode.Node node = Selection.objects[i] as Siccity.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) {
                                Siccity.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) {
                                GUIUtility.hotControl = 0;
                                GUIUtility.keyboardControl = 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.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;
            }
        }