public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            BezierUtils.DrawSeparator();
            EditorGUI.BeginChangeCheck();
            simulateInEditor = GUILayout.Toggle(simulateInEditor, "Simulate In Editor", GUI.skin.button);
            if (EditorGUI.EndChangeCheck())
            {
                if (simulateInEditor)
                {
                    StartSimulateInEditor();
                }
                else
                {
                    StopSimulateInEditor();
                }
            }
        }
        public override void OnInspectorGUI()
        {
            if (CheckCommands())
            {
                GUIUtility.ExitGUI();
            }

            BezierUtils.DrawSplineInspectorGUI(allSplines);

            EditorGUILayout.Space();
            BezierUtils.DrawSeparator();

            GUILayout.BeginHorizontal();

            if (GUILayout.Button("<-", GUILayout.Width(45)))
            {
                Object[] newSelection = new Object[pointCount];
                for (int i = 0, index = 0; i < selection.Length; i++)
                {
                    BezierSpline  spline = selection[i].spline;
                    BezierPoint[] points = selection[i].points;

                    if (spline)
                    {
                        for (int j = 0; j < points.Length; j++)
                        {
                            int prevIndex = points[j].Internal_Index - 1;
                            if (prevIndex < 0)
                            {
                                prevIndex = spline.Count - 1;
                            }

                            newSelection[index++] = spline[prevIndex].gameObject;
                        }
                    }
                    else
                    {
                        for (int j = 0; j < points.Length; j++)
                        {
                            newSelection[index++] = points[j].gameObject;
                        }
                    }
                }

                Selection.objects = newSelection;
                GUIUtility.ExitGUI();
            }

            string pointIndex   = (pointCount == 1 && selection[0].spline) ? (allPoints[0].Internal_Index + 1).ToString() : "-";
            string splineLength = (selection.Length == 1 && selection[0].spline) ? selection[0].spline.Count.ToString() : "-";

            GUILayout.Box("Selected Point: " + pointIndex + " / " + splineLength, GUILayout.ExpandWidth(true));

            if (GUILayout.Button("->", GUILayout.Width(45)))
            {
                Object[] newSelection = new Object[pointCount];
                for (int i = 0, index = 0; i < selection.Length; i++)
                {
                    BezierSpline  spline = selection[i].spline;
                    BezierPoint[] points = selection[i].points;

                    if (spline)
                    {
                        for (int j = 0; j < points.Length; j++)
                        {
                            int nextIndex = points[j].Internal_Index + 1;
                            if (nextIndex >= spline.Count)
                            {
                                nextIndex = 0;
                            }

                            newSelection[index++] = spline[nextIndex].gameObject;
                        }
                    }
                    else
                    {
                        for (int j = 0; j < points.Length; j++)
                        {
                            newSelection[index++] = points[j].gameObject;
                        }
                    }
                }

                Selection.objects = newSelection;
                GUIUtility.ExitGUI();
            }

            GUILayout.EndHorizontal();

            EditorGUILayout.Space();

            if (GUILayout.Button("Decrement Point's Index"))
            {
                Undo.IncrementCurrentGroup();

                for (int i = 0; i < selection.Length; i++)
                {
                    BezierSpline spline = selection[i].spline;
                    if (spline)
                    {
                        selection[i].SortPoints(true);

                        BezierPoint[] points     = selection[i].points;
                        int[]         newIndices = new int[points.Length];
                        for (int j = 0; j < points.Length; j++)
                        {
                            int index    = points[j].Internal_Index;
                            int newIndex = index - 1;
                            if (newIndex < 0)
                            {
                                newIndex = spline.Count - 1;
                            }

                            newIndices[j] = newIndex;
                        }

                        for (int j = 0; j < points.Length; j++)
                        {
                            Undo.RegisterCompleteObjectUndo(points[j].transform.parent, "Change point index");
                            spline.Internal_MovePoint(points[j].Internal_Index, newIndices[j], "Change point index");
                        }

                        selection[i].SortPoints(true);
                    }
                }

                SceneView.RepaintAll();
            }

            if (GUILayout.Button("Increment Point's Index"))
            {
                Undo.IncrementCurrentGroup();

                for (int i = 0; i < selection.Length; i++)
                {
                    BezierSpline spline = selection[i].spline;
                    if (spline)
                    {
                        selection[i].SortPoints(false);

                        BezierPoint[] points     = selection[i].points;
                        int[]         newIndices = new int[points.Length];
                        for (int j = 0; j < points.Length; j++)
                        {
                            int index    = points[j].Internal_Index;
                            int newIndex = index + 1;
                            if (newIndex >= spline.Count)
                            {
                                newIndex = 0;
                            }

                            newIndices[j] = newIndex;
                        }

                        for (int j = 0; j < points.Length; j++)
                        {
                            Undo.RegisterCompleteObjectUndo(points[j].transform.parent, "Change point index");
                            spline.Internal_MovePoint(points[j].Internal_Index, newIndices[j], "Change point index");
                        }

                        selection[i].SortPoints(true);
                    }
                }

                SceneView.RepaintAll();
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("Insert Point Before"))
            {
                InsertNewPoints(false);
            }

            if (GUILayout.Button("Insert Point After"))
            {
                InsertNewPoints(true);
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("Duplicate Point"))
            {
                DuplicateSelectedPoints();
            }

            EditorGUILayout.Space();

            bool hasMultipleDifferentValues = false;

            BezierPoint.HandleMode handleMode = allPoints[0].handleMode;
            for (int i = 1; i < allPoints.Length; i++)
            {
                if (allPoints[i].handleMode != handleMode)
                {
                    hasMultipleDifferentValues = true;
                    break;
                }
            }

            EditorGUI.showMixedValue = hasMultipleDifferentValues;
            EditorGUI.BeginChangeCheck();
            handleMode = (BezierPoint.HandleMode)EditorGUILayout.EnumPopup("Handle Mode", handleMode);
            if (EditorGUI.EndChangeCheck())
            {
                for (int i = 0; i < allPoints.Length; i++)
                {
                    Undo.RecordObject(allPoints[i], "Change Point Handle Mode");
                    allPoints[i].handleMode = handleMode;
                }

                SceneView.RepaintAll();
            }

            EditorGUILayout.Space();

            hasMultipleDifferentValues = false;
            Vector3 position = allPoints[0].precedingControlPointLocalPosition;

            for (int i = 1; i < allPoints.Length; i++)
            {
                if (allPoints[i].precedingControlPointLocalPosition != position)
                {
                    hasMultipleDifferentValues = true;
                    break;
                }
            }

            EditorGUI.showMixedValue = hasMultipleDifferentValues;
            EditorGUI.BeginChangeCheck();
            position = EditorGUILayout.Vector3Field("Preceding Control Point Local Position", position);
            if (EditorGUI.EndChangeCheck())
            {
                for (int i = 0; i < allPoints.Length; i++)
                {
                    Undo.RecordObject(allPoints[i], "Change Point Position");
                    allPoints[i].precedingControlPointLocalPosition = position;
                }

                SceneView.RepaintAll();
            }

            hasMultipleDifferentValues = false;
            position = allPoints[0].followingControlPointLocalPosition;
            for (int i = 1; i < allPoints.Length; i++)
            {
                if (allPoints[i].followingControlPointLocalPosition != position)
                {
                    hasMultipleDifferentValues = true;
                    break;
                }
            }

            EditorGUI.showMixedValue = hasMultipleDifferentValues;
            EditorGUI.BeginChangeCheck();
            position = EditorGUILayout.Vector3Field("Following Control Point Local Position", position);
            if (EditorGUI.EndChangeCheck())
            {
                for (int i = 0; i < allPoints.Length; i++)
                {
                    Undo.RecordObject(allPoints[i], "Change Point Position");
                    allPoints[i].followingControlPointLocalPosition = position;
                }

                SceneView.RepaintAll();
            }

            bool showControlPointDistanceWarning = false;

            for (int i = 0; i < allPoints.Length; i++)
            {
                BezierPoint point = allPoints[i];
                if ((point.position - point.precedingControlPointPosition).sqrMagnitude < CONTROL_POINTS_MINIMUM_SAFE_DISTANCE_SQR ||
                    (point.position - point.followingControlPointPosition).sqrMagnitude < CONTROL_POINTS_MINIMUM_SAFE_DISTANCE_SQR)
                {
                    showControlPointDistanceWarning = true;
                    break;
                }
            }

            if (showControlPointDistanceWarning)
            {
                EditorGUILayout.HelpBox("Positions of control point(s) shouldn't be very close to (0,0,0), this might result in unpredictable behaviour while moving along the spline with constant speed.", MessageType.Warning);
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("Swap Control Points"))
            {
                for (int i = 0; i < allPoints.Length; i++)
                {
                    Undo.RecordObject(allPoints[i], "Swap Control Points");
                    Vector3 temp = allPoints[i].precedingControlPointLocalPosition;
                    allPoints[i].precedingControlPointLocalPosition = allPoints[i].followingControlPointLocalPosition;
                    allPoints[i].followingControlPointLocalPosition = temp;
                }

                SceneView.RepaintAll();
            }

            EditorGUILayout.Space();
            BezierUtils.DrawSeparator();

            hasMultipleDifferentValues = false;
            BezierPoint.ExtraData extraData = allPoints[0].extraData;
            for (int i = 1; i < allPoints.Length; i++)
            {
                if (allPoints[i].extraData != extraData)
                {
                    hasMultipleDifferentValues = true;
                    break;
                }
            }

            GUILayout.BeginHorizontal();
            EditorGUI.showMixedValue = hasMultipleDifferentValues;
            EditorGUI.BeginChangeCheck();
            Rect extraDataRect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight);               // When using GUILayout, button isn't vertically centered

            extraDataRect.width -= 65f;
            extraData            = EditorGUI.Vector4Field(extraDataRect, "Extra Data", extraData);
            extraDataRect.x     += extraDataRect.width + 5f;
            extraDataRect.width  = 30f;
            if (GUI.Button(extraDataRect, EXTRA_DATA_SET_AS_CAMERA))
            {
                extraData = SceneView.lastActiveSceneView.camera.transform.rotation;
            }
            if (EditorGUI.EndChangeCheck())
            {
                for (int i = 0; i < allPoints.Length; i++)
                {
                    Undo.RecordObject(allPoints[i], "Change Extra Data");
                    allPoints[i].extraData = extraData;
                }

                SceneView.RepaintAll();
            }

            EditorGUI.showMixedValue = false;

            extraDataRect.x += 30f;
            EditorGUI.BeginChangeCheck();
            m_visualizeExtraDataAsFrustum = GUI.Toggle(extraDataRect, m_visualizeExtraDataAsFrustum, EXTRA_DATA_VIEW_AS_FRUSTUM, GUI.skin.button);
            if (EditorGUI.EndChangeCheck())
            {
                VisualizeExtraDataAsFrustum = m_visualizeExtraDataAsFrustum;
                SceneView.RepaintAll();
            }

            GUILayout.EndHorizontal();

            BezierUtils.DrawSeparator();
            EditorGUILayout.Space();

            Color c = GUI.color;

            GUI.color = RESET_POINT_BUTTON_COLOR;

            if (GUILayout.Button("Reset Point"))
            {
                for (int i = 0; i < allPoints.Length; i++)
                {
                    Undo.RecordObject(allPoints[i].transform, "Reset Point");
                    Undo.RecordObject(allPoints[i], "Reset Point");

                    allPoints[i].Reset();
                }

                SceneView.RepaintAll();
            }

            EditorGUILayout.Space();

            GUI.color = REMOVE_POINT_BUTTON_COLOR;

            if (GUILayout.Button("Remove Point"))
            {
                RemoveSelectedPoints();
                GUIUtility.ExitGUI();
            }

            GUI.color = c;

            for (int i = 0; i < allSplines.Length; i++)
            {
                allSplines[i].Internal_CheckDirty();
            }
        }