// Given a track, return the animation clip
        internal static AnimationClip FindRecordingAnimationClipAtTime(this TrackAsset trackAsset, double time)
        {
            if (trackAsset == null)
                return null;

            AnimationTrack animTrack = trackAsset as AnimationTrack;
            if (animTrack != null && !animTrack.inClipMode)
            {
                return animTrack.infiniteClip;
            }

            TimelineClip displayBackground = null;
            trackAsset.FindRecordingClipAtTime(time, out displayBackground);
            if (displayBackground != null)
            {
                if (displayBackground.recordable)
                {
                    AnimationPlayableAsset asset = displayBackground.asset as AnimationPlayableAsset;
                    if (asset != null)
                        return asset.clip;
                }
                else if (animTrack == null)
                {
                    AnimatedParameterExtensions.CreateCurvesIfRequired(displayBackground);
                    return displayBackground.curves;
                }
            }

            return null;
        }
示例#2
0
 private void DoManipulators()
 {
     if (!(this.m_EditorClip == null) && this.m_EditorClip.clip != null)
     {
         AnimationPlayableAsset animationPlayableAsset = this.m_EditorClip.clip.asset as AnimationPlayableAsset;
         AnimationTrack         animationTrack         = this.m_EditorClip.clip.parentTrack as AnimationTrack;
         Transform transform = this.GetTransform();
         if (transform != null && animationPlayableAsset != null && this.m_OffsetEditMode != TimelineAnimationUtilities.OffsetEditMode.None && animationTrack != null)
         {
             Vector3    vector     = transform.get_position();
             Quaternion quaternion = transform.get_rotation();
             EditorGUI.BeginChangeCheck();
             if (this.m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Translation)
             {
                 vector = Handles.PositionHandle(vector, (Tools.get_pivotRotation() != 1) ? quaternion : Quaternion.get_identity());
             }
             else if (this.m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Rotation)
             {
                 quaternion = Handles.RotationHandle(quaternion, vector);
             }
             if (EditorGUI.EndChangeCheck())
             {
                 TimelineAnimationUtilities.RigidTransform rigidTransform = TimelineAnimationUtilities.UpdateClipOffsets(animationPlayableAsset, animationTrack, transform, vector, quaternion);
                 animationPlayableAsset.position = rigidTransform.position;
                 animationPlayableAsset.rotation = rigidTransform.rotation;
                 this.Reevaluate();
                 base.Repaint();
             }
         }
     }
 }
示例#3
0
        public static TimelineClip Clone(TimelineClip clip, PlayableDirector directorInstance)
        {
            EditorClip   editorClip = EditorItemFactory.GetEditorClip(clip);
            TimelineClip clip2      = Object.Instantiate <EditorClip>(editorClip).clip;

            SelectionManager.Remove(clip2);
            clip2.parentTrack = null;
            clip2.ClearAnimatedParameterCurves();
            if (clip.curves != null)
            {
                AnimatedParameterExtensions.CreateCurvesIfRequired(clip2, clip.parentTrack);
                EditorUtility.CopySerialized(clip.curves, clip2.curves);
            }
            ScriptableObject scriptableObject = clip2.asset as ScriptableObject;

            if (scriptableObject != null && clip2.asset is IPlayableAsset)
            {
                ScriptableObject scriptableObject2 = TimelineHelpers.CloneReferencedPlayableAsset(scriptableObject, directorInstance);
                TimelineHelpers.SaveCloneToOriginalAsset(scriptableObject, scriptableObject2);
                clip2.asset = scriptableObject2;
                AnimationPlayableAsset animationPlayableAsset = scriptableObject2 as AnimationPlayableAsset;
                if (clip2.recordable && animationPlayableAsset != null && animationPlayableAsset.clip != null)
                {
                    clip2.displayName = animationPlayableAsset.clip.get_name();
                }
            }
            return(clip2);
        }
示例#4
0
        internal static bool IsRecordingToClip(this TrackAsset track, TimelineClip clip)
        {
            bool result;

            if (track == null || clip == null)
            {
                result = false;
            }
            else
            {
                AnimationClip activeRecordingAnimationClip = track.GetActiveRecordingAnimationClip();
                if (activeRecordingAnimationClip == null)
                {
                    result = false;
                }
                else if (activeRecordingAnimationClip == clip.curves)
                {
                    result = true;
                }
                else
                {
                    AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset;
                    result = (animationPlayableAsset != null && activeRecordingAnimationClip == animationPlayableAsset.clip);
                }
            }
            return(result);
        }
