private void CheckHoveringAndSelection()
        {
            if (_isLayoutEvent)
            {
                return;
            }

            ResetHover();

            bool isDraggingGrid = _currentActivity == Activity.DraggingGrid;

            Rect          selectionRect = _selectionRect;
            Vector2       mousePosition = _mousePosition;
            List <Object> boxSelected   = new List <Object>();

            //TODO Investigate reverse recognition not working!?
            //Never mind it works, it's just my architecture works bottom-top,
            //instead of top-bottom-or-stop
            //Why? Cause hovering
            //TODO Investigate alternatives for conversion
            for (int i = 0; i < Graph.NodeCount; i++)
            {
                Node       node       = Graph.GetNode(i);
                NodeEditor nodeEditor = NodeEditor.GetEditor(node);

                Vector2 size;
                if (_nodeSizes.TryGetValue(node, out size))
                {
                    Rect nodeRect = new Rect(node.Position, size);
                    nodeRect = GridToWindowRect(nodeRect);
                    if (nodeRect.Contains(mousePosition))
                    {
                        _hoveredNode = node;
                    }
                    if (isDraggingGrid && nodeRect.Overlaps(selectionRect))
                    {
                        boxSelected.Add(node);
                    }
                }

                //Check hovering over ports
                var inputNode = node as IInput;
                if (inputNode != null)
                {
                    InputPort input     = inputNode.InputPort;
                    Rect      inputRect = nodeEditor.GetPortRect(input);
                    //inputRect.position += node.Position;
                    inputRect = GridToWindowRect(inputRect);
                    if (inputRect.Contains(mousePosition))
                    {
                        HoveredPort = input;
                    }
                }

                IOutput sOutputNode = node as IOutput;
                if (sOutputNode != null)
                {
                    OutputPort output     = sOutputNode.OutputPort;
                    Rect       outputRect = nodeEditor.GetPortRect(output);
                    //outputRect.position += node.Position;
                    outputRect = GridToWindowRect(outputRect);
                    if (outputRect.Contains(mousePosition))
                    {
                        HoveredPort = output;
                    }
                }

                IMultipleOutput mOutputNode = node as IMultipleOutput;
                if (mOutputNode != null)
                {
                    var outputs = mOutputNode.GetOutputs();
                    foreach (OutputPort output in outputs)
                    {
                        Rect outputRect = nodeEditor.GetPortRect(output);
                        //outputRect.position += node.Position;
                        outputRect = GridToWindowRect(outputRect);
                        if (outputRect.Contains(mousePosition))
                        {
                            HoveredPort = output;
                        }
                    }
                }
            }

            for (int i = 0; i < Graph.ConnectionCount; i++)
            {
                Connection connection = Graph.GetConnection(i);
                if (connection == null)
                {
                    Debug.Log("Null connection at index " + i);
                    OnNull(Graph);
                    continue;
                }

                Vector2 start = NodeEditor.FindPortRect(connection.Start).center;
                Vector2 end   = NodeEditor.FindPortRect(connection.End).center;
                start = GridToWindowPosition(start);
                end   = GridToWindowPosition(end);

                //if (OtherUtilities.PointOverlapBezier(mousePosition, start, end, NodePreferences.CONNECTION_WIDTH))
                if (LineSegment.WideLineSegmentPointCheck(mousePosition, start, end, NodePreferences.CONNECTION_WIDTH * 2 / Zoom))
                {
                    _hoveredConnection = connection;
                }

                //DONE: Add range percentage overlap check, as just overlapping might be too annoying.
                if (isDraggingGrid && LineSegment.LineRectOverlapPercentageCheck(selectionRect, start, end) > 0.3f)
                {
                    boxSelected.Add(connection);
                }


                Rect[] modifierRects;
                if (!_connectionModifierRects.TryGetValue(connection, out modifierRects))
                {
                    continue;
                }

                for (int j = 0; j < connection.InstructionCount; j++)
                {
                    Instruction mod  = connection.GetInstruction(j);
                    Rect        rect = GridToWindowRect(modifierRects[j]);
                    if (rect.Contains(mousePosition))
                    {
                        _hoveredInstruction = mod;
                    }
                    if (isDraggingGrid && rect.Overlaps(selectionRect))
                    {
                        boxSelected.Add(mod);
                    }
                }
            }

            //return;
            if (isDraggingGrid)
            {
                if (_cachedEvent.control || _cachedEvent.shift)
                {
                    boxSelected.AddRange(_cachedSelectedObjects);
                }
                Selection.objects = boxSelected.ToArray();
            }
            else
            {
                _selectionRect = Rect.zero;
            }
        }
        private void DrawNodes()
        {
            if (_isLayoutEvent)
            {
                _culledNodes = new List <Node>();
            }

            _nodeSizes = new Dictionary <Node, Vector2>();
            Color oldColor = GUI.color;

            //Utilities.BeginZoom(position, Zoom, TopPadding);

            for (int i = 0; i < _graph.NodeCount; i++)
            {
                Node node = _graph.GetNode(i);
                if (node == null)
                {
                    continue;
                }
                if (i >= _graph.NodeCount)
                {
                    return;
                }
                bool selected = Selection.Contains(node);

                if (_isLayoutEvent)
                {
                    if (!selected && ShouldBeCulled(node))
                    {
                        _culledNodes.Add(node);
                        continue;
                    }
                }
                else if (_culledNodes.Contains(node))
                {
                    continue;
                }

                NodeEditor nodeEditor = NodeEditor.GetEditor(node);

                Vector2 nodePosition = GridToWindowPositionNotClipped(node.Position);
                GUILayout.BeginArea(new Rect(nodePosition, new Vector2(nodeEditor.GetWidth(), 4000)));

                if (selected)
                {
                    GUIStyle style          = new GUIStyle(nodeEditor.GetBodyStyle());
                    GUIStyle highlightStyle = new GUIStyle(NodeResources.Styles.nodeHighlight)
                    {
                        padding = style.padding
                    };
                    style.padding = new RectOffset();
                    GUI.color     = nodeEditor.GetTint();
                    GUILayout.BeginVertical(style);
                    GUI.color = Color.white;
                    GUILayout.BeginVertical(new GUIStyle(highlightStyle));
                }
                else
                {
                    GUIStyle style = new GUIStyle(nodeEditor.GetBodyStyle());
                    GUI.color = nodeEditor.GetTint();
                    GUILayout.BeginVertical(style);
                }

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

                nodeEditor.OnHeaderGUI();
                nodeEditor.OnBodyGUI();

                if (EditorGUI.EndChangeCheck())
                {
                    NodeEditor.UpdateCallback(node);
                    EditorUtility.SetDirty(node);
                    nodeEditor.SerializedObject.ApplyModifiedProperties();
                }

                GUILayout.EndVertical();
                if (!_isLayoutEvent)
                {
                    Rect rect = GUILayoutUtility.GetLastRect();
                    //Debug.Log("Caching Rect: " + rect);
                    _nodeSizes[node] = rect.size;
                }
                if (selected)
                {
                    GUILayout.EndVertical();
                }

                GUILayout.EndArea();
            }
        }
        private void MouseUp()
        {
            if (!_leftMouseButtonUsed)
            {
                if (_rightMouseButtonUsed || _middleMouseButtonUsed)
                {
                    ContextClick();
                }
                return;
            }
            if (IsDraggingPort)
            {
                //If the connection is valid, save it
                if (DraggedOutputTarget != null)
                {
                    //DraggedOutput.Connect(DraggedOutputTarget)
                    if (Graph.NodeCount != 0)
                    {
                        Connect(DraggedOutput, DraggedOutputTarget);
                    }
                    NodeEditor.UpdateCallback(DraggedOutputTarget.Node);
                    NodeEditor.UpdateCallback(DraggedOutput.Node);
                }

                //Release the dragged connection
                DraggedOutput       = null;
                DraggedOutputTarget = null;
                EditorUtility.SetDirty(Graph);
                NodeEditorUtilities.AutoSaveAssets();
            }
            else if (_currentActivity == Activity.Dragging)
            {
                Node[] nodes = GetSelected <Node>();
                foreach (Node node in nodes)
                {
                    EditorUtility.SetDirty(node);
                }
                NodeEditorUtilities.AutoSaveAssets();
            }
            else if (!IsHoveringConnectionModifier)
            {
                //If clicking outside the Con. Mod, release the field focus
                if (!IsPanning)
                {
                    EditorGUI.FocusTextInControl(null);
                }
                NodeEditorUtilities.AutoSaveAssets();
            }
            else if (!IsHoveringNode)
            {
                //If clicking outside the node, release the field focus
                if (!IsPanning)
                {
                    EditorGUI.FocusTextInControl(null);
                }
                NodeEditorUtilities.AutoSaveAssets();
            }

            if (_currentActivity == Activity.Holding && !(_cachedEvent.control || _cachedEvent.shift))
            {
                if (IsHoveringNode)
                {
                    Select(_hoveredNode, false);
                }
                else if (IsHoveringConnectionModifier)
                {
                    Select(_hoveredInstruction, false);
                }
            }

            Repaint();
            _currentActivity = Activity.Idle;
        }