TrackAssetRecordingExtensions.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEngine;
  4. using UnityEngine.Playables;
  5. using UnityEngine.Timeline;
  6. namespace UnityEditor.Timeline
  7. {
  8. static class TrackAssetRecordingExtensions
  9. {
  10. static readonly Dictionary<TrackAsset, AnimationClip> s_ActiveClips = new Dictionary<TrackAsset, AnimationClip>();
  11. internal static void OnRecordingArmed(this TrackAsset track, PlayableDirector director)
  12. {
  13. if (track == null)
  14. return;
  15. var animClip = track.FindRecordingAnimationClipAtTime(director.time);
  16. if (animClip == null)
  17. return;
  18. s_ActiveClips[track] = animClip;
  19. }
  20. internal static void OnRecordingTimeChanged(this TrackAsset track, PlayableDirector director)
  21. {
  22. if (track == null)
  23. return;
  24. var animClip = track.FindRecordingAnimationClipAtTime(director.time);
  25. AnimationClip prevClip = track.GetActiveRecordingAnimationClip();
  26. if (prevClip != animClip)
  27. {
  28. s_ActiveClips[track] = animClip;
  29. }
  30. }
  31. internal static void OnRecordingUnarmed(this TrackAsset track, PlayableDirector director)
  32. {
  33. s_ActiveClips.Remove(track);
  34. }
  35. internal static bool CanRecordAtTime(this TrackAsset track, double time)
  36. {
  37. // Animation Track
  38. var animTrack = track as AnimationTrack;
  39. if (animTrack != null)
  40. {
  41. if (!animTrack.inClipMode)
  42. return true;
  43. TimelineClip clip = null;
  44. return FindRecordingClipAtTime(track, time, out clip);
  45. }
  46. // Custom track
  47. return track.clips.Any(x => x.start < time + TimeUtility.kTimeEpsilon && x.HasAnyAnimatableParameters());
  48. }
  49. internal static AnimationClip GetActiveRecordingAnimationClip(this TrackAsset track)
  50. {
  51. AnimationClip clip = null;
  52. s_ActiveClips.TryGetValue(track, out clip);
  53. return clip;
  54. }
  55. internal static bool IsRecordingToClip(this TrackAsset track, TimelineClip clip)
  56. {
  57. if (track == null || clip == null)
  58. return false;
  59. var animClip = track.GetActiveRecordingAnimationClip();
  60. if (animClip == null)
  61. return false;
  62. if (animClip == clip.curves)
  63. return true;
  64. var animAsset = clip.asset as AnimationPlayableAsset;
  65. return animAsset != null && animClip == animAsset.clip;
  66. }
  67. // Finds the clip at the given time that recording should use
  68. // returns whether recording at this particular point is valid
  69. // The target clip will be returned, even if recording at that time is invalid
  70. // in case of recording in a blend OR recording to a non-timeline clip
  71. internal static bool FindRecordingClipAtTime(this TrackAsset track, double time, out TimelineClip target)
  72. {
  73. target = null;
  74. if (track == null)
  75. {
  76. return false;
  77. }
  78. var discreteTime = new DiscreteTime(time);
  79. // only animation tracks require the recordable flag as they are recording
  80. // to an animation clip
  81. bool requiresRecordable = (track as AnimationTrack) != null;
  82. if (requiresRecordable)
  83. {
  84. track.SortClips();
  85. var sortedByStartTime = track.clips;
  86. int i = 0;
  87. for (i = 0; i < sortedByStartTime.Length; i++)
  88. {
  89. var clip = sortedByStartTime[i];
  90. if (new DiscreteTime(clip.start) <= discreteTime && new DiscreteTime(clip.end) > discreteTime)
  91. {
  92. target = clip;
  93. // not recordable
  94. if (!clip.recordable)
  95. return false;
  96. // in a blend
  97. if (!Mathf.Approximately(1.0f, clip.EvaluateMixIn(time) * clip.EvaluateMixOut(time)))
  98. return false;
  99. return true;
  100. }
  101. if (new DiscreteTime(clip.start) > discreteTime)
  102. {
  103. break;
  104. }
  105. }
  106. return false;
  107. }
  108. // Recordable playable assets -- takes the last clip that matches
  109. track.SortClips();
  110. for (int i = 0; i < track.clips.Length; i++)
  111. {
  112. var clip = track.clips[i];
  113. if (clip.start <= time && clip.end >= time && clip.HasAnyAnimatableParameters())
  114. target = clip;
  115. if (clip.start > time)
  116. break;
  117. }
  118. return target != null;
  119. }
  120. // Given a track, return the animation clip
  121. internal static AnimationClip FindRecordingAnimationClipAtTime(this TrackAsset trackAsset, double time)
  122. {
  123. if (trackAsset == null)
  124. return null;
  125. AnimationTrack animTrack = trackAsset as AnimationTrack;
  126. if (animTrack != null && !animTrack.inClipMode)
  127. {
  128. return animTrack.infiniteClip;
  129. }
  130. TimelineClip displayBackground;
  131. trackAsset.FindRecordingClipAtTime(time, out displayBackground);
  132. if (displayBackground != null)
  133. {
  134. if (displayBackground.recordable)
  135. {
  136. AnimationPlayableAsset asset = displayBackground.asset as AnimationPlayableAsset;
  137. if (asset != null)
  138. return asset.clip;
  139. }
  140. else if (animTrack == null)
  141. {
  142. if (displayBackground.curves == null)
  143. displayBackground.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(displayBackground.parentTrack, TimelineClip.kDefaultCurvesName));
  144. return displayBackground.curves;
  145. }
  146. }
  147. else if (trackAsset.HasAnyAnimatableParameters())
  148. {
  149. if (trackAsset.curves == null)
  150. trackAsset.CreateCurves(AnimationTrackRecorder.GetUniqueRecordedClipName(trackAsset.timelineAsset, TrackAsset.kDefaultCurvesName));
  151. return trackAsset.curves;
  152. }
  153. return null;
  154. }
  155. internal static void ClearRecordingState()
  156. {
  157. s_ActiveClips.Clear();
  158. }
  159. }
  160. }