Beispiel #1
0
        /// <summary>
        /// Creates a node of the specified ID at pos on the specified canvas, optionally auto-connecting the specified output to a matching input
        /// silent disables any events, init specifies whether OnCreate should be called
        /// </summary>
        public static Node Create(string nodeID, Vector2 pos, NodeCanvas hostCanvas, ConnectionPort connectingPort = null, bool silent = false, bool init = true)
        {
            if (string.IsNullOrEmpty(nodeID) || hostCanvas == null)
            {
                throw new ArgumentException();
            }
            if (!NodeCanvasManager.CheckCanvasCompability(nodeID, hostCanvas.GetType()))
            {
                throw new UnityException("Cannot create Node with ID '" + nodeID + "' as it is not compatible with the current canavs type (" + hostCanvas.GetType().ToString() + ")!");
            }
            if (!hostCanvas.CanAddNode(nodeID))
            {
                throw new UnityException("Cannot create Node with ID '" + nodeID + "' on the current canvas of type (" + hostCanvas.GetType().ToString() + ")!");
            }

            // Create node from data
            NodeTypeData data = NodeTypes.getNodeData(nodeID);
            Node         node = (Node)CreateInstance(data.type);

            if (node == null)
            {
                return(null);
            }

            // Init node state
            node.name     = node.Title;
            node.autoSize = node.DefaultSize;
            node.position = pos;
            ConnectionPortManager.UpdateConnectionPorts(node);
            if (init)
            {
                node.OnCreate();
            }

            if (connectingPort != null)
            {             // Handle auto-connection and link the output to the first compatible input
                for (int i = 0; i < node.connectionPorts.Count; i++)
                {
                    if (node.connectionPorts[i].TryApplyConnection(connectingPort, silent))
                    {
                        break;
                    }
                }
            }

            // Add node to host canvas
            hostCanvas.nodes.Add(node);
            if (!silent)
            {             // Callbacks
                hostCanvas.OnNodeChange(connectingPort != null ? connectingPort.body : node);
                NodeEditorCallbacks.IssueOnAddNode(node);
                hostCanvas.Validate();
                NodeEditor.RepaintClients();
            }

            return(node);
        }
Beispiel #2
0
        private static void FillAddNodes(NodeEditorInputInfo inputInfo, GenericMenu canvasContextMenu)
        {         // Show all nodes, and if a connection is drawn, only compatible nodes to auto-connect
            NodeEditorState state          = inputInfo.editorState;
            List <Node>     displayedNodes = state.connectOutput != null?NodeTypes.getCompatibleNodes(state.connectOutput) : NodeTypes.nodes.Keys.ToList();

            foreach (Node compatibleNode in displayedNodes)
            {
                canvasContextMenu.AddItem(new GUIContent("Add " + NodeTypes.nodes[compatibleNode].adress), false, CreateNodeCallback, new NodeEditorInputInfo(compatibleNode.GetID, state));
            }
        }
Beispiel #3
0
        private static void FillAddNodes(NodeEditorInputInfo inputInfo, GenericMenu canvasContextMenu)
        {         // Fill context menu with nodes to add to the canvas
            NodeEditorState state = inputInfo.editorState;
            List <string>   nodes = NodeTypes.getCompatibleNodes(state.connectKnob);

            foreach (string node in nodes)
            {             // Only add nodes to the context menu that are compatible
                if (NodeCanvasManager.CheckCanvasCompability(node, inputInfo.editorState.canvas.GetType()) && inputInfo.editorState.canvas.CanAddNode(node))
                {
                    canvasContextMenu.AddItem(new GUIContent("Add " + NodeTypes.getNodeData(node).adress), false, CreateNodeCallback, new NodeEditorInputInfo(node, state));
                }
            }
        }