示例#5
0
        public override void DrawClip(TrackDrawer.ClipDrawData drawData)
        {
            TimelineClip clip = drawData.clip;

            if (clip.animationClip == null)
            {
                base.DrawClip(drawData);
            }
            else
            {
                bool flag = false;
                if (clip.asset != null)
                {
                    AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset;
                    if (animationPlayableAsset != null)
                    {
                        flag = (animationPlayableAsset.clip == null);
                    }
                }
                if (flag)
                {
                    if (AnimationTrackDrawer.s_MissingIcon == null)
                    {
                        Texture2D errorIcon = EditorGUIUtility.get_errorIcon();
                        AnimationTrackDrawer.s_MissingIcon = new GUIContent(errorIcon, "This clip has no animation assigned");
                    }
                    base.DrawClipErrorIcon(drawData, AnimationTrackDrawer.s_MissingIcon);
                }
                base.DrawClip(drawData);
            }
        }
 public static void ConvertToClipMode(this AnimationTrack track)
 {
     if (track.CanConvertToClipMode())
     {
         TimelineUndo.PushUndo(track, "Convert To Clip");
         if (!track.animClip.get_empty())
         {
             TimelineUndo.PushUndo(track.animClip, "Convert To Clip");
             float num = AnimationClipCurveCache.Instance.GetCurveInfo(track.animClip).keyTimes.FirstOrDefault <float>();
             track.animClip.ShiftBySeconds(-num);
             TimelineClip timelineClip = track.CreateClipFromAsset(track.animClip);
             TimelineCreateUtilities.SaveAssetIntoObject(timelineClip.asset, track);
             timelineClip.start = (double)num;
             timelineClip.preExtrapolationMode  = track.openClipPreExtrapolation;
             timelineClip.postExtrapolationMode = track.openClipPostExtrapolation;
             timelineClip.recordable            = true;
             if (Math.Abs(timelineClip.duration) < 1.4012984643248171E-45)
             {
                 timelineClip.duration = 1.0;
             }
             AnimationPlayableAsset animationPlayableAsset = timelineClip.asset as AnimationPlayableAsset;
             if (animationPlayableAsset)
             {
                 animationPlayableAsset.position = track.openClipOffsetPosition;
                 animationPlayableAsset.rotation = track.openClipOffsetRotation;
                 track.openClipOffsetPosition    = Vector3.get_zero();
                 track.openClipOffsetRotation    = Quaternion.get_identity();
             }
             track.CalculateExtrapolationTimes();
         }
         track.animClip = null;
         EditorUtility.SetDirty(track);
     }
 }
    void setClipOffset(GameObject animTimeline, Vector3 anim_location, Quaternion anim_rotation)
    {
        // SET ATTRIBUTES OF TARGET TIMELINE, a child of some gameobject is the convention

        PlayableDirector       anim_director     = animTimeline.GetComponent <PlayableDirector>();
        List <PlayableBinding> playable_list     = anim_director.playableAsset.outputs.ToList();
        TrackAsset             target_anim_track = playable_list[0].sourceObject as AnimationTrack;

        foreach (TimelineClip track_clip in target_anim_track.GetClips())
        {
            AnimationPlayableAsset target_anim_clip = track_clip.asset as AnimationPlayableAsset;
            target_anim_clip.position = anim_location;
            target_anim_clip.rotation = anim_rotation;
        }

        // this is the animation track, always; here, we are setting an offset
        //TrackAsset target_anim_track = playable_list[0].sourceObject as AnimationTrack;
        //List<TimelineClip> track_clips = target_anim_track.GetClips().ToList();
        //AnimationPlayableAsset target_anim_clip = track_clips[0].asset as AnimationPlayableAsset;
        //target_anim_clip.position = start_pos;

        // this is the lerp track, always; here, we set destination
        //TrackAsset target_lerp_track = playable_list[1].sourceObject as PlayableTrack;
        //List<TimelineClip> lerp_clips = target_lerp_track.GetClips().ToList();
    }
        string GetErrorText(AnimationPlayableAsset animationAsset, AnimationTrack track, string defaultError)
        {
            if (animationAsset.clip == null)
            {
                return(k_NoClipAssignedError);
            }
            if (animationAsset.clip.legacy)
            {
                return(k_LegacyClipError);
            }
            if (animationAsset.clip.hasMotionCurves || animationAsset.clip.hasRootCurves)
            {
                if (track != null && track.trackOffset == TrackOffset.Auto)
                {
                    var animator = track.GetBinding(TimelineEditor.inspectedDirector);
                    if (animator != null && !animator.applyRootMotion && !animationAsset.clip.hasGenericRootTransform)
                    {
                        if (animationAsset.clip.hasMotionCurves)
                        {
                            return(k_MotionCurveError);
                        }
                        return(k_RootCurveError);
                    }
                }
            }

            return(defaultError);
        }
示例#9
0
 public virtual bool GetHasRootTransforms(AnimationPlayableAsset instance)
 {
     if (instance == null)
     {
         return(false);
     }
     return(uAnimationUtility.HasRootCurves(instance.clip));
 }
        // Is this a recordable clip on an animation track.
        internal static bool IsRecordableAnimationClip(TimelineClip clip)
        {
            if (!clip.recordable)
                return false;

            AnimationPlayableAsset asset = clip.asset as AnimationPlayableAsset;
            if (asset == null)
                return false;

            return true;
        }
示例#11
0
 public override bool GetHasRootTransforms(AnimationPlayableAsset instance)
 {
     if (instance == null)
     {
         return(false);
     }
     if (dg_get_hasRootTransforms == null || dg_get_hasRootTransforms.Target != (object)instance)
     {
         dg_get_hasRootTransforms = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), instance, instance.GetType().GetProperty("hasRootTransforms", BindingFlags.NonPublic | BindingFlags.Instance).GetGetMethod(true));
     }
     return(dg_get_hasRootTransforms());
 }
 private static void ResetClipOffsets(ITimelineState state, TimelineClip[] clips)
 {
     for (int i = 0; i < clips.Length; i++)
     {
         TimelineClip timelineClip = clips[i];
         if (timelineClip.asset is AnimationPlayableAsset)
         {
             AnimationPlayableAsset animationPlayableAsset = (AnimationPlayableAsset)timelineClip.asset;
             animationPlayableAsset.ResetOffsets();
         }
     }
     state.rebuildGraph = true;
 }
