static void RenderCustomGizmos(Position positionData, GizmoType gizmoType)
    {
        for (int i = 0; i < positionData.nodes.Count; i++)
        {
            Position.PositionNode positionNode = positionData.nodes[i];

            Vector3 position = positionData.nodes[i].position;
            if (gizmoType == GizmoType.NotInSelectionHierarchy)
            {
                Gizmos.color = i == positionData.finishLineIndex ? Color.red : Color.green;
                Gizmos.DrawSphere(position, .2f);
            }

            for (int c = 0; c < 4; c++)
            {
                int connection = positionNode.connectedIndexes[c];
                if (connection == -1)
                {
                    continue;
                }

                Vector3 mid = position * .5f + positionData.nodes[connection].position * .5f;
                Gizmos.color = Color.black;
                Gizmos.DrawLine(mid, position);
                Gizmos.color = Color.cyan;
                Gizmos.DrawLine(mid, positionData.nodes[connection].position);
            }
        }
    }
    private void ChangeNodeConnection(int nodeIndex)
    {
        if (nodeIndex == selectedNodeIndex || selectedNodeIndex == -1)
        {
            return;
        }

        EditorUtility.SetDirty(positionData);
        Undo.RecordObject(positionData, "Change Node Connection");

        Position.PositionNode selectedNode = positionData.nodes[selectedNodeIndex];
        bool used = false;

        for (int c = 0; c < 4; c++)
        {
            if (positionData.nodes[nodeIndex].connectedIndexes[c] == selectedNodeIndex)
            {
                positionData.nodes[nodeIndex].connectedIndexes[c] = -1;
                used = true;
                break;
            }
        }

        if (!used)
        {
            for (int c = 0; c < 4; c++)
            {
                if (selectedNode.connectedIndexes[c] == nodeIndex)
                {
                    selectedNode.connectedIndexes[c] = -1;
                    used = true;
                    break;
                }
            }
        }

        if (!used)
        {
            for (int c = 0; c < 4; c++)
            {
                if (selectedNode.connectedIndexes[c] == -1)
                {
                    selectedNode.connectedIndexes[c] = nodeIndex;
                    break;
                }
            }
        }
    }
    private void DoMidPoint(int nodeIndex)
    {
        Handles.color = new Color(1, 1, 1, .2f);
        Position.PositionNode node = positionData.nodes[nodeIndex];

        for (int c = 0; c < 4; c++)
        {
            int connection = node.connectedIndexes[c];
            if (connection == -1)
            {
                continue;
            }
            if (selectedNodeIndex == nodeIndex || connection == selectedNodeIndex)
            {
                Position.PositionNode otherNode = positionData.nodes[connection];

                Vector3 middle = Vector3.Lerp(node.position, otherNode.position, .5f);
                Vector3 connectionDirection = otherNode.position - node.position;
                Vector3 viewDirection       = middle - SceneView.currentDrawingSceneView.camera.transform.position;
                Vector3 cross = Vector3.Cross(connectionDirection, viewDirection).normalized;

                Handles.DrawLine(middle + cross, middle - cross);

                float handleScale = HandleUtility.GetHandleSize(middle);
                if (Handles.Button(middle, Quaternion.identity, handleScale * .03f, handleScale * .05f, Handles.DotHandleCap))
                {
                    EditorUtility.SetDirty(positionData);
                    Undo.RecordObject(positionData, "Insert Node");

                    node.connectedIndexes[c] = positionData.nodes.Count;

                    positionData.nodes.Add(new Position.PositionNode()
                    {
                        position         = middle,
                        connectedIndexes = new int[4] {
                            connection, -1, -1, -1
                        }
                    });
                }
            }
        }

        positionData.nodes[nodeIndex] = node;
    }
    private void DeleteNode(int nodeIndex)
    {
        if (nodeIndex == -1)
        {
            return;
        }

        EditorUtility.SetDirty(positionData);
        Undo.RecordObject(positionData, "Delete Node");

        for (int i = 0; i < positionData.nodes.Count; i++)
        {
            Position.PositionNode previousNode = positionData.nodes[i];
            for (int c = 0; c < 4; c++)
            {
                if (previousNode.connectedIndexes[c] == nodeIndex)
                {
                    previousNode.connectedIndexes[c] = positionData.nodes[nodeIndex].connectedIndexes[0];
                }
            }
            positionData.nodes[i] = previousNode;
        }

        positionData.nodes.RemoveAt(nodeIndex);

        for (int i = 0; i < positionData.nodes.Count; i++)
        {
            Position.PositionNode node = positionData.nodes[i];
            for (int c = 0; c < 4; c++)
            {
                if (node.connectedIndexes[c] > nodeIndex)
                {
                    node.connectedIndexes[c]--;
                }
            }
            positionData.nodes[i] = node;
        }
    }
    private void DoNode(int nodeIndex)
    {
        Position.PositionNode positionNode = positionData.nodes[nodeIndex];
        Vector3 newPosition = positionNode.position;

        DoMidPoint(nodeIndex);

        Handles.color = Color.green;
        if (dragMode == DragMode.Project)
        {
            int controlId = GUIUtility.GetControlID(SurfaceHandle.hash, FocusType.Keyboard);
            if (GUIUtility.keyboardControl == controlId)
            {
                switch (e.type)
                {
                case EventType.MouseUp:
                    OnSelect(nodeIndex);
                    break;
                }
            }
            else if (HandleUtility.nearestControl == controlId)
            {
                switch (e.type)
                {
                case EventType.MouseDown:
                    if (e.button == 1 && selectedNodeIndex != nodeIndex && selectedNodeIndex != -1)
                    {
                        ChangeNodeConnection(nodeIndex);

                        e.Use();
                    }
                    break;
                }
            }
            newPosition = SurfaceHandle.Do(controlId, newPosition, nodeIndex == positionData.finishLineIndex ? 1.5f : .5f);
        }
        else
        {
            if (selectedNodeIndex == nodeIndex)
            {
                newPosition = Handles.PositionHandle(newPosition, Quaternion.identity);
            }
            else
            {
                float handleScale = HandleUtility.GetHandleSize(newPosition);
                if (Handles.Button(positionNode.position, Quaternion.identity, handleScale * .03f, handleScale * .05f, Handles.DotHandleCap))
                {
                    OnSelect(nodeIndex);
                }
            }
        }

        if (newPosition != positionNode.position)
        {
            EditorUtility.SetDirty(positionData);
            Undo.RecordObject(positionData, "Move Position");

            positionNode.position = newPosition;
        }

        positionData.nodes[nodeIndex] = positionNode;
    }