Beispiel #4
0
        public static void checkInit()
        {
            if (!initiated && !InitiationError)
            {
        #if UNITY_EDITOR
                Object script = UnityEditor.AssetDatabase.LoadAssetAtPath(editorPath + "Framework/NodeEditor.cs", typeof(Object));
                if (script == null)
                {
                    Debug.LogError("Node Editor: Not installed in default directory '" + editorPath + "'! Please modify the editorPath variable in the source!");
                    InitiationError = true;
                    return;
                }
        #endif

                Background = LoadTexture("Textures/background.png");
                AALineTex  = LoadTexture("Textures/AALine.png");
                if (!Background || !AALineTex)
                {
                    InitiationError = true;
                    return;
                }

                ConnectionTypes.FetchTypes();
                NodeTypes.FetchNodes();
                NodeEditorCallbacks.SetupReceivers();
                NodeEditorCallbacks.IssueOnEditorStartUp();

                // Styles
                nodeBox = new GUIStyle(GUI.skin.box);

        #if UNITY_EDITOR
                nodeBox.normal.background = ColorToTex(UnityEditor.EditorGUIUtility.isProSkin? new Color(0.5f, 0.5f, 0.5f) : new Color(0.2f, 0.2f, 0.2f));
        #else
                nodeBox.normal.background = ColorToTex(new Color(0.2f, 0.2f, 0.2f));
        #endif

                nodeBox.normal.textColor = new Color(0.7f, 0.7f, 0.7f);

                nodeButton = new GUIStyle(GUI.skin.button);

                nodeLabel = new GUIStyle(GUI.skin.label);
                nodeLabel.normal.textColor = new Color(0.7f, 0.7f, 0.7f);

                nodeLabelBold           = new GUIStyle(nodeLabel);
                nodeLabelBold.fontStyle = FontStyle.Bold;
                nodeLabelBold.wordWrap  = false;

                initiated = true;
            }
            return;
        }
Beispiel #5
0
        public static Transition Create(Node from, Node to)
        {
            if (NodeTypes.getNodeData(from).transitions == false || NodeTypes.getNodeData(to).transitions == false)
            {
                return(null);
            }
            Transition transition = CreateInstance <Transition> ();

            transition.name       = "Transition " + from.name + "-" + to.name;
            transition.startNode  = from;
            transition.endNode    = to;
            transition.conditions = new List <Func <Transition, bool> > ();
            return(transition);
        }
        public static Node Create(string nodeID, Vector2 position)
        {
            Node node = NodeTypes.getDefaultNode(nodeID);

            if (node == null)
            {
                throw new UnityException("Cannot create Node with id " + nodeID + " as no such Node type is registered!");
            }

            node = node.Create(position);
            node.InitBase();

            NodeEditorCallbacks.IssueOnAddNode(node);
            return(node);
        }
Beispiel #7
0
        public static Node MoveNext(Node node)
        {
            if (NodeTypes.getNodeData(node).transitions == false)
            {
                Debug.LogError("Node " + node.ToString() + " does not accept Transitions!");
                return(null);
            }

            for (int transCnt = 0; transCnt < node.transitions.Count; transCnt++)
            {
                if (node.transitions[transCnt].conditionsMet())
                {
                    return(node.transitions[transCnt].endNode);
                }
            }

            return(node);
        }
Beispiel #8
0
        /// <summary>
        /// Create the a Node of the type specified by the nodeID at position
        /// Auto-connects the passed connectingOutput if not null to the first compatible input
        /// </summary>
        public static Node Create(string nodeID, Vector2 position, NodeOutput connectingOutput)
        {
            if (!NodeCanvasManager.CheckCanvasCompability(nodeID, NodeEditor.curNodeCanvas))
            {
                throw new UnityException("Cannot create Node with ID '" + nodeID + "' as it is not compatible with the current canavs type (" + NodeEditor.curNodeCanvas.GetType().ToString() + ")!");
            }
            if (!NodeEditor.curNodeCanvas.CanAddNode(nodeID))
            {
                throw new UnityException("Cannot create another Node with ID '" + nodeID + "' on the current canvas of type (" + NodeEditor.curNodeCanvas.GetType().ToString() + ")!");
            }
            Node node = NodeTypes.getDefaultNode(nodeID);

            if (node == null)
            {
                throw new UnityException("Cannot create Node as ID '" + nodeID + "' is not registered!");
            }

            node = node.Create(position);

            if (node == null)
            {
                return(null);
            }

            node.InitBase();

            if (connectingOutput != null)
            {             // Handle auto-connection and link the output to the first compatible input
                foreach (NodeInput input in node.Inputs)
                {
                    if (input.TryApplyConnection(connectingOutput))
                    {
                        break;
                    }
                }
            }

            NodeEditorCallbacks.IssueOnAddNode(node);
            NodeEditor.curNodeCanvas.Validate();

            return(node);
        }