示例#13
0
    public void SetClipOffset(Vector3 _position, Vector3 _normal)
    {
        var obj = UnityEditor.Selection.activeObject;

        if (obj != null)
        {
            var fi = obj.GetType().GetField("m_Clip", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
            if (fi != null)
            {
                var clip = fi.GetValue(obj) as TimelineClip;
                if (clip != null)
                {
                    AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset;
                    animationPlayableAsset.position = new Vector3(0, 0, 0);
                    var view = SceneView.lastActiveSceneView;
                    if (view != null)
                    {
                        Undo.RecordObject(animationPlayableAsset, "Object Placer: Adjusting Clip Offset");
                        if (lookUp)
                        {
                            animationPlayableAsset.rotation *= Quaternion.FromToRotation(Vector3.up, _normal);
                        }
                        if (useOffset)
                        {
                            animationPlayableAsset.position = _position + offset;
                        }
                        else
                        {
                            animationPlayableAsset.position = _position;
                        }
                    }
                }
                else
                {
                    Debug.Log("Select a clip please.");
                }
            }
            else
            {
                Debug.Log("Select a clip please.");
            }
        }
        else
        {
            Debug.Log("Select a clip please.");
        }
        HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Keyboard));
        opg.isDrawing = false;
        isMoving      = false;
    }
        // Given a track, return the animation clip
        internal static AnimationClip FindRecordingAnimationClipAtTime(this TrackAsset trackAsset, double time)
        {
            if (trackAsset == null)
            {
                return(null);
            }

            AnimationTrack animTrack = trackAsset as AnimationTrack;

            if (animTrack != null && !animTrack.inClipMode)
            {
                return(animTrack.infiniteClip);
            }

            TimelineClip displayBackground;

            trackAsset.FindRecordingClipAtTime(time, out displayBackground);
            if (displayBackground != null)
            {
                if (displayBackground.recordable)
                {
                    AnimationPlayableAsset asset = displayBackground.asset as AnimationPlayableAsset;
                    if (asset != null)
                    {
                        return(asset.clip);
                    }
                }
                else if (animTrack == null)
                {
                    if (displayBackground.curves == null)
                    {
                        displayBackground.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(displayBackground.parentTrack, TimelineClip.kDefaultCurvesName));
                    }

                    return(displayBackground.curves);
                }
            }
            else if (trackAsset.HasAnyAnimatableParameters())
            {
                if (trackAsset.curves == null)
                {
                    trackAsset.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(trackAsset.timelineAsset, TrackAsset.kDefaultCurvesName));
                }

                return(trackAsset.curves);
            }

            return(null);
        }
        public static bool CanConvertFromClipMode(this AnimationTrack track)
        {
            bool result;

            if (track == null || !track.inClipMode || track.clips.Length != 1 || track.clips[0].start < 0.0 || !track.clips[0].recordable)
            {
                result = false;
            }
            else
            {
                AnimationPlayableAsset animationPlayableAsset = track.clips[0].asset as AnimationPlayableAsset;
                result = (!(animationPlayableAsset == null) && TimelineHelpers.HaveSameContainerAsset(track, animationPlayableAsset.clip));
            }
            return(result);
        }
 private static void GetAnimationClips(IEnumerable <TimelineClip> timelineClips, List <AnimationClip> clips)
 {
     foreach (var timelineClip in timelineClips)
     {
         if (timelineClip.curves != null)
         {
             clips.Add(timelineClip.curves);
         }
         AnimationPlayableAsset apa = timelineClip.asset as AnimationPlayableAsset;
         if (apa != null && apa.clip != null)
         {
             clips.Add(apa.clip);
         }
     }
 }
示例#17
0
        // Is this a recordable clip on an animation track.
        internal static bool IsRecordableAnimationClip(TimelineClip clip)
        {
            if (!clip.recordable)
            {
                return(false);
            }

            AnimationPlayableAsset asset = clip.asset as AnimationPlayableAsset;

            if (asset == null)
            {
                return(false);
            }

            return(true);
        }
