Exemplo n.º 1
0
        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;
        }
Exemplo n.º 2
0
        //============================================================================================
        /**
        *  @brief 
        *         
        *********************************************************************************************/
        public float GetSectionSpeedAtTime(float a_time, MotionTimingPresets a_presets)
        {
            float speed = 1f;
            float lastTime = 0f;
            for(int i=0; i < MotionSections.Count; ++i)
            {
                if(a_time > lastTime && a_time < MotionSections[i].EndTime)
                {
                    speed = 1f / MotionSections[i].GetSpeedMod(lastTime, a_presets, m_targetMxMAnim);
                    break;
                }

                lastTime = MotionSections[i].EndTime;
            }

            return speed;
        }
Exemplo n.º 3
0
        public void GenerateModifiedAnimation(MxMPreProcessData a_preProcessData, string a_directory)
        {
            EditorUtility.DisplayProgressBar("Generate Modified Animations", "Scraping Old Anims", 0f);

            if (a_preProcessData != null)
                m_targetPreProcessData = a_preProcessData;

            ScrapGeneratedClips();

            List<MotionSection> motionList = MotionModifier.MotionSections;
            MotionTimingPresets presets = m_targetPreProcessData.MotionTimingPresets;



            if (UseSpeedMods && m_clips != null && m_targetPreProcessData != null)
            {
                int blendSpaceId = 0;
                for (int i = 0; i < m_targetPreProcessData.BlendSpaces.Count; ++i)
                {
                    if(this == m_targetPreProcessData.BlendSpaces[i])
                    {
                        blendSpaceId = i;
                        break;
                    }
                }

                float cumTimeShift = 0f; //This is the cumulative amount of time shift at the point of modification;
                float curStartTime = 0f; //The start time for the current motion section
                //Loop clips and generate ndes ones
                foreach (AnimationClip clip in m_clips)
                {
                    EditorUtility.DisplayProgressBar("Generate Modified Animation", "Copying Clip " + clip.name, 0f);

                    var generatedClip = new AnimationClip();
                    EditorUtility.CopySerialized(clip, generatedClip);
                    generatedClip.name = clip.name + "_MxM_MOD_" + blendSpaceId;

                    var curveBindings = AnimationUtility.GetCurveBindings(generatedClip);
                    List<AnimationCurve> workingCurves = new List<AnimationCurve>(curveBindings.Length + 1);
                    List<AnimationEvent> newEvents = new List<AnimationEvent>();

                    //Create curves but don't add keys
                    for (int i = 0; i < curveBindings.Length; ++i)
                    {
                        workingCurves.Add(new AnimationCurve());
                    }

                    cumTimeShift = 0f;
                    curStartTime = 0f;
                    int[] startKeyIndex = new int[workingCurves.Count]; //The start key for the current motion section
                    for (int i = 0; i < motionList.Count; ++i)
                    {
                        EditorUtility.DisplayProgressBar("Generate Modified Animation",
                            "Modifying Section " + i + " of " + clip.name, ((float)i) / ((float)motionList.Count));

                        MotionSection motionSection = motionList[i];

                        float startWarpTime = curStartTime;
                        float endWarpTime = motionSection.EndTime;
                        float warpScale = motionSection.GetSpeedMod(curStartTime, presets, this);

                        float localTimeShift = (endWarpTime - startWarpTime) - (endWarpTime - startWarpTime) * warpScale;

                        //Shift Curve Keys
                        for (int k = 0; k < curveBindings.Length; ++k)
                        {
                            EditorCurveBinding binding = curveBindings[k];
                            AnimationCurve originalCurve = AnimationUtility.GetEditorCurve(clip, binding);
                            AnimationCurve workingCurve = workingCurves[k];

                            //Make a cut at the end only
                            int endKeyIndex = originalCurve.AddKey(endWarpTime, originalCurve.Evaluate(endWarpTime));

                            if (endKeyIndex == -1)
                                endKeyIndex = originalCurve.keys.Length - 1;

                            //Add in the intermediate keys scaled relative to the start and shifted by the cumulative time shift
                            for (int keyIndex = startKeyIndex[k]; i < motionList.Count - 1 ? keyIndex < endKeyIndex : keyIndex <= endKeyIndex; ++keyIndex)
                            {
                                Keyframe key = originalCurve.keys[keyIndex];
                                key.time = startWarpTime + ((key.time - startWarpTime) * warpScale) - cumTimeShift;
                                key.inTangent /= warpScale;
                                key.outTangent /= warpScale;

                                workingCurve.AddKey(key);
                            }

                            startKeyIndex[k] = endKeyIndex;
                        }

                        //Shift Animation Clip EventsEvents
                        foreach (AnimationEvent evt in generatedClip.events)
                        {
                            if (evt.time > startWarpTime && evt.time < endWarpTime)
                            {
                                //Scale & Shift
                                evt.time = startWarpTime + ((evt.time - startWarpTime) * warpScale) - cumTimeShift;
                            }

                            newEvents.Add(evt);
                        }
                    }

                    for (int i = 0; i < workingCurves.Count; ++i)
                    {
                        EditorUtility.DisplayProgressBar("Generate Modified Animation",
                            "Generating Curves for clip: " + clip.name, ((float)i) / ((float)workingCurves.Count));

                        AnimationUtility.SetEditorCurve(generatedClip, curveBindings[i], workingCurves[i]);
                    }

                    AnimationUtility.SetAnimationEvents(generatedClip, newEvents.ToArray());
                    EditorUtility.SetDirty(generatedClip);

                    AssetDatabase.CreateAsset(generatedClip, a_directory + "/" + generatedClip.name + ".anim");

                    AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(generatedClip));
                    GeneratedClips.Add(generatedClip);
                }
                //End loop clips. Generations is complete

                //Go through Motion Sections again and modify tag tracks and events
                cumTimeShift = 0f; //This is the cumulative amount of time shift at the point of modification;
                curStartTime = 0f; //The start time for the current motion section
                for (int i = 0; i < motionList.Count; ++i)
                {
                    MotionSection motionSection = motionList[i];

                    float startWarpTime = curStartTime;
                    float endWarpTime = motionSection.EndTime;
                    float warpScale = motionSection.GetSpeedMod(curStartTime, presets, this);

                    float localTimeShift = (endWarpTime - startWarpTime) - (endWarpTime - startWarpTime) * warpScale;

                    //Shift MXM Tag Points
                    foreach (TagTrack track in TagTracks)
                    {
                        TagTrack newTrack = new TagTrack(track);
                        List<Vector2> tagList = newTrack.Tags;

                        for (int k = 0; k < tagList.Count; ++k)
                        {
                            Vector2 newTag = tagList[k];

                            if (newTag.x > startWarpTime && newTag.x < endWarpTime)
                            {
                                newTag.x = startWarpTime + ((newTag.x - startWarpTime) * warpScale) - cumTimeShift;
                            }

                            if (newTag.y > startWarpTime && newTag.y < endWarpTime)
                            {
                                newTag.y = startWarpTime + ((newTag.y - startWarpTime) * warpScale) - cumTimeShift;
                            }

                            tagList[k] = newTag;
                        }

                        GeneratedTagTracks.Add(newTrack);
                    }

                    cumTimeShift += localTimeShift;
                    curStartTime = endWarpTime;
                }  
            }

            EditorUtility.SetDirty(this);
            EditorUtility.ClearProgressBar();
        }
        public void GenerateModifiedAnimation(MxMPreProcessData a_preProcessData, string a_directory)
        {
            EditorUtility.DisplayProgressBar("Generate Modified Animation", "Scraping Old Anims", 0f);

            if (a_preProcessData != null)
                m_targetPreProcessData = a_preProcessData;

            ScrapGeneratedClips();

            if (UseSpeedMods)
            {
                if (PrimaryClip != null && m_targetPreProcessData != null)
                {

                    EditorUtility.DisplayProgressBar("Generate Modified Animation", "Copying Clip " + PrimaryClip.name, 0f);

                    GeneratedClip = new AnimationClip();
                    EditorUtility.CopySerialized(PrimaryClip, GeneratedClip);
                    GeneratedClip.name = PrimaryClip.name + "_MxM_MOD";

                    var curveBindings = AnimationUtility.GetCurveBindings(GeneratedClip);
                    List<AnimationCurve> workingCurves = new List<AnimationCurve>(curveBindings.Length + 1);
                    List<AnimationEvent> newEvents = new List<AnimationEvent>();
                    List<MotionSection> motionList = MotionModifier.MotionSections;
                    MotionTimingPresets presets = m_targetPreProcessData.MotionTimingPresets;

                    GeneratedTagTracks = new List<TagTrack>(TagTracks);
                    GeneratedFavourTagTracks = new List<TagTrack>(TagTracks);
                    GeneratedUserBoolTracks = new List<TagTrackBase>(UserBoolTracks);
                    GeneratedLeftFootStepTrack = new FootStepTagTrack(LeftFootStepTrack);
                    GeneratedRightFootStepTrack = new FootStepTagTrack(RightFootStepTrack);
                    GeneratedWarpPositionTrack = new TagTrackBase(WarpPositionTrack);
                    GeneratedWarpRotationTrack = new TagTrackBase(WarpRotationTrack);
                    GeneratedEnableRootMotionTrack = new TagTrackBase(EnableRootMotionTrack);
                    GeneratedPoseFavourTrack = new FloatTagTrack(PoseFavourTrack);
                    GeneratedWarpTrajLatTrack = new TagTrackBase(WarpTrajLatTrack);
                    GeneratedWarpTrajLongTrack = new TagTrackBase(WarpTrajLongTrack);

                    //Create curves but don't add keys
                    for (int i = 0; i < curveBindings.Length; ++i)
                    {
                        workingCurves.Add(new AnimationCurve());
                    }

                    float cumTimeShift = 0f; //This is the cumulative amount of time shift at the point of modification;
                    float curStartTime = 0f; //The start time for the current motion section
                    int[] startKeyIndex = new int[workingCurves.Count]; //The start key for the current motion section
                    for (int i = 0; i < motionList.Count; ++i)
                    {
                        EditorUtility.DisplayProgressBar("Generate Modified Animation",
                            "Modifying Section " + i + " of " + PrimaryClip.name, ((float)i) / ((float)motionList.Count));

                        MotionSection motionSection = motionList[i];

                        float startWarpTime = curStartTime;
                        float endWarpTime = motionSection.EndTime;
                        float warpScale = motionSection.GetSpeedMod(curStartTime, presets, this);

                        float localTimeShift = (endWarpTime - startWarpTime) - (endWarpTime - startWarpTime) * warpScale;

                        //Shift Curve Keys
                        for (int k = 0; k < curveBindings.Length; ++k)
                        {
                            EditorCurveBinding binding = curveBindings[k];
                            AnimationCurve originalCurve = AnimationUtility.GetEditorCurve(PrimaryClip, binding);
                            AnimationCurve workingCurve = workingCurves[k];

                            //Make a cut at the end only
                            int endKeyIndex = originalCurve.AddKey(endWarpTime, originalCurve.Evaluate(endWarpTime));

                            if (endKeyIndex == -1)
                                endKeyIndex = originalCurve.keys.Length - 1;

                            //Add in the intermediate keys scaled relative to the start and shifted by the cumulative time shift
                            for (int keyIndex = startKeyIndex[k]; i < motionList.Count - 1 ? keyIndex < endKeyIndex : keyIndex <= endKeyIndex; ++keyIndex)
                            {
                                Keyframe key = originalCurve.keys[keyIndex];
                                key.time = startWarpTime + ((key.time - startWarpTime) * warpScale) - cumTimeShift;
                                key.inTangent /= warpScale;
                                key.outTangent /= warpScale;

                                workingCurve.AddKey(key);
                            }

                            startKeyIndex[k] = endKeyIndex;
                        }

                        //Shift Events
                        foreach (AnimationEvent evt in GeneratedClip.events)
                        {
                            if (evt.time > startWarpTime && evt.time < endWarpTime)
                            {
                                //Scale & Shift
                                evt.time = startWarpTime + ((evt.time - startWarpTime) * warpScale) - cumTimeShift;
                            }

                            newEvents.Add(evt);
                        }

                        //Shift MxM Events
                        foreach (EventMarker evt in Events)
                        {
                            EventMarker newMarker = new EventMarker(evt);

                            if (newMarker.EventTime > startWarpTime && evt.EventTime < endWarpTime)
                            {
                                evt.EventTime = startWarpTime + ((evt.EventTime - startWarpTime) * warpScale) - cumTimeShift;
                            }

                            GeneratedEvents.Add(newMarker);
                        }

                        //Shift MXM Tag Points
                        foreach (TagTrack track in GeneratedTagTracks)
                        {
                            List<Vector2> tagList = track.Tags;

                            for (int k = 0; k < tagList.Count; ++k)
                            {
                                Vector2 newTag = tagList[k];

                                if (newTag.x > startWarpTime && newTag.x < endWarpTime)
                                {
                                    newTag.x = startWarpTime + ((newTag.x - startWarpTime) * warpScale) - cumTimeShift;
                                }

                                if (newTag.y > startWarpTime && newTag.y < endWarpTime)
                                {
                                    newTag.y = startWarpTime + ((newTag.y - startWarpTime) * warpScale) - cumTimeShift;
                                }

                                tagList[k] = newTag;
                            }
                        }

                        //Shift MXM FavourTag Points
                        foreach (TagTrack track in GeneratedFavourTagTracks)
                        {
                            List<Vector2> tagList = track.Tags;

                            for (int k = 0; k < tagList.Count; ++k)
                            {
                                Vector2 newTag = tagList[k];

                                if (newTag.x > startWarpTime && newTag.x < endWarpTime)
                                {
                                    newTag.x = startWarpTime + ((newTag.x - startWarpTime) * warpScale) - cumTimeShift;
                                }

                                if (newTag.y > startWarpTime && newTag.y < endWarpTime)
                                {
                                    newTag.y = startWarpTime + ((newTag.y - startWarpTime) * warpScale) - cumTimeShift;
                                }

                                tagList[k] = newTag;
                            }
                        }

                        //Shift MxM User Tags
                        foreach (TagTrackBase track in GeneratedUserBoolTracks)
                        {
                            ShiftTrackTags(track, startWarpTime, endWarpTime, warpScale, cumTimeShift);
                        }

                        //Shift MxM Utility Tags
                        ShiftTrackTags(GeneratedLeftFootStepTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift);
                        ShiftTrackTags(GeneratedRightFootStepTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift);
                        ShiftTrackTags(GeneratedWarpPositionTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift);
                        ShiftTrackTags(GeneratedWarpRotationTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift);
                        ShiftTrackTags(GeneratedEnableRootMotionTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift);
                        ShiftTrackTags(GeneratedPoseFavourTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift);
                        ShiftTrackTags(GeneratedWarpTrajLatTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift);
                        ShiftTrackTags(GeneratedWarpTrajLongTrack, startWarpTime, endWarpTime, warpScale, cumTimeShift);

                        cumTimeShift += localTimeShift;
                        curStartTime = endWarpTime;
                    }

                    for (int i = 0; i < workingCurves.Count; ++i)
                    {
                        EditorUtility.DisplayProgressBar("Generate Modified Animation",
                            "Generating Curves for clip: " + PrimaryClip.name, ((float)i) / ((float)workingCurves.Count));

                        AnimationUtility.SetEditorCurve(GeneratedClip, curveBindings[i], workingCurves[i]);
                    }

                    AnimationUtility.SetAnimationEvents(GeneratedClip, newEvents.ToArray());
                    EditorUtility.SetDirty(GeneratedClip);

                    AssetDatabase.CreateAsset(GeneratedClip, a_directory + "/" + GeneratedClip.name + ".anim");

                    //AssetDatabase.AddObjectToAsset(GeneratedClip, m_targetPreProcessData);
                    AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(GeneratedClip));

                    EditorUtility.SetDirty(this);

                    EditorUtility.ClearProgressBar();

                }
                else
                {
                    Debug.LogWarning("Warning: Cannot generate modified animation with no PrimaryClip in MxMAnimationClipComposite");
                }
            }
        }
Exemplo n.º 5
0
        //============================================================================================
        /**
        *  @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;
            }
        }