Beispiel #9
0
        public static void InitSystem()
        {
            _inst = AssetDatabase.LoadAssetAtPath <NodeSystemSetting>(ASSET_PATH);
            bool hasExist = _inst != null;

            if (!hasExist)
            {
                _inst = CreateInstance <NodeSystemSetting>();
                AssetDatabase.CreateAsset(_inst, ASSET_PATH);
            }

            ConnectionPortStyles.InitSystem(out _inst.portStyles, out _inst.valueTypes);
            NodeTypes.InitSystem(out _inst.nodeDatas);
            NodeCanvasManager.InitSystem(out _inst.canvasDatas);
            ConnectionPortManager.InitSystem(out _inst.nodePortDec);
            ConnectionPortManager.InitSystem(out _inst.nodePortDec);
            ImportExportManager.InitSystem(out _inst.ioFormats);

            NodeEditorInputSystem.InitSystem(out _inst.eventHandlers, out _inst.hotkeyHandlers, out _inst.contextEntries, out _inst.contextFillers);
        }
 public static void ReInit(bool GUIFunction)
 {
     CheckEditorPath();
     ResourceManager.SetDefaultResourcePath(editorPath + "Resources/");
     if (!NodeEditorGUI.Init(GUIFunction))
     {
         InitiationError = true;
     }
     else
     {
         ConnectionTypes.FetchTypes();
         NodeTypes.FetchNodes();
         NodeCanvasManager.GetAllCanvasTypes();
         NodeEditorCallbacks.SetupReceivers();
         NodeEditorCallbacks.IssueOnEditorStartUp();
         GUIScaleUtility.CheckInit();
         NodeEditorInputSystem.SetupInput();
         initiated = GUIFunction;
     }
 }
Beispiel #11
0
        /// <summary>
        /// Fetches every node connection declaration for each node type for later use
        /// </summary>
        public static void FetchNodeConnectionDeclarations()
        {
            nodePortDeclarations = new Dictionary <string, ConnectionPortDeclaration[]> ();
            foreach (NodeTypeData nodeData in NodeTypes.getNodeDefinitions())
            {
                Type nodeType = nodeData.type;
                List <ConnectionPortDeclaration> declarations = new List <ConnectionPortDeclaration> ();
                // Get all declared port fields
                FieldInfo[] declaredPorts = ReflectionUtility.getFieldsOfType(nodeType, typeof(ConnectionPort));

                if (nodeType.Name == "DialogueConditionCheckNode")
                {
                    string s = "";
                    for (int i = 0; i < declaredPorts.Length; i++)
                    {
                        s += "(" + declaredPorts[i].Name + ", " + declaredPorts[i].ToString() + ") ";
                    }
                    Debug.Log(s);
                }

                foreach (FieldInfo portField in declaredPorts)
                {                 // Get info about that port declaration using the attribute
                    object[] declAttrs = portField.GetCustomAttributes(typeof(ConnectionPortAttribute), true);
                    if (declAttrs.Length < 1)
                    {
                        continue;
                    }
                    ConnectionPortAttribute declarationAttr = (ConnectionPortAttribute)declAttrs[0];
                    if (declarationAttr.MatchFieldType(portField.FieldType))
                    {
                        declarations.Add(new ConnectionPortDeclaration(portField, declarationAttr));
                    }
                    else
                    {
                        Debug.LogError("Mismatched " + declarationAttr.GetType().Name + " for " + portField.FieldType.Name + " '" + declarationAttr.Name + "' on " + nodeData.type.Name + "!");
                    }
                }
                nodePortDeclarations.Add(nodeData.typeID, declarations.ToArray());
            }
        }
Beispiel #12
0
        /// <summary>
        /// Re-Inits the NodeCanvas regardless of whetehr it was initiated before
        /// </summary>
        public static void ReInit(bool GUIFunction)
        {
            CheckEditorPath();

            // Init Resource system. Can be called anywhere else, too, if it's needed before.
            ResourceManager.SetDefaultResourcePath(editorPath + "Resources/");

            // Init NE GUI. I may throw an error if a texture was not found.
            if (!NodeEditorGUI.Init(GUIFunction))
            {
                InitiationError = true;
                return;
            }

            // Run fetching algorithms searching the script assemblies for Custom Nodes / Connection Types
            ConnectionTypes.FetchTypes();
            NodeTypes.FetchNodes();


            NodeCanvasManager.GetAllCanvasTypes();

            // Setup Callback system
            NodeEditorCallbacks.SetupReceivers();
            NodeEditorCallbacks.IssueOnEditorStartUp();

            // Init GUIScaleUtility. This fetches reflected calls and my throw a message notifying about incompability.
            GUIScaleUtility.CheckInit();

            // Init input
            NodeEditorInputSystem.SetupInput();

        #if UNITY_EDITOR
            UnityEditor.EditorApplication.update -= Update;
            UnityEditor.EditorApplication.update += Update;
            RepaintClients();
        #endif
            initiated = GUIFunction;
        }