示例#18
0
        internal static TimelineClip Clone(TimelineClip clip, PlayableDirector director, PlayableAsset newOwner)
        {
            var editorClip = EditorClipFactory.GetEditorClip(clip);
            // Workaround for Clips not being unity object, assign it to a editor clip wrapper, clone it, and pull the clip back out
            var newClip = Object.Instantiate(editorClip).clip;

            // perform fix ups for what Instantiate cannot properly detect
            SelectionManager.Remove(newClip);
            newClip.parentTrack = null;
            newClip.curves      = null; // instantiate might copy the reference, we need to clear it

            // curves are explicitly owned by the clip
            if (clip.curves != null)
            {
                newClip.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(newOwner, clip.curves.name));
                EditorUtility.CopySerialized(clip.curves, newClip.curves);
                TimelineCreateUtilities.SaveAssetIntoObject(newClip.curves, newOwner);
            }

            ScriptableObject playableAsset = newClip.asset as ScriptableObject;

            if (playableAsset != null && newClip.asset is IPlayableAsset)
            {
                var clone = CloneReferencedPlayableAsset(playableAsset, director);
                SaveCloneToAsset(clone, newOwner);

                newClip.asset = clone;

                // special case to make the name match the recordable clips, but only if they match on the original clip
                var originalRecordedAsset = clip.asset as AnimationPlayableAsset;
                if (clip.recordable && originalRecordedAsset != null && originalRecordedAsset.clip != null)
                {
                    AnimationPlayableAsset clonedAnimationAsset = clone as AnimationPlayableAsset;
                    if (clonedAnimationAsset != null && clonedAnimationAsset.clip != null)
                    {
                        clonedAnimationAsset.clip = CloneAnimationClip(originalRecordedAsset.clip, newOwner);
                        if (clip.displayName == originalRecordedAsset.clip.name && newClip.recordable)
                        {
                            clonedAnimationAsset.name = clonedAnimationAsset.clip.name;
                            newClip.displayName       = clonedAnimationAsset.name;
                        }
                    }
                }
            }

            return(newClip);
        }
        private static void WriteMatchFields(AnimationPlayableAsset asset, TimelineAnimationUtilities.RigidTransform result, MatchTargetFields fields)
        {
            Vector3 position = asset.position;

            position.x     = ((!fields.HasAny(MatchTargetFields.PositionX)) ? position.x : result.position.x);
            position.y     = ((!fields.HasAny(MatchTargetFields.PositionY)) ? position.y : result.position.y);
            position.z     = ((!fields.HasAny(MatchTargetFields.PositionZ)) ? position.z : result.position.z);
            asset.position = position;
            if (fields.HasAny(MatchTargetFieldConstants.Rotation))
            {
                Vector3 eulerAngles  = asset.rotation.get_eulerAngles();
                Vector3 eulerAngles2 = result.rotation.get_eulerAngles();
                eulerAngles.x  = ((!fields.HasAny(MatchTargetFields.RotationX)) ? eulerAngles.x : eulerAngles2.x);
                eulerAngles.y  = ((!fields.HasAny(MatchTargetFields.RotationY)) ? eulerAngles.y : eulerAngles2.y);
                eulerAngles.z  = ((!fields.HasAny(MatchTargetFields.RotationZ)) ? eulerAngles.z : eulerAngles2.z);
                asset.rotation = Quaternion.Euler(eulerAngles);
            }
        }
        public static void MatchPrevious(TimelineClip currentClip, Transform matchPoint, PlayableDirector director)
        {
            MatchTargetFields matchFields = TimelineAnimationUtilities.GetMatchFields(currentClip);

            if (matchFields != MatchTargetFieldConstants.None && !(matchPoint == null))
            {
                double       time         = director.get_time();
                TimelineClip previousClip = TimelineAnimationUtilities.GetPreviousClip(currentClip);
                if (previousClip != null && currentClip != previousClip)
                {
                    AnimationTrack animationTrack  = currentClip.parentTrack as AnimationTrack;
                    double         blendInDuration = currentClip.blendInDuration;
                    currentClip.blendInDuration = 0.0;
                    double blendOutDuration = previousClip.blendOutDuration;
                    previousClip.blendOutDuration = 0.0;
                    director.Stop();
                    animationTrack.RemoveClip(currentClip);
                    director.Play();
                    double num = (currentClip.start <= previousClip.end) ? currentClip.start : previousClip.end;
                    director.set_time(num - 1E-05);
                    director.Evaluate();
                    Vector3    position = matchPoint.get_position();
                    Quaternion rotation = matchPoint.get_rotation();
                    director.Stop();
                    animationTrack.AddClip(currentClip);
                    animationTrack.RemoveClip(previousClip);
                    director.Play();
                    director.set_time(currentClip.start + 1E-05);
                    director.Evaluate();
                    AnimationPlayableAsset asset = currentClip.asset as AnimationPlayableAsset;
                    TimelineAnimationUtilities.RigidTransform result = TimelineAnimationUtilities.UpdateClipOffsets(asset, animationTrack, matchPoint, position, rotation);
                    TimelineAnimationUtilities.WriteMatchFields(asset, result, matchFields);
                    currentClip.blendInDuration   = blendInDuration;
                    previousClip.blendOutDuration = blendOutDuration;
                    director.Stop();
                    animationTrack.AddClip(previousClip);
                    director.Play();
                    director.set_time(time);
                    director.Evaluate();
                }
            }
        }
        public static void ComputeClipWorldSpaceOffset(PlayableDirector director, TimelineClip clip, out Vector3 clipPositionOffset, out Quaternion clipRotationOffset)
        {
            GameObject sceneGameObject = TimelineUtility.GetSceneGameObject(director, clip.parentTrack);
            double     time            = director.get_time();
            TrackAsset parentTrack     = clip.parentTrack;

            TimelineClip[] clips = parentTrack.clips;
            director.Stop();
            for (int i = 0; i < clips.Length; i++)
            {
                parentTrack.RemoveClip(clips[i]);
            }
            parentTrack.AddClip(clip);
            double start           = clip.start;
            double blendInDuration = clip.blendInDuration;

            clip.blendInDuration = 0.0;
            clip.start           = 1.0;
            director.Play();
            director.set_time(0.0);
            director.Evaluate();
            clipPositionOffset = sceneGameObject.get_transform().get_position();
            clipRotationOffset = sceneGameObject.get_transform().get_rotation();
            AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset;

            if (!(animationPlayableAsset == null))
            {
                clipPositionOffset += clipRotationOffset * animationPlayableAsset.position;
                clipRotationOffset *= animationPlayableAsset.rotation;
                director.Stop();
                clip.start           = start;
                clip.blendInDuration = blendInDuration;
                parentTrack.RemoveClip(clip);
                for (int j = 0; j < clips.Length; j++)
                {
                    parentTrack.AddClip(clips[j]);
                }
                director.Play();
                director.set_time(time);
                director.Evaluate();
            }
        }
        private static MatchTargetFields GetMatchFields(TimelineClip clip)
        {
            AnimationTrack    animationTrack = clip.parentTrack as AnimationTrack;
            MatchTargetFields result;

            if (animationTrack == null)
            {
                result = MatchTargetFieldConstants.None;
            }
            else
            {
                AnimationPlayableAsset animationPlayableAsset = clip.asset as AnimationPlayableAsset;
                MatchTargetFields      matchTargetFields      = animationTrack.matchTargetFields;
                if (animationPlayableAsset != null && animationPlayableAsset.useTrackMatchFields)
                {
                    matchTargetFields = animationPlayableAsset.matchTargetFields;
                }
                result = matchTargetFields;
            }
            return(result);
        }
