123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- using UnityEngine.Playables;
- using UnityEngine.Timeline;
- namespace UnityEditor.Timeline
- {
- static class TrackAssetRecordingExtensions
- {
- static readonly Dictionary<TrackAsset, AnimationClip> s_ActiveClips = new Dictionary<TrackAsset, AnimationClip>();
- internal static void OnRecordingArmed(this TrackAsset track, PlayableDirector director)
- {
- if (track == null)
- return;
- var animClip = track.FindRecordingAnimationClipAtTime(director.time);
- if (animClip == null)
- return;
- s_ActiveClips[track] = animClip;
- }
- internal static void OnRecordingTimeChanged(this TrackAsset track, PlayableDirector director)
- {
- if (track == null)
- return;
- var animClip = track.FindRecordingAnimationClipAtTime(director.time);
- AnimationClip prevClip = track.GetActiveRecordingAnimationClip();
- if (prevClip != animClip)
- {
- s_ActiveClips[track] = animClip;
- }
- }
- internal static void OnRecordingUnarmed(this TrackAsset track, PlayableDirector director)
- {
- s_ActiveClips.Remove(track);
- }
- internal static bool CanRecordAtTime(this TrackAsset track, double time)
- {
- // Animation Track
- var animTrack = track as AnimationTrack;
- if (animTrack != null)
- {
- if (!animTrack.inClipMode)
- return true;
- TimelineClip clip = null;
- return FindRecordingClipAtTime(track, time, out clip);
- }
- // Custom track
- return track.clips.Any(x => x.start < time + TimeUtility.kTimeEpsilon && x.HasAnyAnimatableParameters());
- }
- internal static AnimationClip GetActiveRecordingAnimationClip(this TrackAsset track)
- {
- AnimationClip clip = null;
- s_ActiveClips.TryGetValue(track, out clip);
- return clip;
- }
- internal static bool IsRecordingToClip(this TrackAsset track, TimelineClip clip)
- {
- if (track == null || clip == null)
- return false;
- var animClip = track.GetActiveRecordingAnimationClip();
- if (animClip == null)
- return false;
- if (animClip == clip.curves)
- return true;
- var animAsset = clip.asset as AnimationPlayableAsset;
- return animAsset != null && animClip == animAsset.clip;
- }
- // Finds the clip at the given time that recording should use
- // returns whether recording at this particular point is valid
- // The target clip will be returned, even if recording at that time is invalid
- // in case of recording in a blend OR recording to a non-timeline clip
- internal static bool FindRecordingClipAtTime(this TrackAsset track, double time, out TimelineClip target)
- {
- target = null;
- if (track == null)
- {
- return false;
- }
- var discreteTime = new DiscreteTime(time);
- // only animation tracks require the recordable flag as they are recording
- // to an animation clip
- bool requiresRecordable = (track as AnimationTrack) != null;
- if (requiresRecordable)
- {
- track.SortClips();
- var sortedByStartTime = track.clips;
- int i = 0;
- for (i = 0; i < sortedByStartTime.Length; i++)
- {
- var clip = sortedByStartTime[i];
- if (new DiscreteTime(clip.start) <= discreteTime && new DiscreteTime(clip.end) > discreteTime)
- {
- target = clip;
- // not recordable
- if (!clip.recordable)
- return false;
- // in a blend
- if (!Mathf.Approximately(1.0f, clip.EvaluateMixIn(time) * clip.EvaluateMixOut(time)))
- return false;
- return true;
- }
- if (new DiscreteTime(clip.start) > discreteTime)
- {
- break;
- }
- }
- return false;
- }
- // Recordable playable assets -- takes the last clip that matches
- track.SortClips();
- for (int i = 0; i < track.clips.Length; i++)
- {
- var clip = track.clips[i];
- if (clip.start <= time && clip.end >= time && clip.HasAnyAnimatableParameters())
- target = clip;
- if (clip.start > time)
- break;
- }
- return target != null;
- }
- // 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;
- }
- internal static void ClearRecordingState()
- {
- s_ActiveClips.Clear();
- }
- }
- }
|