Beispiel #13
0
        public static Node Create(string nodeID, Vector2 position, NodeOutput connectingOutput)
        {
            Node defaultNode = NodeTypes.getDefaultNode(nodeID);

            if ((UnityEngine.Object)defaultNode == (UnityEngine.Object)null)
            {
                throw new UnityException("Cannot create Node with id " + nodeID + " as no such Node type is registered!");
            }
            defaultNode = defaultNode.Create(position);
            defaultNode.InitBase();
            if ((UnityEngine.Object)connectingOutput != (UnityEngine.Object)null)
            {
                foreach (NodeInput input in defaultNode.Inputs)
                {
                    if (input.TryApplyConnection(connectingOutput))
                    {
                        break;
                    }
                }
            }
            NodeEditorCallbacks.IssueOnAddNode(defaultNode);
            return(defaultNode);
        }
Beispiel #14
0
        /// <summary>
        /// Creates a node of the specified ID at pos on the specified canvas, optionally auto-connecting the specified output to a matching input
        /// silent disables any events, init specifies whether OnCreate should be called
        /// </summary>
        public static Node Create(string nodeID, Vector2 pos, NodeCanvas hostCanvas, ConnectionPort connectingPort = null, bool silent = false, bool init = true)
        {
            if (string.IsNullOrEmpty(nodeID) || hostCanvas == null)
            {
                throw new ArgumentException();
            }
            if (!NodeCanvasManager.CheckCanvasCompability(nodeID, hostCanvas.GetType()))
            {
                throw new UnityException("Cannot create Node with ID '" + nodeID + "' as it is not compatible with the current canavs type (" + hostCanvas.GetType().ToString() + ")!");
            }
            if (!hostCanvas.CanAddNode(nodeID))
            {
                throw new UnityException("Cannot create Node with ID '" + nodeID + "' on the current canvas of type (" + hostCanvas.GetType().ToString() + ")!");
            }

            // Create node from data
            NodeTypeData data = NodeTypes.getNodeData(nodeID);
            Node         node = (Node)CreateInstance(data.type);

            if (node == null)
            {
                return(null);
            }

            // Init node state
            node.canvas   = hostCanvas;
            node.name     = node.Title;
            node.autoSize = node.DefaultSize;
            node.position = pos;
            ConnectionPortManager.UpdateConnectionPorts(node);
            if (init)
            {
                node.OnCreate();
            }

            if (connectingPort != null)
            {             // Handle auto-connection and link the output to the first compatible input
                for (int i = 0; i < node.connectionPorts.Count; i++)
                {
                    if (node.connectionPorts[i].TryApplyConnection(connectingPort, true))
                    {
                        break;
                    }
                }
            }

            // Add node to host canvas
            hostCanvas.nodes.Add(node);
            if (!silent)
            {             // Callbacks
                hostCanvas.OnNodeChange(connectingPort != null ? connectingPort.body : node);
                NodeEditorCallbacks.IssueOnAddNode(node);
                hostCanvas.Validate();
                NodeEditor.RepaintClients();
            }

#if UNITY_EDITOR
            if (!silent)
            {
                List <ConnectionPort> connectedPorts = new List <ConnectionPort>();
                foreach (ConnectionPort port in node.connectionPorts)
                {                 // 'Encode' connected ports in one list (double level cannot be serialized)
                    foreach (ConnectionPort conn in port.connections)
                    {
                        connectedPorts.Add(conn);
                    }
                    connectedPorts.Add(null);
                }
                Node createdNode = node;
                UndoPro.UndoProManager.RecordOperation(
                    () => NodeEditorUndoActions.ReinstateNode(createdNode, connectedPorts),
                    () => NodeEditorUndoActions.RemoveNode(createdNode),
                    "Create Node");
                // Make sure the new node is in the memory dump
                NodeEditorUndoActions.CompleteSOMemoryDump(hostCanvas);
            }
#endif

            return(node);
        }
        /// <summary>
        /// Checks whether the süecified nodeID is compatible with the given canvas type
        /// 检测制定的Node ID是否与当前Canvas相匹配
        /// </summary>
        public static bool CheckCanvasCompability(string nodeID, Type canvasType)
        {
            NodeTypeData data = NodeTypes.GetNodeData(nodeID);

            return(data.limitToCanvasTypes == null || data.limitToCanvasTypes.Length == 0 || data.limitToCanvasTypes.Contains(canvasType));
        }
        private static void FillAddNodes(NodeEditorInputInfo inputInfo, GenericMenu canvasContextMenu)
        {
            NodeEditorState editorState    = inputInfo.editorState;
            List <Node>     displayedNodes = (!((UnityEngine.Object)editorState.connectOutput != (UnityEngine.Object)null)) ? NodeTypes.nodes.Keys.ToList() : NodeTypes.getCompatibleNodes(editorState.connectOutput);

            DeCafList(ref displayedNodes, editorState.canvas);
            foreach (Node item in displayedNodes)
            {
                NodeData nodeData = NodeTypes.nodes[item];
                canvasContextMenu.AddItem(new GUIContent("Add " + nodeData.adress), false, CreateNodeCallback, new NodeEditorInputInfo(item.GetID, editorState));
            }
        }
