public float GetSpeedMod(float a_startTime, MotionTimingPresets a_presets, IMxMAnim a_mxmAnim)
        {
            MotionPreset motionDef = null;

            if (a_presets != null)
                motionDef = a_presets.GetDefenition(MotionPresetId);

            if (motionDef == null || !UsePresets) //Raw
            {
                switch (ModType)
                {
                    case EMotionModType.PlaybackSpeed:
                        {
                            return 1f / RawModValue;
                        }
                    case EMotionModType.Duration:
                        {
                            return RawModValue / ((EndTime - a_startTime));
                        }
                    case EMotionModType.LinearSpeed:
                        {
                            if (a_mxmAnim != null)
                            {
                                float averageSpeedOriginal = a_mxmAnim.GetAverageRootSpeed(a_startTime, EndTime);

                                return averageSpeedOriginal / RawModValue;
                            }

                            return 1f / RawModValue;
                        }
                }
            }
            else //from Database
            {
                switch (motionDef.MotionType)
                {
                    case EMotionModType.PlaybackSpeed:
                        {
                            return 1f / motionDef.MotionTiming;
                        }
                    case EMotionModType.Duration:
                        {
                            return motionDef.MotionTiming / (EndTime - a_startTime);
                        }
                    case EMotionModType.LinearSpeed:
                        {
                            if (a_mxmAnim != null)
                            {
                                float averageSpeedOriginal = a_mxmAnim.GetAverageRootSpeed(a_startTime, EndTime);

                                return averageSpeedOriginal / motionDef.MotionTiming;
                            }

                            return 1f / motionDef.MotionTiming;
                        }
                }
            }
            return RawModValue;
        }
        //============================================================================================
        /**
        *  @brief 
        *         
        *********************************************************************************************/
        public MotionModifyData(MotionModifyData a_copy, IMxMAnim a_targetMxMAnim)
        {
            m_targetMxMAnim = a_targetMxMAnim;

            MotionSections = new List<MotionSection>();
            foreach(MotionSection motionSection in a_copy.MotionSections)
            {
                MotionSections.Add(new MotionSection(motionSection));
            }
        }
        //============================================================================================
        /**
        *  @brief 
        *         
        *********************************************************************************************/
        public void OnEnable(IMxMAnim m_targetMxMAnim)
        {
            if (MotionSections == null)
                MotionSections = new List<MotionSection>();

            if (m_targetMxMAnim == null)
                return;

            AnimationClip primaryClip = m_targetMxMAnim.TargetClip;

            if (MotionSections.Count == 0 && m_targetMxMAnim != null && primaryClip != null)
            {
                MotionSections.Add(new MotionSection(0, 0, 0, primaryClip.length));
            }
        }
        //============================================================================================

        /**
         *  @brief Copy constructor
         *
         *********************************************************************************************/
        public void DrawEvent(Rect _trackRect, float _zoom, MxMTaggingWindow _taggingWindow, IMxMAnim a_mxmAnim)
        {
            Texture markerIcon = EditorGUIUtility.IconContent("Animation.EventMarker").image;

            if (m_selected)
            {
                Handles.BeginGUI();
                Handles.color = Color.green;

                Vector3 start = new Vector3(EventTime * 75f * _zoom - (markerIcon.width / 2f),
                                            _trackRect.y + markerIcon.height / 2f, 0f);
                Vector3 end  = new Vector3(start.x - Actions[0] * 75f * _zoom + markerIcon.width / 2f, start.y, 0f);
                Vector3 up   = new Vector3(end.x, end.y - markerIcon.height / 4f);
                Vector3 down = new Vector3(up.x, up.y + markerIcon.height / 2f);

                Handles.DrawLine(start, end);
                Handles.DrawLine(up, down);

                start = end;
                end   = new Vector3(start.x - Windup * 75f * _zoom, start.y, 0f);
                up.x  = down.x = end.x;

                Handles.color = Color.blue;
                Handles.DrawLine(start, end);
                Handles.DrawLine(up, down);

                start = new Vector3(EventTime * 75f * _zoom + (markerIcon.width / 2f),
                                    _trackRect.y + markerIcon.height / 2f, 0f);

                Handles.color = Color.green;
                for (int i = 1; i < Actions.Count; ++i)
                {
                    float markerWidth = 0;

                    if (i == 1)
                    {
                        markerWidth = markerIcon.width / 2f;
                    }

                    end  = new Vector3(start.x + Actions[i] * 75f * _zoom - markerWidth, start.y, 0f);
                    up.x = down.x = end.x;

                    Handles.DrawLine(start, end);
                    Handles.DrawLine(up, down);

                    //Draw a circle maybe

                    start = end;
                }

                end  = new Vector3(start.x + FollowThrough * 75f * _zoom - markerIcon.width / 2f, start.y, 0f);
                up.x = down.x = end.x;

                Handles.color = Color.red;
                Handles.DrawLine(start, end);
                Handles.DrawLine(up, down);

                start = end;
                end   = new Vector3(start.x + Recovery * 75f * _zoom, start.y, 0f);
                up.x  = down.x = end.x;

                Handles.color = Color.yellow;
                Handles.DrawLine(start, end);
                Handles.DrawLine(up, down);

                Handles.EndGUI();
            }

            Rect markerRect = new Rect(EventTime * 75f * _zoom - (markerIcon.width / 2f), _trackRect.y,
                                       markerIcon.width, markerIcon.height);

            GUI.DrawTexture(markerRect, markerIcon);

            if (m_selected)
            {
                GUI.DrawTexture(markerRect, EditorUtil.EditorFunctions.GetHighlightTex());
            }

            Event evt = Event.current;

            markerRect.x     -= 3f;
            markerRect.height = _trackRect.height;
            markerRect.width += 6f;

            if (evt.isMouse)
            {
                if (evt.button == 0)
                {
                    switch (evt.type)
                    {
                    case EventType.MouseDown:
                    {
                        if (markerRect.Contains(evt.mousePosition))
                        {
                            m_selected = true;
                            m_dragging = true;
                            _taggingWindow.SelectEvent(this, EventTime);
                            evt.Use();
                        }
                    }
                    break;

                    case EventType.MouseUp:
                    {
                        m_dragging = false;
                    }
                    break;

                    case EventType.MouseDrag:
                    {
                        if (m_dragging && m_selected)
                        {
                            float desiredValueDelta = ((evt.delta.x / _zoom)) / 75f;

                            EventTime += desiredValueDelta;

                            EventTime = Mathf.Clamp(EventTime, 0f,
                                                    _taggingWindow.TargetClip.length);

                            _taggingWindow.Modified(EventTime);

                            evt.Use();
                        }
                    }
                    break;
                    }
                }
                else if (evt.button == 1)
                {
                    //Begin Context menu
                    GenericMenu menu = new GenericMenu();

                    menu.AddItem(new GUIContent("Delete"), false, a_mxmAnim.OnDeleteEventMarker, this);
                    menu.ShowAsContext();
                }
            }
        }
 public void CopyTagsAndEvents(IMxMAnim a_target, bool a_mirrored) { }
        public void CopyTagsAndEvents(IMxMAnim a_target, bool a_mirrored)
        {
            //Copy Require tag tracks
            List<TagTrack> targetTagTracks = a_target.AnimTagTracks;
            if (targetTagTracks != null)
            {
                TagTracks = new List<TagTrack>(targetTagTracks.Count + 1);
                foreach (TagTrack track in targetTagTracks)
                {
                    if (track != null)
                    {
                        TagTracks.Add(new TagTrack(track));
                    }
                }
            }

            //Copy Favour tag tracks
            List<TagTrack> targetFavourTracks = a_target.AnimFavourTagTracks;
            if (FavourTagTracks != null)
            {
                FavourTagTracks = new List<TagTrack>(targetFavourTracks.Count + 1);
                foreach (TagTrack track in targetFavourTracks)
                {
                    if (track != null)
                        FavourTagTracks.Add(new TagTrack(track));
                }
            }

            //Copy User Tags
            List<TagTrackBase> userTagTracks = a_target.UserTagTracks;
            if (userTagTracks != null)
            {
                UserBoolTracks = new List<TagTrackBase>(userTagTracks.Count + 1);
                foreach (TagTrackBase track in userTagTracks)
                {
                    if (track != null)
                        UserBoolTracks.Add(track);
                }
            }

            //Copy Utility Tags
            List<TagTrackBase> utilityTagTracks = a_target.GenericTagTracks;

            if (utilityTagTracks != null)
            {
                if (a_mirrored)
                {
                    if (utilityTagTracks.Count > 0)
                    {
                        RightFootStepTrack = new FootStepTagTrack(utilityTagTracks[0] as FootStepTagTrack);
                        RightFootStepTrack.Name = "Footstep Right";
                    }

                    if (utilityTagTracks.Count > 1)
                    {
                        LeftFootStepTrack = new FootStepTagTrack(utilityTagTracks[1] as FootStepTagTrack);
                        LeftFootStepTrack.Name = "Footstep Left";
                    }
                }
                else
                {
                    if (utilityTagTracks.Count > 0)
                        LeftFootStepTrack = new FootStepTagTrack(utilityTagTracks[0] as FootStepTagTrack);

                    if (utilityTagTracks.Count > 1)
                        RightFootStepTrack = new FootStepTagTrack(utilityTagTracks[1] as FootStepTagTrack);
                }

                if (utilityTagTracks.Count > 2)
                    WarpPositionTrack = new TagTrackBase(utilityTagTracks[2]);

                if (utilityTagTracks.Count > 3)
                    WarpRotationTrack = new TagTrackBase(utilityTagTracks[3]);

                if (utilityTagTracks.Count > 4)
                    EnableRootMotionTrack = new TagTrackBase(utilityTagTracks[4]);

                if (utilityTagTracks.Count > 5)
                    PoseFavourTrack = new FloatTagTrack(utilityTagTracks[5] as FloatTagTrack);

                if (utilityTagTracks.Count > 6)
                    WarpTrajLatTrack = new TagTrackBase(utilityTagTracks[6]);

                if (utilityTagTracks.Count > 7)
                    WarpTrajLongTrack = new TagTrackBase(utilityTagTracks[7]);
            }
        }