示例#23
0
        internal static AnimationClip FindRecordingAnimationClipAtTime(this TrackAsset trackAsset, double time)
        {
            AnimationClip result;

            if (trackAsset == null)
            {
                result = null;
            }
            else
            {
                AnimationTrack animationTrack = trackAsset as AnimationTrack;
                if (animationTrack != null && !animationTrack.inClipMode)
                {
                    result = animationTrack.animClip;
                }
                else
                {
                    TimelineClip timelineClip = trackAsset.FindRecordingClipAtTime(time);
                    if (timelineClip != null)
                    {
                        AnimationPlayableAsset animationPlayableAsset = timelineClip.asset as AnimationPlayableAsset;
                        if (animationPlayableAsset != null)
                        {
                            result = animationPlayableAsset.clip;
                        }
                        else
                        {
                            AnimatedParameterExtensions.CreateCurvesIfRequired(timelineClip, null);
                            result = timelineClip.curves;
                        }
                    }
                    else
                    {
                        result = null;
                    }
                }
            }
            return(result);
        }
        public static TimelineAnimationUtilities.RigidTransform UpdateClipOffsets(AnimationPlayableAsset asset, AnimationTrack track, Transform transform, Vector3 globalPosition, Quaternion globalRotation)
        {
            Matrix4x4 worldToLocalMatrix = transform.get_worldToLocalMatrix();
            Matrix4x4 matrix4x           = Matrix4x4.TRS(asset.position, asset.rotation, Vector3.get_one());
            Matrix4x4 matrix4x2          = Matrix4x4.TRS(track.position, track.rotation, Vector3.get_one());

            if (transform.get_parent() != null)
            {
                matrix4x2 = transform.get_parent().get_localToWorldMatrix() * matrix4x2;
            }
            Vector3    position = transform.get_position();
            Quaternion rotation = transform.get_rotation();

            transform.set_position(globalPosition);
            transform.set_rotation(globalRotation);
            Matrix4x4 localToWorldMatrix = transform.get_localToWorldMatrix();

            transform.set_position(position);
            transform.set_rotation(rotation);
            Matrix4x4 matrix4x3 = matrix4x2.get_inverse() * localToWorldMatrix * worldToLocalMatrix * matrix4x2 * matrix4x;

            return(TimelineAnimationUtilities.RigidTransform.Compose(matrix4x3.GetColumn(3), MathUtils.QuaternionFromMatrix(matrix4x3)));
        }
        static void WriteMatchFields(AnimationPlayableAsset asset, RigidTransform result, MatchTargetFields fields)
        {
            Vector3 position = asset.position;

            position.x = fields.HasAny(MatchTargetFields.PositionX) ? result.position.x : position.x;
            position.y = fields.HasAny(MatchTargetFields.PositionY) ? result.position.y : position.y;
            position.z = fields.HasAny(MatchTargetFields.PositionZ) ? result.position.z : position.z;

            asset.position = position;

            // check first to avoid unnecessary conversion errors
            if (fields.HasAny(MatchTargetFieldConstants.Rotation))
            {
                Vector3 eulers       = asset.eulerAngles;
                Vector3 resultEulers = result.rotation.eulerAngles;

                eulers.x = fields.HasAny(MatchTargetFields.RotationX) ? resultEulers.x : eulers.x;
                eulers.y = fields.HasAny(MatchTargetFields.RotationY) ? resultEulers.y : eulers.y;
                eulers.z = fields.HasAny(MatchTargetFields.RotationZ) ? resultEulers.z : eulers.z;

                asset.eulerAngles = AnimationUtility.GetClosestEuler(Quaternion.Euler(eulers), asset.eulerAngles, RotationOrder.OrderZXY);
            }
        }
        // Given a world space position and rotation, updates the clip offsets to match that
        public static RigidTransform UpdateClipOffsets(AnimationPlayableAsset asset, AnimationTrack track, Transform transform, Vector3 globalPosition, Quaternion globalRotation)
        {
            Matrix4x4 worldToLocal = transform.worldToLocalMatrix;
            Matrix4x4 clipMatrix   = Matrix4x4.TRS(asset.position, asset.rotation, Vector3.one);
            Matrix4x4 trackMatrix  = GetTrackMatrix(transform, track);


            // Use the transform to find the proper goal matrix with scale taken into account
            var oldPos = transform.position;
            var oldRot = transform.rotation;

            transform.position = globalPosition;
            transform.rotation = globalRotation;
            Matrix4x4 goal = transform.localToWorldMatrix;

            transform.position = oldPos;
            transform.rotation = oldRot;

            // compute the new clip matrix.
            Matrix4x4 newClip = trackMatrix.inverse * goal * worldToLocal * trackMatrix * clipMatrix;

            return(RigidTransform.Compose(newClip.GetColumn(3), MathUtils.QuaternionFromMatrix(newClip)));
        }
        void DoManipulators()
        {
            if (m_EditorClip == null || m_EditorClip.clip == null)
            {
                return;
            }

            AnimationPlayableAsset animationPlayable = m_EditorClip.clip.asset as AnimationPlayableAsset;
            AnimationTrack         track             = m_EditorClip.clip.parentTrack as AnimationTrack;
            Transform transform = GetTransform();

            if (transform != null && animationPlayable != null && m_OffsetEditMode != TimelineAnimationUtilities.OffsetEditMode.None && track != null)
            {
                UndoExtensions.RegisterPlayableAsset(animationPlayable, "Inspector");
                Vector3    position = transform.position;
                Quaternion rotation = transform.rotation;

                EditorGUI.BeginChangeCheck();
                if (m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Translation)
                {
                    position = Handles.PositionHandle(position, Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : rotation);
                }
                else if (m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Rotation)
                {
                    rotation = Handles.RotationHandle(rotation, position);
                }

                if (EditorGUI.EndChangeCheck())
                {
                    var res = TimelineAnimationUtilities.UpdateClipOffsets(animationPlayable, track, transform, position, rotation);
                    animationPlayable.position    = res.position;
                    animationPlayable.eulerAngles = AnimationUtility.GetClosestEuler(res.rotation, animationPlayable.eulerAngles, RotationOrder.OrderZXY);
                    Reevaluate();
                    Repaint();
                }
            }
        }
 public static void ConvertFromClipMode(this AnimationTrack track, TimelineAsset timeline)
 {
     if (track.CanConvertFromClipMode())
     {
         TimelineUndo.PushUndo(track, "Convert From Clip");
         TimelineClip timelineClip = track.clips[0];
         float        time         = (float)timelineClip.start;
         track.openClipTimeOffset        = 0.0;
         track.openClipPreExtrapolation  = timelineClip.preExtrapolationMode;
         track.openClipPostExtrapolation = timelineClip.postExtrapolationMode;
         AnimationPlayableAsset animationPlayableAsset = timelineClip.asset as AnimationPlayableAsset;
         if (animationPlayableAsset)
         {
             track.openClipOffsetPosition = animationPlayableAsset.position;
             track.openClipOffsetRotation = animationPlayableAsset.rotation;
         }
         AnimationClip animationClip = timelineClip.animationClip;
         float         num           = (float)timelineClip.timeScale;
         if (!Mathf.Approximately(num, 1f))
         {
             if (!Mathf.Approximately(num, 0f))
             {
                 num = 1f / num;
             }
             animationClip.ScaleTime(num);
         }
         TimelineUndo.PushUndo(animationClip, "Convert From Clip");
         animationClip.ShiftBySeconds(time);
         Object asset = timelineClip.asset;
         timelineClip.asset = null;
         ClipModifier.Delete(timeline, timelineClip);
         TimelineUndo.PushDestroyUndo(null, track, asset, "Convert From Clip");
         track.animClip = animationClip;
         EditorUtility.SetDirty(track);
     }
 }
        // 导出AnimationTrack
        private int ExportAnimationTrack(AnimationTrack animationTrack, JSONObject trackListArr, JSONObject clipListArr)
        {
            JSONObject trackJSON = GenerateBaseTrack(animationTrack, PlaybaleTrackTypeMap["AnimationTrack"]);

            trackJSON.AddField("applyAvatarMask", animationTrack.applyAvatarMask);
            JSONObject infiniteClipOffsetPositionArr = new JSONObject(JSONObject.Type.ARRAY);
            JSONObject infiniteClipOffsetRotationArr = new JSONObject(JSONObject.Type.ARRAY);

            trackJSON.AddField("infiniteClipOffsetPosition", infiniteClipOffsetPositionArr);
            trackJSON.AddField("infiniteClipOffsetRotation", infiniteClipOffsetRotationArr);
#if UNITY_2018_3_OR_NEWER
            trackJSON.AddField("trackOffset", TrackOffsetMap[animationTrack.trackOffset]);
#else
            if (animationTrack.applyOffsets)
            {
                trackJSON.AddField("trackOffset", TrackOffsetMap["ApplyTransformOffsets"]);
            }
            else
            {
                trackJSON.AddField("trackOffset", TrackOffsetMap["Auto"]);
            }
#endif
#if UNITY_2019_1_OR_NEWER
            infiniteClipOffsetPositionArr.Add(-animationTrack.infiniteClipOffsetPosition.x);
            infiniteClipOffsetPositionArr.Add(animationTrack.infiniteClipOffsetPosition.y);
            infiniteClipOffsetPositionArr.Add(animationTrack.infiniteClipOffsetPosition.z);
            infiniteClipOffsetRotationArr.Add(-animationTrack.infiniteClipOffsetRotation.x);
            infiniteClipOffsetRotationArr.Add(animationTrack.infiniteClipOffsetRotation.y);
            infiniteClipOffsetRotationArr.Add(animationTrack.infiniteClipOffsetRotation.z);
            infiniteClipOffsetRotationArr.Add(-animationTrack.infiniteClipOffsetRotation.w);
#else
            infiniteClipOffsetPositionArr.Add(-animationTrack.openClipOffsetPosition.x);
            infiniteClipOffsetPositionArr.Add(animationTrack.openClipOffsetPosition.y);
            infiniteClipOffsetPositionArr.Add(animationTrack.openClipOffsetPosition.z);
            infiniteClipOffsetRotationArr.Add(-animationTrack.openClipOffsetRotation.x);
            infiniteClipOffsetRotationArr.Add(animationTrack.openClipOffsetRotation.y);
            infiniteClipOffsetRotationArr.Add(animationTrack.openClipOffsetRotation.z);
            infiniteClipOffsetRotationArr.Add(-animationTrack.openClipOffsetRotation.w);
#endif
            if (animationTrack.avatarMask != null)
            {
                WXAvatarMask mask = new WXAvatarMask(animationTrack.avatarMask);
                string       uid  = AddDependencies(mask);
                trackJSON.AddField("avatarMask", uid);
            }
            else
            {
                trackJSON.AddField("avatarMask", new JSONObject(JSONObject.Type.NULL));
            }

            JSONObject positionArr = new JSONObject(JSONObject.Type.ARRAY);
            positionArr.Add(-animationTrack.position.x);
            positionArr.Add(animationTrack.position.y);
            positionArr.Add(animationTrack.position.z);
            trackJSON.AddField("position", positionArr);

            JSONObject rotationArr = new JSONObject(JSONObject.Type.ARRAY);
            rotationArr.Add(-animationTrack.rotation.x);
            rotationArr.Add(animationTrack.rotation.y);
            rotationArr.Add(animationTrack.rotation.z);
            rotationArr.Add(-animationTrack.rotation.w);
            trackJSON.AddField("rotation", rotationArr);

            JSONObject matchTargetFieldsJSON = new JSONObject(JSONObject.Type.OBJECT);
            trackJSON.AddField("matchTargetFields", matchTargetFieldsJSON);
            matchTargetFieldsJSON.AddField("PositionX", (animationTrack.matchTargetFields & MatchTargetFields.PositionX) == MatchTargetFields.PositionX);
            matchTargetFieldsJSON.AddField("PositionY", (animationTrack.matchTargetFields & MatchTargetFields.PositionY) == MatchTargetFields.PositionY);
            matchTargetFieldsJSON.AddField("PositionZ", (animationTrack.matchTargetFields & MatchTargetFields.PositionZ) == MatchTargetFields.PositionZ);
            matchTargetFieldsJSON.AddField("RotationX", (animationTrack.matchTargetFields & MatchTargetFields.RotationX) == MatchTargetFields.RotationX);
            matchTargetFieldsJSON.AddField("RotationY", (animationTrack.matchTargetFields & MatchTargetFields.RotationY) == MatchTargetFields.RotationY);
            matchTargetFieldsJSON.AddField("RotationZ", (animationTrack.matchTargetFields & MatchTargetFields.RotationZ) == MatchTargetFields.RotationZ);

            UnityEditor.SerializedObject   serializedObject = new UnityEditor.SerializedObject(animationTrack);
            UnityEditor.SerializedProperty serializedClip   = serializedObject.FindProperty("m_Clips");

            JSONObject clipsIndexArr = trackJSON.GetField("clips");
            if (animationTrack.inClipMode) // 普通clip
            // 貌似有时候序列化的m_Clips顺序跟 timelineClipList 的顺序对不上,但是很难复现。没有找到顺序可以必定对上的方法,先这样吧
            {
                IEnumerable <TimelineClip> timelineClipList = animationTrack.GetClips();
                int num = 0;
                foreach (TimelineClip timelineClip in timelineClipList)
                {
                    JSONObject clipJSON = GenerateBaseTimelineClip(timelineClip, PlaybaleClipTypeMap["Animation"]);
                    JSONObject clipData = new JSONObject(JSONObject.Type.OBJECT);
                    float      m_PostExtrapolationTime = (float)serializedClip.FindPropertyRelative("Array.data[" + num + "].m_PostExtrapolationTime").doubleValue;
                    float      m_PreExtrapolationTime  = (float)serializedClip.FindPropertyRelative("Array.data[" + num + "].m_PreExtrapolationTime").doubleValue;
                    clipJSON.SetField("postExtrapolationTime", m_PostExtrapolationTime);
                    clipJSON.SetField("preExtrapolationTime", m_PreExtrapolationTime);
                    clipJSON.AddField("data", clipData);

                    bool m_Recordable = serializedClip.FindPropertyRelative("Array.data[" + num + "].m_Recordable").boolValue;
                    clipData.AddField("recordable", m_Recordable);

                    string clipPath = ExportAnimationClip(timelineClip.animationClip);
                    if (string.IsNullOrEmpty(clipPath))
                    {
                        clipData.AddField("clip", JSONObject.nullJO);
                    }
                    else
                    {
                        clipData.AddField("clip", clipPath);
                    }


                    AnimationPlayableAsset asset = (AnimationPlayableAsset)timelineClip.asset;
                    // clipData.AddField("clipCaps", ClipCapsMap.ContainsKey(timelineClip.clipCaps) ? ClipCapsMap[timelineClip.clipCaps] : ClipCapsMap[ClipCaps.None]);
                    // clipData.AddField("duration", (float)asset.duration);
#if UNITY_2018_3_OR_NEWER
                    // 2018_3才开始支持
                    clipData.AddField("applyFootIK", asset.applyFootIK);
#else
                    clipData.AddField("applyFootIK", false);
#endif

#if UNITY_2019_1_OR_NEWER
                    // 2019_1才开始支持
                    clipData.AddField("loop", LoopModeMap[asset.loop]);
#else
                    clipData.AddField("loop", LoopModeMap["UseSourceAsset"]);
#endif

                    clipData.AddField("useTrackMatchFields", asset.useTrackMatchFields);

                    JSONObject clipMatchTargetFieldsJSON = new JSONObject(JSONObject.Type.OBJECT);
                    clipData.AddField("matchTargetFields", clipMatchTargetFieldsJSON);
                    clipMatchTargetFieldsJSON.AddField("PositionX", (asset.matchTargetFields & MatchTargetFields.PositionX) == MatchTargetFields.PositionX);
                    clipMatchTargetFieldsJSON.AddField("PositionY", (asset.matchTargetFields & MatchTargetFields.PositionY) == MatchTargetFields.PositionY);
                    clipMatchTargetFieldsJSON.AddField("PositionZ", (asset.matchTargetFields & MatchTargetFields.PositionZ) == MatchTargetFields.PositionZ);
                    clipMatchTargetFieldsJSON.AddField("RotationX", (asset.matchTargetFields & MatchTargetFields.RotationX) == MatchTargetFields.RotationX);
                    clipMatchTargetFieldsJSON.AddField("RotationY", (asset.matchTargetFields & MatchTargetFields.RotationY) == MatchTargetFields.RotationY);
                    clipMatchTargetFieldsJSON.AddField("RotationZ", (asset.matchTargetFields & MatchTargetFields.RotationZ) == MatchTargetFields.RotationZ);

                    JSONObject clipPositionArr = new JSONObject(JSONObject.Type.ARRAY);
                    clipPositionArr.Add(-asset.position.x);
                    clipPositionArr.Add(asset.position.y);
                    clipPositionArr.Add(asset.position.z);
                    clipData.AddField("position", clipPositionArr);

                    JSONObject clipRotationArr = new JSONObject(JSONObject.Type.ARRAY);
                    clipRotationArr.Add(-asset.rotation.x);
                    clipRotationArr.Add(asset.rotation.y);
                    clipRotationArr.Add(asset.rotation.z);
                    clipRotationArr.Add(-asset.rotation.w);
                    clipData.AddField("rotation", clipRotationArr);

                    clipsIndexArr.Add(ExportTimelineClip(clipJSON, clipListArr));
                    num++;
                }
            }
            else // infiniteClip
            {
#if UNITY_2019_1_OR_NEWER
                // 2019_1才开始支持
                AnimationClip infiniteClip = animationTrack.infiniteClip;
#else
                // 序列化取出私有变量
                UnityEditor.SerializedObject   trackSerializedObject = new UnityEditor.SerializedObject(animationTrack);
                UnityEditor.SerializedProperty animClipSerialize     = trackSerializedObject.FindProperty("m_AnimClip");
                AnimationClip infiniteClip = animClipSerialize.objectReferenceValue as AnimationClip;
#endif
                string infinityClipPath = ExportAnimationClip(infiniteClip);
                if (string.IsNullOrEmpty(infinityClipPath))
                {
                    trackJSON.SetField("infinityClip", JSONObject.nullJO);
                }
                else
                {
                    trackJSON.SetField("infinityClip", infinityClipPath);
                }
            }
            // 导出子track
            JSONObject childrenJSON = trackJSON.GetField("children");
            IEnumerable <TrackAsset> childTrackAssetList = animationTrack.GetChildTracks();
            List <int> indexList = ExportTrackList(childTrackAssetList, trackListArr, clipListArr);
            foreach (int index in indexList)
            {
                childrenJSON.Add(index);
            }
            return(ExportTrack(trackJSON, trackListArr));
        }