Example #1
0
 //============================================================================================
 /**
 *  @brief 
 *         
 *********************************************************************************************/
 public FootStepTagTrack(FootStepTagTrack a_copy) : base(a_copy)
 {
    for(int i=0; i < a_copy.m_footStepData.Count; ++i)
     {
         m_footStepData.Add(a_copy.m_footStepData[i]);
     }
 }
        public void ScrapGeneratedClips()
        {
            if (GeneratedClip != null)
            {
                AssetDatabase.RemoveObjectFromAsset(GeneratedClip);
                AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(this));
                GeneratedClip = null;
            }

            GeneratedTagTracks = new List<TagTrack>();
            GeneratedEvents = new List<EventMarker>();
            GeneratedUserBoolTracks = new List<TagTrackBase>();

            if (PrimaryClip != null)
            {

                GeneratedLeftFootStepTrack = new FootStepTagTrack(0, "FootStep Left", PrimaryClip.length);
                GeneratedRightFootStepTrack = new FootStepTagTrack(1, "FootStep Right", PrimaryClip.length);
                GeneratedWarpPositionTrack = new TagTrackBase(2, "Diable Warp (Position)", PrimaryClip.length);
                GeneratedWarpRotationTrack = new TagTrackBase(3, "Disable Warp (Rotation)", PrimaryClip.length);
                GeneratedEnableRootMotionTrack = new TagTrackBase(4, "Disable Matching", PrimaryClip.length);
                GeneratedPoseFavourTrack = new FloatTagTrack(5, "Pose Favour", PrimaryClip.length);
                GeneratedWarpTrajLatTrack = new TagTrackBase(6, "Disable Trajectory Warp (Angular)", PrimaryClip.length);
                GeneratedWarpTrajLongTrack = new TagTrackBase(7, "Disable Trajectory Warp (Long)", PrimaryClip.length);

                GeneratedPoseFavourTrack.DefaultValue = PoseFavourTrack.DefaultValue;
            }
        }
        public void ValidateBaseData()
        {
            if (MotionModifier == null)
                MotionModifier = new MotionModifyData();

            if (Events == null)
                Events = new List<EventMarker>();

            if (TagTracks == null)
                TagTracks = new List<TagTrack>();

            if (FavourTagTracks == null)
                FavourTagTracks = new List<TagTrack>();

            if (GeneratedEvents == null)
                GeneratedEvents = new List<EventMarker>();

            if (GeneratedTagTracks == null)
                GeneratedTagTracks = new List<TagTrack>();

            if (GeneratedFavourTagTracks == null)
                GeneratedFavourTagTracks = new List<TagTrack>();

            if (GeneratedUserBoolTracks == null)
                GeneratedUserBoolTracks = new List<TagTrackBase>();

            if (PrimaryClip != null)
            {
                if (LeftFootStepTrack == null || LeftFootStepTrack.Name == null || LeftFootStepTrack.Name == "")
                    LeftFootStepTrack = new FootStepTagTrack(0, "Footstep Left", PrimaryClip.length);

                if (RightFootStepTrack == null || RightFootStepTrack.Name == null || RightFootStepTrack.Name == "")
                    RightFootStepTrack = new FootStepTagTrack(1, "Footstep Right", PrimaryClip.length);

                if (WarpPositionTrack == null || WarpPositionTrack.Name == null || WarpPositionTrack.Name == "")
                    WarpPositionTrack = new TagTrackBase(2, "Disable Warp (Position)", PrimaryClip.length);

                if (WarpRotationTrack == null || WarpRotationTrack.Name == null || WarpRotationTrack.Name == "")
                    WarpRotationTrack = new TagTrackBase(3, "Disable Warp (Rotation)", PrimaryClip.length);

                if (EnableRootMotionTrack == null || EnableRootMotionTrack.Name == null || EnableRootMotionTrack.Name != "Disable Matching")
                    EnableRootMotionTrack = new TagTrackBase(4, "Disable Matching", PrimaryClip.length);

                if (PoseFavourTrack == null || PoseFavourTrack.Name == null || PoseFavourTrack.Name == "" )
                    PoseFavourTrack = new FloatTagTrack(5, "Pose Favour", PrimaryClip.length);

                if (WarpTrajLatTrack == null || WarpTrajLatTrack.Name == null || WarpTrajLatTrack.Name == "")
                    WarpTrajLatTrack = new TagTrackBase(6, "Disable Trajectory Warp (Angular)", PrimaryClip.length);

                if (WarpTrajLongTrack == null || WarpTrajLongTrack.Name == null || WarpTrajLongTrack.Name == "")
                    WarpTrajLongTrack = new TagTrackBase(7, "Disable Trajectory Warp (Long)", PrimaryClip.length);

                PoseFavourTrack.DefaultValue = 1f;
            }
            
            MotionModifier.OnEnable(this);

            EditorUtility.SetDirty(this);
        }
        public void ValidateBaseData()
        {
            if (MotionModifier == null)
                MotionModifier = new MotionModifyData();

            if (TagTracks == null)
                TagTracks = new List<TagTrack>();

            if (FavourTagTracks == null)
                FavourTagTracks = new List<TagTrack>();

            if (GeneratedTagTracks == null)
                GeneratedTagTracks = new List<TagTrack>();

            if (GeneratedFavourTagTracks == null)
                GeneratedFavourTagTracks = new List<TagTrack>();

            if (m_clips == null)
                m_clips = new List<AnimationClip>();

            if (m_positions == null)
                m_positions = new List<Vector2>();

            if (m_clips != null && m_clips.Count > 0)
            {
                float clipLength = m_clips[0].length;

                if (LeftFootStepTrack == null || LeftFootStepTrack.Name == "" || LeftFootStepTrack.Name == null)
                    LeftFootStepTrack = new FootStepTagTrack(0, "Footstep Left", clipLength);

                if (RightFootStepTrack == null || RightFootStepTrack.Name == "" || RightFootStepTrack.Name == null)
                    RightFootStepTrack = new FootStepTagTrack(1, "Footstep Right", clipLength);

                if (WarpPositionTrack == null || WarpPositionTrack.Name == "" || WarpPositionTrack.Name == null)
                    WarpPositionTrack = new TagTrackBase(2, "Disable Warp (Position)", clipLength);

                if (WarpRotationTrack == null || WarpRotationTrack.Name == "" || WarpRotationTrack.Name == null)
                    WarpRotationTrack = new TagTrackBase(3, "Disable Warp (Rotation)", clipLength);

                if (EnableRootMotionTrack == null || EnableRootMotionTrack.Name == "" || EnableRootMotionTrack.Name == null)
                    EnableRootMotionTrack = new TagTrackBase(4, "Enable Root Motion", clipLength);

                if (PoseFavourTrack == null || PoseFavourTrack.Name == "" || PoseFavourTrack.Name == null)
                    PoseFavourTrack = new FloatTagTrack(5, "Pose Favour", clipLength);

                if (WarpTrajLatTrack == null || WarpTrajLatTrack.Name == null || WarpTrajLatTrack.Name == "")
                    WarpTrajLatTrack = new TagTrackBase(6, "Disable Trajectory Warp (Angular)", clipLength);

                if (WarpTrajLongTrack == null || WarpTrajLongTrack.Name == null || WarpTrajLongTrack.Name == "")
                    WarpTrajLongTrack = new TagTrackBase(7, "Disable Trajectory Warp (Long)", clipLength);

                PoseFavourTrack.SetDefaultTagValue(1f);
            }

            MotionModifier.OnEnable(this);
            EditorUtility.SetDirty(this);
        }
        public void CopyData(MxMBlendSpace a_copy)
        {
            ValidateBaseData();

            m_magnitude = a_copy.m_magnitude;
            m_smoothing = a_copy.m_smoothing;

            m_scatterSpace = a_copy.m_scatterSpace;
            m_scatterSpacing = a_copy.m_scatterSpacing;
            m_scatterPositions = null;

            UseSpeedMods = a_copy.UseSpeedMods;

            GlobalTags = a_copy.GlobalTags;
            GlobalFavourTags = a_copy.GlobalFavourTags;

            m_clips = new List<AnimationClip>(a_copy.m_clips);
            m_positions = new List<Vector2>(a_copy.Positions);

            if(m_targetPrefab == null)
                m_targetPrefab = a_copy.m_targetPrefab;

            TagTracks = new List<TagTrack>(a_copy.TagTracks.Count + 1);
            foreach(TagTrack track in a_copy.TagTracks)
            {
                TagTracks.Add(new TagTrack(track));
            }

            FavourTagTracks = new List<TagTrack>(a_copy.FavourTagTracks.Count + 1);
            foreach(TagTrack track in a_copy.FavourTagTracks)
            {
                FavourTagTracks.Add(new TagTrack(track));
            }

            UserBoolTracks = new List<TagTrackBase>(a_copy.UserBoolTracks.Count + 1);
            foreach(TagTrackBase track in a_copy.UserBoolTracks)
            {
                UserBoolTracks.Add(new TagTrackBase(track));
            }

            LeftFootStepTrack = new FootStepTagTrack(a_copy.LeftFootStepTrack);
            RightFootStepTrack = new FootStepTagTrack(a_copy.RightFootStepTrack);
            WarpPositionTrack = new TagTrackBase(a_copy.WarpPositionTrack);
            WarpRotationTrack = new TagTrackBase(a_copy.WarpRotationTrack);
            EnableRootMotionTrack = new TagTrackBase(a_copy.EnableRootMotionTrack);
            PoseFavourTrack = new FloatTagTrack(a_copy.PoseFavourTrack);
            WarpTrajLatTrack = new TagTrackBase(a_copy.WarpTrajLatTrack);
            WarpTrajLongTrack = new TagTrackBase(a_copy.WarpTrajLongTrack);

            MotionModifier = new MotionModifyData(a_copy.MotionModifier, this);
        }
        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]);
            }
        }
        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");
                }
            }
        }
        public void CopyData(MxMAnimationClipComposite a_copy)
        {
            PrimaryClip = a_copy.PrimaryClip;
            BeforeClips = new List<AnimationClip>(a_copy.BeforeClips);
            AfterClips = new List<AnimationClip>(a_copy.AfterClips);

            Looping= a_copy.Looping;
            IgnoreEdges = a_copy.IgnoreEdges;
            ExtrapolateTrajectory = a_copy.ExtrapolateTrajectory;
            FlattenTrajectory = a_copy.FlattenTrajectory;
            RuntimeSplicing = a_copy.RuntimeSplicing;
            UseSpeedMods = a_copy.UseSpeedMods;

            GlobalTags = a_copy.GlobalTags;
            GlobalFavourTags = a_copy.GlobalFavourTags;

            TagTracks = new List<TagTrack>(a_copy.TagTracks.Count + 1);
            foreach(TagTrack track in a_copy.TagTracks)
            {
                TagTracks.Add(new TagTrack(track));
            }

            for (int i = 0; i < a_copy.TagTracks.Count; ++i)
            {
                TagTracks.Add(new TagTrack(a_copy.TagTracks[i]));
            }

            FavourTagTracks = new List<TagTrack>(a_copy.FavourTagTracks.Count + 1);
            foreach(TagTrack track  in a_copy.FavourTagTracks)
            {
                FavourTagTracks.Add(new TagTrack(track));
            }

            UserBoolTracks = new List<TagTrackBase>(a_copy.UserBoolTracks.Count + 1);
            foreach(TagTrackBase track in a_copy.UserBoolTracks)
            {
                UserBoolTracks.Add(new TagTrackBase(track));
            }

            Events = new List<EventMarker>(a_copy.Events.Count + 1);
            foreach(EventMarker marker in a_copy.Events)
            {
                Events.Add(new EventMarker(marker));
            }

            m_targetPreProcessData = a_copy.m_targetPreProcessData;
            m_targetAnimModule = a_copy.m_targetAnimModule;
            m_targetPrefab = a_copy.m_targetPrefab;

            PoseList = null;

            LeftFootStepTrack = new FootStepTagTrack(a_copy.LeftFootStepTrack);
            RightFootStepTrack = new FootStepTagTrack(a_copy.RightFootStepTrack);
            WarpPositionTrack = new TagTrackBase(a_copy.WarpPositionTrack);
            WarpRotationTrack = new TagTrackBase(a_copy.WarpRotationTrack);
            EnableRootMotionTrack = new TagTrackBase(a_copy.EnableRootMotionTrack);
            PoseFavourTrack = new FloatTagTrack(a_copy.PoseFavourTrack);
            WarpTrajLatTrack = new TagTrackBase(a_copy.WarpTrajLatTrack);
            WarpTrajLongTrack = new TagTrackBase(a_copy.WarpTrajLongTrack);

            MotionModifier = new MotionModifyData(a_copy.MotionModifier, this);
        }
Example #9
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);
        }