Beispiel #7
0
        public static void DetectFootsteps(IMxMAnim a_mxmAnim, GameObject a_targetModel, MxMPreProcessData a_preProcessData,
                                           AnimationModule a_animModule, float a_groundingThreshold, float a_minSpacing, float a_minDuration, float a_maxFootSpeed)
        {
            if ((a_preProcessData == null && a_animModule == null) || a_mxmAnim == null)
            {
                return;
            }

            AnimationClip targetClip = a_mxmAnim.TargetClip;

            if (targetClip == null)
            {
                return;
            }

            if (a_targetModel == null)
            {
                if (a_preProcessData == null)
                {
                    a_targetModel = a_preProcessData.Prefab;
                }
                else if (a_animModule == null)
                {
                    a_targetModel = a_animModule.Prefab;
                }

                if (a_targetModel == null)
                {
                    Debug.LogError("MxM Footstep Detection - The MxMAnim you are trying to detect footsteps for has no target" +
                                   "model. This could occur if your target model is not set on the pre-processor, or your animation module" +
                                   "doesn't have a MotionMatch Config referenced.");
                    return;
                }
            }

            List <FootStepData> leftFootStepData      = new List <FootStepData>();
            List <Vector2>      leftFootStepPositions = new List <Vector2>();

            List <FootStepData> rightFootStepData      = new List <FootStepData>();
            List <Vector2>      rightFootStepPositions = new List <Vector2>();

            GameObject model = GameObject.Instantiate(a_targetModel);

            model.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);

            Animator animator = model.GetComponent <Animator>();

            if (animator == null)
            {
                animator = model.AddComponent <Animator>();
            }

            animator.applyRootMotion = true;
            animator.cullingMode     = AnimatorCullingMode.AlwaysAnimate;

            Transform leftToeJoint  = null;
            Transform rightToeJoint = null;

            bool getBonesByName = false;

            if (a_preProcessData != null)
            {
                getBonesByName = a_preProcessData.GetBonesByName;
            }
            else if (a_animModule != null)
            {
                getBonesByName = a_animModule.GetBonesByName;
            }

            if (!getBonesByName)
            {
                leftToeJoint  = animator.GetBoneTransform(HumanBodyBones.LeftToes);
                rightToeJoint = animator.GetBoneTransform(HumanBodyBones.RightToes);
            }
            else
            {
                //Get generic joints?
                Debug.LogWarning("Automatic detection of footsteps is not currently supported for generic rigs");
                return;
            }

            PlayableGraph playableGraph = PlayableGraph.Create();

            playableGraph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
            var playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", animator);
            var animationMixer = AnimationMixerPlayable.Create(playableGraph, 1, true);

            playableOutput.SetSourcePlayable(animationMixer);

            var clipPlayable = AnimationClipPlayable.Create(playableGraph, targetClip);

            animationMixer.ConnectInput(0, clipPlayable, 0);
            animationMixer.SetInputWeight(0, 1f);

            clipPlayable.SetTime(0.0);
            clipPlayable.SetTime(0.0);
            playableGraph.Evaluate(0f);
            model.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);

            const float SixtyHz = 1f / 60f;

            float leftFootLowestY  = leftToeJoint.position.y;
            float rightFootLowestY = rightToeJoint.position.y;

            for (float time = 0f; time <= targetClip.length; time += SixtyHz)
            {
                float leftFootY  = leftToeJoint.position.y;
                float rightFootY = rightToeJoint.position.y;

                if (leftFootY < leftFootLowestY)
                {
                    leftFootLowestY = leftFootY;
                }

                if (rightFootY < rightFootLowestY)
                {
                    rightFootLowestY = rightFootY;
                }

                playableGraph.Evaluate(SixtyHz);
            }

            clipPlayable.SetTime(0.0);
            clipPlayable.SetTime(0.0);
            playableGraph.Evaluate(0f);
            bool leftFootGrounded  = false;
            bool rightFootGrounded = false;

            float leftStepStartTime = 0f;
            float leftStepEndTime   = 0f;

            float rightStepStartTime = 0f;
            float rightStepEndTime   = 0f;

            model.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);

            float leftToeSpeed  = 0f;
            float rightToeSpeed = 0f;

            Vector3 leftToeLastPos  = leftToeJoint.position;
            Vector3 rightToeLastPos = rightToeJoint.position;

            for (float time = 0f; time <= targetClip.length; time += SixtyHz)
            {
                //Velocities
                leftToeSpeed    = Vector3.Distance(leftToeLastPos, leftToeJoint.position) / SixtyHz;
                rightToeSpeed   = Vector3.Distance(rightToeLastPos, rightToeJoint.position) / SixtyHz;
                leftToeLastPos  = leftToeJoint.position;
                rightToeLastPos = rightToeJoint.position;

                //LEFT FOOT
                float leftFootDif = leftToeJoint.position.y - leftFootLowestY;
                if (leftFootDif < a_groundingThreshold && leftToeSpeed < a_maxFootSpeed)
                {
                    if (leftFootGrounded == false)
                    {
                        leftStepStartTime = time;
                    }

                    leftFootGrounded = true;
                }
                else
                {
                    if (leftFootGrounded == true)
                    {
                        leftStepEndTime = time;

                        leftFootStepData.Add(new FootStepData());
                        leftFootStepPositions.Add(new Vector2(leftStepStartTime, leftStepEndTime));
                    }

                    leftFootGrounded = false;
                }

                //RIGHT FOOT
                float rightFootDif = rightToeJoint.position.y - rightFootLowestY;

                if (rightFootDif < a_groundingThreshold && rightToeSpeed < a_maxFootSpeed)
                {
                    if (rightFootGrounded == false)
                    {
                        rightStepStartTime = time;
                    }

                    rightFootGrounded = true;
                }
                else
                {
                    if (rightFootGrounded == true)
                    {
                        rightStepEndTime = time;

                        rightFootStepData.Add(new FootStepData());
                        rightFootStepPositions.Add(new Vector2(rightStepStartTime, rightStepEndTime));
                    }

                    rightFootGrounded = false;
                }

                playableGraph.Evaluate(SixtyHz);
            }

            List <TagTrackBase> genericTagTracks = a_mxmAnim.GenericTagTracks;
            FootStepTagTrack    leftFootTagTrack = genericTagTracks[0] as FootStepTagTrack;

            leftFootTagTrack.RemoveAllTags();

            for (int i = 0; i < leftFootStepPositions.Count; ++i)
            {
                Vector2 footStepPosition = leftFootStepPositions[i];

                //Combine footsteps that are too close to be real (This should be recursive)
                if (i + 1 < leftFootStepPositions.Count)
                {
                    for (int k = i + 1; k < leftFootStepPositions.Count; ++k)
                    {
                        Vector2 nextFootStepPos = leftFootStepPositions[k];

                        if (nextFootStepPos.x - footStepPosition.y < a_minSpacing)
                        {
                            footStepPosition.y = nextFootStepPos.y;
                            leftFootStepPositions.RemoveAt(k);
                            --k;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                //Ignore footsteps that are too short to be real
                if (footStepPosition.y - footStepPosition.x < a_minDuration)
                {
                    continue;
                }

                leftFootTagTrack.AddTag(footStepPosition.x, footStepPosition.y);
            }

            FootStepTagTrack rightFootTagTrack = genericTagTracks[1] as FootStepTagTrack;

            rightFootTagTrack.RemoveAllTags();

            for (int i = 0; i < rightFootStepPositions.Count; ++i)
            {
                Vector3 footStepPosition = rightFootStepPositions[i];

                //Combine footsteps that are too close to be real (This should be recursive)
                if (i + 1 < rightFootStepPositions.Count)
                {
                    for (int k = i + 1; k < rightFootStepPositions.Count; ++k)
                    {
                        Vector2 nextFootStepPos = rightFootStepPositions[k];

                        if (nextFootStepPos.x - footStepPosition.y < a_minSpacing)
                        {
                            footStepPosition.y = nextFootStepPos.y;
                            rightFootStepPositions.RemoveAt(k);
                            --k;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                //Ignore footsteps that are too short to be real
                if (footStepPosition.y - footStepPosition.x < a_minDuration)
                {
                    continue;
                }

                rightFootTagTrack.AddTag(footStepPosition.x, footStepPosition.y);
            }

            GameObject.DestroyImmediate(model);
        }
        //============================================================================================
        /**
        *  @brief 
        *         
        *********************************************************************************************/
        public void DrawSections(ref Rect a_trackRect, ref Rect a_timelineRect, float a_zoom, MxMTaggingWindow a_taggingWindow)
        {
            Texture markerIcon = EditorGUIUtility.IconContent("Animation.EventMarker").image;

            Rect markerRect;

            Event evt = Event.current;

            float lastTime = 0f;

            MotionTimingPresets motionTimingPresets = null;

            if (a_taggingWindow != null)
                m_targetMxMAnim = a_taggingWindow.TargetMxMAnim;

            var targetPreProcess = m_targetMxMAnim.TargetPreProcess;

            if (m_targetMxMAnim != null && targetPreProcess != null)
            {
                motionTimingPresets = targetPreProcess.MotionTimingPresets;
            }

            string[] defenitionNames = null;
            if(motionTimingPresets != null)
            {
                defenitionNames = motionTimingPresets.GetDefenitionNames();
            }

           float maxSpeedVariance = 0.5f;

            //Determine max variance
            for (int i = 0; i < MotionSections.Count; ++i)
            {
                MotionSection curSection = MotionSections[i];

                float speedMod = 1f;
                speedMod = curSection.GetSpeedMod(lastTime, motionTimingPresets, m_targetMxMAnim);

                float speedVariance = 0f;
                if (speedMod > 1f)
                    speedVariance = (speedMod / 1f) - 1f;
                else if (speedMod < 1f)
                    speedVariance = (1f / speedMod) - 1f;

                if (speedVariance > maxSpeedVariance)
                    maxSpeedVariance = speedVariance;

                lastTime = curSection.EndTime;
            }

            lastTime = 0f;
            for (int i = 0; i < MotionSections.Count; ++i)
            {
                MotionSection curSection = MotionSections[i];

                markerRect = new Rect(curSection.EndTime * 75f * a_zoom - (markerIcon.width / 2f), a_trackRect.y,
                     markerIcon.width, markerIcon.height);

                Vector3 start = new Vector3(markerRect.x + markerRect.width / 2f,
                                                markerRect.y + markerRect.height);
                Vector3 end = new Vector3(start.x, a_timelineRect.height);

                if (i != MotionSections.Count - 1)
                {
                    GUI.DrawTexture(markerRect, markerIcon);

                    Handles.color = Color.black;
                    Handles.DrawLine(start, end);

                    if (curSection.Selected)
                        GUI.DrawTexture(markerRect, EditorUtil.EditorFunctions.GetHighlightTex());


                    markerRect.x -= 3f;
                    markerRect.height = a_trackRect.height;
                    markerRect.width += 6f;

                    if (evt.isMouse && evt.button == 0)
                    {
                        switch (evt.type)
                        {
                            case EventType.MouseDown:
                                {
                                    if (markerRect.Contains(evt.mousePosition))
                                    {
                                        curSection.Selected = true;
                                        curSection.Dragging = true;
                                        a_taggingWindow.SelectSection(curSection, curSection.EndTime);
                                    }

                                }
                                break;
                            case EventType.MouseUp:
                                {
                                    curSection.Dragging = false;
                                }
                                break;
                            case EventType.MouseDrag:
                                {
                                    if (curSection.Dragging && curSection.Selected)
                                    {
                                        float desiredValueDelta = ((evt.delta.x / a_zoom)) / 75f;

                                        curSection.EndTime += desiredValueDelta;

                                        curSection.EndTime = Mathf.Clamp(curSection.EndTime, 0f,
                                            a_taggingWindow.TargetClip.length);
                                        a_taggingWindow.Modified(curSection.EndTime);
                                    }
                                }
                                break;
                        }
                    }
                }


                float speedMod = 1f;
                speedMod = curSection.GetSpeedMod(lastTime, motionTimingPresets, m_targetMxMAnim);

                float speedVariance = 0f;
                if (speedMod > 1f)
                {
                    speedVariance = (speedMod / 1f) - 1f;
                }
                else if (speedMod < 1f)
                {
                    speedVariance = (1f / speedMod) - 1f;
                }

                float heightRatio = speedVariance / maxSpeedVariance;

                if (speedMod < 1f)
                    heightRatio *= -1;

                if (maxSpeedVariance < 0.001f)
                    heightRatio = 0f;

                //Draw Baseline
                end = new Vector3(curSection.EndTime * 75f * a_zoom, a_timelineRect.height / 2f + 9f);
                start = new Vector3(lastTime * 75f * a_zoom, end.y);

                Handles.color = new Color(0f, 0f, 0f, 0.5f);
                Handles.DrawLine(start, end);

                //Draw limit line
                Handles.color = new Color(0f, 0f, 0f, 0.3f);
                if (speedMod > 1f + Mathf.Epsilon)
                {
                    end.y = a_timelineRect.height / 2f + (a_timelineRect.height / 2f - 44f) + 9f;
                    start.y = end.y;

                    Handles.DrawLine(start, end);
                }
                else
                {

                    //Draw limit line
                    end.y = a_timelineRect.height / 2f - (a_timelineRect.height / 2f - 44f) + 9f;
                    start.y = end.y;

                    Handles.DrawLine(start, end);
                }

                //Draw Green Line
                end.y = a_timelineRect.height / 2f + heightRatio * (a_timelineRect.height / 2f - 44f) + 9f;
                start.y = end.y;

                Handles.color = Color.green;
                Handles.DrawLine(start, end);

                float invertedSpeedMod = 1f / speedMod;
                string speedString = invertedSpeedMod.ToString("F2");

                speedString += "x";

                float width = GUI.skin.label.CalcSize(new GUIContent(speedString)).x;
                GUI.Label(new Rect(start.x + (end.x - start.x) / 2f - width / 2f, end.y - 18f, width, 18f), speedString);


                Rect dataRect = new Rect(lastTime * 75f * a_zoom + 4, a_timelineRect.height / 1.75f,
                    end.x - start.x - 8, a_timelineRect.height - (a_timelineRect.height / 1.75f) - 18f);

                if (speedMod > 1f + Mathf.Epsilon)
                {
                    dataRect.y = 40f;
                }

                //Draw Drop Down Boxes

                GUI.Box(dataRect, "Section " + i);

                dataRect.x += 3f;
                dataRect.width -= 6f;

                GUILayout.BeginArea(dataRect);
                GUILayout.Space(18f);

                if (motionTimingPresets != null)
                {
                    curSection.UsePresets = GUILayout.Toggle(curSection.UsePresets,
                        new GUIContent("Use Preset"));
                }

                if (curSection.UsePresets && motionTimingPresets != null)
                {
                    curSection.MotionPresetId = EditorGUILayout.Popup(curSection.MotionPresetId,
                        defenitionNames);
                }
                else
                {
                    float defaultLabelWidth = EditorGUIUtility.labelWidth;
                    EditorGUIUtility.labelWidth = 40f;
                    curSection.ModType = (EMotionModType)EditorGUILayout.EnumPopup(new GUIContent("Type"), curSection.ModType);
                    curSection.RawModValue = EditorGUILayout.FloatField(new GUIContent("Value"), curSection.RawModValue);


                    if (curSection.RawModValue < 0.01f)
                        curSection.RawModValue = 0.01f;


                    EditorGUIUtility.labelWidth = defaultLabelWidth;
                }

                GUILayout.FlexibleSpace();

                float originalDurationF = (curSection.EndTime - lastTime);
                float finalDurationF = ((curSection.EndTime - lastTime) * speedMod);

                string originalDuration = originalDurationF.ToString("F2");
                string finalDuration = finalDurationF.ToString("F2");

                float originalSpeedF = m_targetMxMAnim.GetAverageRootSpeed(lastTime, curSection.EndTime);
                float finalSpeedF = originalSpeedF * (originalDurationF / finalDurationF);

                string originalSpeed = originalSpeedF.ToString("F2");
                string finalSpeed = finalSpeedF.ToString("F2");



                EditorGUILayout.LabelField("Original: " + originalDuration + " sec | " + originalSpeed + "m/s");
                EditorGUILayout.LabelField("Final: " + finalDuration + " sec | " + finalSpeed + "m/s");

                GUILayout.EndArea();

                lastTime = curSection.EndTime;
            }
        }