Beispiel #17
0
        /// <summary>
        /// Context Click selection. Here you'll need to register your own using a string identifier
        /// </summary>
        public static void ContextCallback(object obj)
        {
            callbackObject cbObj = obj as callbackObject;

            curNodeCanvas  = cbObj.canvas;
            curEditorState = cbObj.editor;

            switch (cbObj.message)
            {
            case "deleteNode":
                if (curEditorState.focusedNode != null)
                {
                    curEditorState.focusedNode.Delete();
                }
                break;

            case "duplicateNode":
                if (curEditorState.focusedNode != null)
                {
                    ContextCallback(new callbackObject(curEditorState.focusedNode.GetID, curNodeCanvas, curEditorState));
                    Node duplicatedNode = curNodeCanvas.nodes [curNodeCanvas.nodes.Count - 1];

                    curEditorState.focusedNode    = duplicatedNode;
                    curEditorState.dragNode       = true;
                    curEditorState.makeTransition = null;
                    curEditorState.connectOutput  = null;
                    curEditorState.panWindow      = false;
                }
                break;

            case "startTransition":
                if (curEditorState.focusedNode != null)
                {
                    curEditorState.makeTransition = curEditorState.focusedNode;
                    curEditorState.connectOutput  = null;
                }
                curEditorState.dragNode  = false;
                curEditorState.panWindow = false;

                break;

            default:
                Vector2 createPos = ScreenToGUIPos(mousePos);

                Node node = NodeTypes.getDefaultNode(cbObj.message);
                if (node == null)
                {
                    break;
                }

                bool acceptTransitions = NodeTypes.nodes [node].transitions;

                node = node.Create(createPos);
                node.InitBase();
                NodeEditorCallbacks.IssueOnAddNode(node);

                if (curEditorState.connectOutput != null)
                {                 // If nodeOutput is defined, link it to the first input of the same type
                    foreach (NodeInput input in node.Inputs)
                    {
                        if (Node.CanApplyConnection(curEditorState.connectOutput, input))
                        {                         // If it can connect (type is equals, it does not cause recursion, ...)
                            Node.ApplyConnection(curEditorState.connectOutput, input);
                            break;
                        }
                    }
                }
                else if (acceptTransitions && curEditorState.makeTransition != null)
                {
                    Node.CreateTransition(curEditorState.makeTransition, node);
                }

                curEditorState.makeTransition = null;
                curEditorState.connectOutput  = null;
                curEditorState.dragNode       = false;
                curEditorState.panWindow      = false;

                break;
            }

            if (NodeEditor.Repaint != null)
            {
                NodeEditor.Repaint();
            }
        }
