AnimationTrackExtensions.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System.Linq;
  2. using UnityEngine;
  3. using UnityEngine.Timeline;
  4. namespace UnityEditor.Timeline
  5. {
  6. static class AnimationTrackExtensions
  7. {
  8. public static void ConvertToClipMode(this AnimationTrack track)
  9. {
  10. if (!track.CanConvertToClipMode())
  11. return;
  12. TimelineUndo.PushUndo(track, "Convert To Clip");
  13. if (!track.infiniteClip.empty)
  14. {
  15. var animClip = track.infiniteClip;
  16. TimelineUndo.PushUndo(animClip, "Convert To Clip");
  17. TimelineUndo.PushUndo(track, "Convert To Clip");
  18. var start = AnimationClipCurveCache.Instance.GetCurveInfo(animClip).keyTimes.FirstOrDefault();
  19. animClip.ShiftBySeconds(-start);
  20. track.infiniteClip = null;
  21. var clip = track.CreateClip(animClip);
  22. clip.start = start;
  23. clip.preExtrapolationMode = track.infiniteClipPreExtrapolation;
  24. clip.postExtrapolationMode = track.infiniteClipPostExtrapolation;
  25. clip.recordable = true;
  26. if (Mathf.Abs(animClip.length) < TimelineClip.kMinDuration)
  27. {
  28. clip.duration = 1;
  29. }
  30. var animationAsset = clip.asset as AnimationPlayableAsset;
  31. if (animationAsset)
  32. {
  33. animationAsset.position = track.infiniteClipOffsetPosition;
  34. animationAsset.eulerAngles = track.infiniteClipOffsetEulerAngles;
  35. // going to / from infinite mode should reset this. infinite mode
  36. animationAsset.removeStartOffset = track.infiniteClipRemoveOffset;
  37. animationAsset.applyFootIK = track.infiniteClipApplyFootIK;
  38. animationAsset.loop = track.infiniteClipLoop;
  39. track.infiniteClipOffsetPosition = Vector3.zero;
  40. track.infiniteClipOffsetEulerAngles = Vector3.zero;
  41. }
  42. track.CalculateExtrapolationTimes();
  43. }
  44. track.infiniteClip = null;
  45. EditorUtility.SetDirty(track);
  46. }
  47. public static void ConvertFromClipMode(this AnimationTrack track, TimelineAsset timeline)
  48. {
  49. if (!track.CanConvertFromClipMode())
  50. return;
  51. TimelineUndo.PushUndo(track, "Convert From Clip");
  52. var clip = track.clips[0];
  53. var delta = (float)clip.start;
  54. track.infiniteClipTimeOffset = 0.0f;
  55. track.infiniteClipPreExtrapolation = clip.preExtrapolationMode;
  56. track.infiniteClipPostExtrapolation = clip.postExtrapolationMode;
  57. var animAsset = clip.asset as AnimationPlayableAsset;
  58. if (animAsset)
  59. {
  60. track.infiniteClipOffsetPosition = animAsset.position;
  61. track.infiniteClipOffsetEulerAngles = animAsset.eulerAngles;
  62. track.infiniteClipRemoveOffset = animAsset.removeStartOffset;
  63. track.infiniteClipApplyFootIK = animAsset.applyFootIK;
  64. track.infiniteClipLoop = animAsset.loop;
  65. }
  66. // clone it, it may not be in the same asset
  67. var animClip = clip.animationClip;
  68. float scale = (float)clip.timeScale;
  69. if (!Mathf.Approximately(scale, 1.0f))
  70. {
  71. if (!Mathf.Approximately(scale, 0.0f))
  72. scale = 1.0f / scale;
  73. animClip.ScaleTime(scale);
  74. }
  75. TimelineUndo.PushUndo(animClip, "Convert From Clip");
  76. animClip.ShiftBySeconds(delta);
  77. // manually delete the clip
  78. var asset = clip.asset;
  79. clip.asset = null;
  80. // Remove the clip, remove old assets
  81. ClipModifier.Delete(timeline, clip);
  82. TimelineUndo.PushDestroyUndo(null, track, asset, "Convert From Clip");
  83. track.infiniteClip = animClip;
  84. EditorUtility.SetDirty(track);
  85. }
  86. public static bool CanConvertToClipMode(this AnimationTrack track)
  87. {
  88. if (track == null || track.inClipMode)
  89. return false;
  90. return (track.infiniteClip != null && !track.infiniteClip.empty);
  91. }
  92. // Requirements to go from clip mode
  93. // - one clip, recordable, and animation clip belongs to the same asset as the track
  94. public static bool CanConvertFromClipMode(this AnimationTrack track)
  95. {
  96. if ((track == null) ||
  97. (!track.inClipMode) ||
  98. (track.clips.Length != 1) ||
  99. (track.clips[0].start < 0) ||
  100. (!track.clips[0].recordable))
  101. return false;
  102. var asset = track.clips[0].asset as AnimationPlayableAsset;
  103. if (asset == null)
  104. return false;
  105. return TimelineHelpers.HaveSameContainerAsset(track, asset.clip);
  106. }
  107. }
  108. }