void OnCurveModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType type)
        {
            InspectorWindow.RepaintAllInspectors();
            if (state == null || state.rebuildGraph)
            {
                return;
            }

            //Force refresh of curve when modified by another editor.
            Repaint();

            if (state.previewMode == false)
            {
                return;
            }

            bool hasPlayable = m_PlayableLookup.GetPlayableFromAnimClip(clip, out Playable playable);

            // mark the timeline clip as dirty
            TimelineClip timelineClip = m_PlayableLookup.GetTimelineClipFromCurves(clip);

            if (timelineClip != null)
            {
                timelineClip.MarkDirty();
            }

            if (type == AnimationUtility.CurveModifiedType.CurveModified)
            {
                if (hasPlayable)
                {
                    playable.SetAnimatedProperties(clip);
                }

                // updates the duration of the graph without rebuilding
                AnimationUtility.SyncEditorCurves(clip); // deleted keys are not synced when this is sent out, so duration could be incorrect
                state.UpdateRootPlayableDuration(state.editSequence.duration);

                bool             isRecording    = TimelineRecording.IsRecordingAnimationTrack;
                PlayableDirector masterDirector = TimelineEditor.masterDirector;
                bool             isGraphValid   = masterDirector != null && masterDirector.playableGraph.IsValid();

                // don't evaluate if this is caused by recording on an animation track, the extra evaluation can cause hiccups
                // Prevent graphs to be resurrected  by a changed clip.
                if (!isRecording && isGraphValid)
                {
                    state.Evaluate();
                }
            }
            else if (EditorUtility.IsDirty(clip)) // curve added/removed, or clip added/removed
            {
                state.rebuildGraph |= timelineClip != null || hasPlayable;
            }
        }
        void OnCurveModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType type)
        {
            InspectorWindow.RepaintAllInspectors();
            if (state == null || state.rebuildGraph)
            {
                return;
            }

            //Force refresh of curve when modified by another editor.
            Repaint();

            if (state.previewMode == false)
            {
                return;
            }

            if (type == AnimationUtility.CurveModifiedType.CurveModified)
            {
                Playable playable;
                if (m_PlayableLookup.GetPlayableFromAnimClip(clip, out playable))
                {
                    playable.SetAnimatedProperties(clip);
                }

                // mark the timeline clip as dirty
                TimelineClip timelineClip = m_PlayableLookup.GetTimelineClipFromCurves(clip);
                if (timelineClip != null)
                {
                    timelineClip.MarkDirty();
                }

                // updates the duration of the graph without rebuilding
                AnimationUtility.SyncEditorCurves(clip); // deleted keys are not synced when this is sent out, so duration could be incorrect
                state.UpdateRootPlayableDuration(state.editSequence.duration);

                // don't evaluate if this is caused by recording on an animation track, the extra evaluation can cause hiccups
                if (!TimelineRecording.IsRecordingAnimationTrack)
                {
                    state.Evaluate();
                }
            }
            else // curve added/removed, or clip added/removed
            {
                state.rebuildGraph = true;
            }
        }