Beispiel #18
0
        /// <summary>
        /// Processes input events
        /// </summary>
        public static void InputEvents(List <Rect> ignoreInput)
        {
            Event e = Event.current;

            mousePos = e.mousePosition;

            if (OverlayGUI.HasPopupControl())
            {
                return;
            }

            bool insideCanvas = curEditorState.canvasRect.Contains(e.mousePosition);

            for (int ignoreCnt = 0; ignoreCnt < ignoreInput.Count; ignoreCnt++)
            {
                if (ignoreInput [ignoreCnt].Contains(e.mousePosition))
                {
                    insideCanvas = false;
                    break;
                }
            }

            if (!insideCanvas)
            {
                return;
            }

            curEditorState.focusedNode = null;
            if (insideCanvas && (e.type == EventType.MouseDown || e.type == EventType.MouseUp))
            {
                curEditorState.focusedNode = NodeEditor.NodeAtPosition(e.mousePosition);
                if (e.button == 0)
                {
                    curEditorState.activeNode = curEditorState.focusedNode;
                    if (Repaint != null)
                    {
                        Repaint();
                    }
                }
            }

        #if UNITY_EDITOR
            if (curEditorState.focusedNode != null)
            {
                UnityEditor.Selection.activeObject = curEditorState.focusedNode;
            }
        #endif

            switch (e.type)
            {
            case EventType.MouseDown:

                curEditorState.dragNode  = false;
                curEditorState.panWindow = false;

                if (curEditorState.focusedNode != null)
                {                 // A click on a node
                    if (e.button == 1)
                    {             // Right click -> Node Context Click
                        // TODO: Node Editor: Editor-Independancy - GenericMenu conversion
//	#if UNITY_EDITOR
//						UnityEditor.GenericMenu menu = new UnityEditor.GenericMenu ();
//	#else
                        GenericMenu menu = new GenericMenu();
//	#endif
                        menu.AddItem(new GUIContent("Delete Node"), false, ContextCallback, new callbackObject("deleteNode", curNodeCanvas, curEditorState));
                        menu.AddItem(new GUIContent("Duplicate Node"), false, ContextCallback, new callbackObject("duplicateNode", curNodeCanvas, curEditorState));
                        if (NodeTypes.getNodeData(curEditorState.focusedNode).transitions)
                        {
                            menu.AddSeparator("Seperator");
                            menu.AddItem(new GUIContent("Make Transition"), false, ContextCallback, new callbackObject("startTransition", curNodeCanvas, curEditorState));
                        }

                        menu.ShowAsContext();

                        e.Use();
                    }
                    else if (e.button == 0)
                    {
                        if (!GUIToScreenRect(curEditorState.focusedNode.rect).Contains(e.mousePosition))
                        {                         // Left click at node edges -> Check for clicked connections to edit
                            NodeOutput nodeOutput = curEditorState.focusedNode.GetOutputAtPos(e.mousePosition);
                            if (nodeOutput != null)
                            {                             // Output Node -> New Connection drawn from this
                                curEditorState.connectOutput = nodeOutput;
                                e.Use();
                            }
                            else
                            {                             // no output clicked, check input
                                NodeInput nodeInput = curEditorState.focusedNode.GetInputAtPos(e.mousePosition);
                                if (nodeInput != null && nodeInput.connection != null)
                                {                                 // Input node -> Loose and edit Connection
                                    curEditorState.connectOutput = nodeInput.connection;
                                    Node.RemoveConnection(nodeInput);
                                    e.Use();
                                }
                            }
                        }
                    }
                }
                else
                {                 // A click on the empty canvas
                    if (e.button == 2 || e.button == 0)
                    {             // Left/Middle Click -> Start scrolling
                        curEditorState.panWindow = true;
                        e.delta = Vector2.zero;
                    }
                    else if (e.button == 1)
                    {                     // Right click -> Editor Context Click
                        // TODO: Node Editor: Editor-Independancy - GenericMenu conversion
                        if (curEditorState.connectOutput != null || curEditorState.makeTransition != null)
                        {
//							#if UNITY_EDITOR
//							UnityEditor.GenericMenu menu = new UnityEditor.GenericMenu ();
//							#else
                            GenericMenu menu = new GenericMenu();
//							#endif

                            // Iterate through all compatible nodes
                            foreach (Node node in NodeTypes.nodes.Keys)
                            {
                                if (curEditorState.connectOutput != null)
                                {
                                    foreach (var input in node.Inputs)
                                    {
                                        if (input.type == curEditorState.connectOutput.type)
                                        {
                                            menu.AddItem(new GUIContent("Add " + NodeTypes.nodes[node].adress), false, ContextCallback, new callbackObject(node.GetID, curNodeCanvas, curEditorState));
                                            break;
                                        }
                                    }
                                }
                                else if (curEditorState.makeTransition != null && NodeTypes.nodes [node].transitions)
                                {
                                    menu.AddItem(new GUIContent("Add " + NodeTypes.nodes[node].adress), false, ContextCallback, new callbackObject(node.GetID, curNodeCanvas, curEditorState));
                                }
                            }

                            menu.ShowAsContext();
                        }
                        else
                        {
//							#if UNITY_EDITOR
//							UnityEditor.GenericMenu menu = new UnityEditor.GenericMenu ();
//							#else
                            GenericMenu menu = new GenericMenu();
//							#endif

                            foreach (Node node in NodeTypes.nodes.Keys)
                            {
                                menu.AddItem(new GUIContent("Add " + NodeTypes.nodes [node].adress), false, ContextCallback, new callbackObject(node.GetID, curNodeCanvas, curEditorState));
                            }

                            menu.ShowAsContext();
                        }
                        e.Use();
                    }
                }

                break;

            case EventType.MouseUp:

                if (curEditorState.focusedNode != null)
                {
                    if (curEditorState.makeTransition != null)
                    {
                        Node.CreateTransition(curEditorState.makeTransition, curEditorState.focusedNode);
                    }
                    else if (curEditorState.connectOutput != null)
                    {                     // Apply a connection if theres a clicked input
                        if (!curEditorState.focusedNode.Outputs.Contains(curEditorState.connectOutput))
                        {                 // If an input was clicked, it'll will now be connected
                            NodeInput clickedInput = curEditorState.focusedNode.GetInputAtPos(e.mousePosition);
                            if (Node.CanApplyConnection(curEditorState.connectOutput, clickedInput))
                            {                             // If it can connect (type is equals, it does not cause recursion, ...)
                                Node.ApplyConnection(curEditorState.connectOutput, clickedInput);
                            }
                        }
                        e.Use();
                    }
                }

                curEditorState.makeTransition = null;
                curEditorState.connectOutput  = null;
                curEditorState.dragNode       = false;
                curEditorState.panWindow      = false;

                break;

            case EventType.ScrollWheel:

                curEditorState.zoom = (float)Math.Round(Math.Min(2.0f, Math.Max(0.6f, curEditorState.zoom + e.delta.y / 15)), 2);
                if (Repaint != null)
                {
                    Repaint();
                }

                break;

            case EventType.KeyDown:

                // TODO: Node Editor: Shortcuts
                if (e.keyCode == KeyCode.N)                 // Start Navigating (curve to origin / active Node)
                {
                    curEditorState.navigate = true;
                }

                if (e.keyCode == KeyCode.LeftControl && curEditorState.activeNode != null)                 // Snap
                {
                    curEditorState.activeNode.rect.position = new Vector2(Mathf.RoundToInt((curEditorState.activeNode.rect.position.x - curEditorState.panOffset.x) / 10) * 10 + curEditorState.panOffset.x,
                                                                          Mathf.RoundToInt((curEditorState.activeNode.rect.position.y - curEditorState.panOffset.y) / 10) * 10 + curEditorState.panOffset.y);
                }
                if (Repaint != null)
                {
                    Repaint();
                }

                break;

            case EventType.KeyUp:

                if (e.keyCode == KeyCode.N)                 // Stop Navigating
                {
                    curEditorState.navigate = false;
                }

                if (Repaint != null)
                {
                    Repaint();
                }

                break;

            case EventType.MouseDrag:

                if (curEditorState.panWindow)
                {                 // Scroll everything with the current mouse delta
                    curEditorState.panOffset += e.delta * curEditorState.zoom;
                    for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++)
                    {
                        curNodeCanvas.nodes [nodeCnt].rect.position += e.delta * curEditorState.zoom;
                    }
                    e.delta = Vector2.zero;
                    if (Repaint != null)
                    {
                        Repaint();
                    }
                }
                else
                {
                    curEditorState.panWindow = false;
                }

                if (curEditorState.dragNode && curEditorState.activeNode != null && GUIUtility.hotControl == 0)
                {                 // Drag the active node with the current mouse delta
                    curEditorState.activeNode.rect.position += e.delta * curEditorState.zoom;
                    NodeEditorCallbacks.IssueOnMoveNode(curEditorState.activeNode);
                    e.delta = Vector2.zero;
                    if (Repaint != null)
                    {
                        Repaint();
                    }
                }
                else
                {
                    curEditorState.dragNode = false;
                }

                break;
            }
        }