/// <summary>
        /// 1. draw spline
        /// 2. draw points
        /// 3. draw handles
        /// </summary>
        public void OnSceneGUI()
        {
            CatmullRomUniformBehaviour behaviour = (CatmullRomUniformBehaviour)target;
            CatmullRomUniform          spline    = (CatmullRomUniform)behaviour.Spline;
            Transform tr = behaviour.transform;

            DrawSpline(spline, tr);

            if (!ms_isMultiEdit)
            {
                DrawPoints(spline, tr);

                DrawHandles(spline, tr);

                // prevent de-selection by clicking
                EUtil.SceneViewPreventDeselecByClick(m_curPtIdx >= 0);

                // shortcut
                Event e = Event.current;
                switch (e.type)
                {
                case EventType.KeyUp:
                {
                    if (e.keyCode == KeyCode.X)
                    {
                        if (m_curPtIdx >= 0)
                        {
                            _DelPoint(spline);
                        }
                    }
                    else if (e.keyCode == KeyCode.I)
                    {
                        if (m_curPtIdx < 0)
                        {
                            m_curPtIdx = spline.PointCount - 1;
                        }
                        _AddPoint(spline);
                    }
                    else if (e.keyCode == KeyCode.C)
                    {
                        if (m_curPtIdx >= 0)
                        {
                            EUtil.SceneViewLookAt(tr.TransformPoint(spline[m_curPtIdx]), ms_lookAtDist);
                        }
                    }
                }
                break;
                }
            }
        }
        private void _OnUndoRedo()
        {
            CatmullRomUniformBehaviour behaviour = (CatmullRomUniformBehaviour)target;

            if (behaviour == null)
            {
                Undo.undoRedoPerformed -= _OnUndoRedo;
                return;
            }

            CatmullRomUniform spline = (CatmullRomUniform)behaviour.Spline;

            if (spline == null)
            {
                Undo.undoRedoPerformed -= _OnUndoRedo;
                return;
            }

            spline.SetDirty();
        }
        public override void OnInspectorGUI()
        {
            if (targets.Length > 1)
            {
                EditorGUILayout.HelpBox("Cannot edit multiple spline together", MessageType.Info, true);
                ms_isMultiEdit = true;
                return;
            }
            else
            {
                ms_isMultiEdit = false;
            }

            CatmullRomUniformBehaviour behaviour = (CatmullRomUniformBehaviour)target;
            CatmullRomUniform          spline    = (CatmullRomUniform)behaviour.Spline;

            GUILayout.Space(5f);
            EditorGUILayout.BeginHorizontal();
            {
                if (GUILayout.Button(new GUIContent("Add Point", "hotkey: I"), EditorStyles.toolbarButton))
                {
                    _AddPoint(spline);
                }
                if (GUILayout.Button(new GUIContent("Del Point", "hotkey: X"), EditorStyles.toolbarButton))
                {
                    _DelPoint(spline);
                }
                if (GUILayout.Button(spline.Cycle ? "Break Cycle" : "Make Cycle", EditorStyles.toolbarButton))
                {
                    _ToggleCycle(spline);
                }
            }
            EditorGUILayout.EndHorizontal();
            GUILayout.Space(5f);

            if (m_curPtIdx >= 0)
            {
                EditorGUILayout.BeginHorizontal();
                {
                    MUndo.RecordObject(this, "change current point");
                    GUILayout.Label("Current Point");
                    if (GUILayout.Button("<<"))
                    {
                        m_curPtIdx = Mathf.Max(0, m_curPtIdx - 1);
                    }

                    EditorGUI.BeginChangeCheck();
                    m_curPtIdx = EditorGUILayout.IntField(m_curPtIdx);
                    if (EditorGUI.EndChangeCheck())
                    {
                        m_curPtIdx = Mathf.Clamp(m_curPtIdx, 0, spline.PointCount);
                    }

                    GUILayout.Label(" / " + (spline.PointCount - 1));
                    if (GUILayout.Button(">>"))
                    {
                        m_curPtIdx = Mathf.Min(m_curPtIdx + 1, spline.PointCount - 1);
                    }
                }
                EditorGUILayout.EndHorizontal();

                MUndo.RecordObject(target, "modify control point");
                EUtil.PushLabelWidth(80f);
                spline[m_curPtIdx] = EUtil.DrawV3P(new GUIContent("Position"), spline[m_curPtIdx]);
                spline.SetTilt(m_curPtIdx, EditorGUILayout.FloatField("Tilt", spline.GetTilt(m_curPtIdx)));
                EUtil.PopLabelWidth();
            }

            ms_foldoutSettings = EditorGUILayout.Foldout(ms_foldoutSettings, "Settings");
            if (ms_foldoutSettings)
            {
                MUndo.RecordObject(this, "change setting");
                spline.Resolution = EditorGUILayout.IntField("Point/Seg", spline.Resolution);
                spline.TwistMtd   = (ETwistMethod)EditorGUILayout.EnumPopup(new GUIContent("Twist Method", "Decide how to calculate the base-up direction before applying tilt"), spline.TwistMtd);
                ms_drawArrow      = EditorGUILayout.Toggle("Draw Arrow", ms_drawArrow);
                ms_drawUp         = EditorGUILayout.Toggle("Draw Up", ms_drawUp);
                ms_arrowLineLen   = EditorGUILayout.FloatField("Arrow LineLen", ms_arrowLineLen);

                ms_drawPts = EditorGUILayout.Toggle("Draw points", ms_drawPts);
                ms_ptSize  = EditorGUILayout.FloatField("Point size", ms_ptSize);

                ms_lookAtDist = EditorGUILayout.FloatField(new GUIContent("LookAt dist", "the distance from camera to target point when camera in follow mode"), ms_lookAtDist);
            }

            ms_foldoutTSlider = EditorGUILayout.Foldout(ms_foldoutTSlider, "T slider");
            if (ms_foldoutTSlider)
            {
                EditorGUI.BeginChangeCheck();
                EUtil.PushLabelWidth(20f);
                m_tSlider = EditorGUILayout.Slider("T", m_tSlider, 0, 1f);
                EUtil.PopLabelWidth();
                if (EditorGUI.EndChangeCheck())
                {
                    //Transform tr = behaviour.transform;
                    EUtil.SceneViewLookAt(
                        behaviour.GetTransformedPosition(m_tSlider),
                        Quaternion.LookRotation(behaviour.GetTransformedTangent(m_tSlider), behaviour.GetTransformedUp(m_tSlider)),
                        ms_lookAtDist);
                }
            }

            if (GUI.changed)
            {
                EUtil.RepaintSceneView();
            }
        }