TrimClip.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using UnityEngine;
  6. using UnityEngine.Timeline;
  7. namespace UnityEditor.Timeline
  8. {
  9. class TrimClip : Manipulator
  10. {
  11. class TrimClipAttractionHandler : IAttractionHandler
  12. {
  13. public void OnAttractedEdge(IAttractable attractable, ManipulateEdges manipulateEdges, AttractedEdge edge, double time)
  14. {
  15. var clipGUI = attractable as TimelineClipGUI;
  16. if (clipGUI == null)
  17. return;
  18. var clipItem = ItemsUtils.ToItem(clipGUI.clip);
  19. if (manipulateEdges == ManipulateEdges.Right)
  20. {
  21. bool affectTimeScale = IsAffectingTimeScale(clipGUI.clip);
  22. EditMode.TrimEnd(clipItem, time, affectTimeScale);
  23. }
  24. else if (manipulateEdges == ManipulateEdges.Left)
  25. {
  26. bool affectTimeScale = IsAffectingTimeScale(clipGUI.clip);
  27. EditMode.TrimStart(clipItem, time, affectTimeScale);
  28. }
  29. }
  30. private bool IsAffectingTimeScale(TimelineClip clip)
  31. {
  32. bool autoScale = (clip.clipCaps & ClipCaps.AutoScale) == ClipCaps.AutoScale;
  33. // TODO Do not use Event.current from here.
  34. bool affectTimeScale = (autoScale && (Event.current.modifiers != EventModifiers.Shift))
  35. || (!autoScale && (Event.current.modifiers == EventModifiers.Shift));
  36. return affectTimeScale;
  37. }
  38. }
  39. bool m_IsCaptured;
  40. TimelineClipHandle m_TrimClipHandler;
  41. double m_OriginalDuration;
  42. double m_OriginalTimeScale;
  43. double m_OriginalEaseInDuration;
  44. double m_OriginalEaseOutDuration;
  45. bool m_UndoSaved;
  46. SnapEngine m_SnapEngine;
  47. readonly StringBuilder m_OverlayText = new StringBuilder();
  48. readonly List<string> m_OverlayStrings = new List<string>();
  49. static readonly double kEpsilon = 0.0000001;
  50. protected override bool MouseDown(Event evt, WindowState state)
  51. {
  52. var handle = PickerUtils.TopmostPickedItem() as TimelineClipHandle;
  53. if (handle == null)
  54. return false;
  55. if (handle.clipGUI.clip.parentTrack != null && handle.clipGUI.clip.parentTrack.lockedInHierarchy)
  56. return false;
  57. m_TrimClipHandler = handle;
  58. m_IsCaptured = true;
  59. state.AddCaptured(this);
  60. m_UndoSaved = false;
  61. var clip = m_TrimClipHandler.clipGUI.clip;
  62. m_OriginalDuration = clip.duration;
  63. m_OriginalTimeScale = clip.timeScale;
  64. m_OriginalEaseInDuration = clip.easeInDuration;
  65. m_OriginalEaseOutDuration = clip.easeOutDuration;
  66. RefreshOverlayStrings(m_TrimClipHandler, state);
  67. // in ripple trim, the right edge moves and needs to snap
  68. var edges = ManipulateEdges.Right;
  69. if (EditMode.editType != EditMode.EditType.Ripple && m_TrimClipHandler.trimDirection == TrimEdge.Start)
  70. edges = ManipulateEdges.Left;
  71. m_SnapEngine = new SnapEngine(m_TrimClipHandler.clipGUI, new TrimClipAttractionHandler(), edges, state,
  72. evt.mousePosition);
  73. EditMode.BeginTrim(ItemsUtils.ToItem(clip), m_TrimClipHandler.trimDirection);
  74. return true;
  75. }
  76. protected override bool MouseUp(Event evt, WindowState state)
  77. {
  78. if (!m_IsCaptured)
  79. return false;
  80. m_IsCaptured = false;
  81. m_TrimClipHandler = null;
  82. m_UndoSaved = false;
  83. m_SnapEngine = null;
  84. EditMode.FinishTrim();
  85. state.captured.Clear();
  86. return true;
  87. }
  88. protected override bool MouseDrag(Event evt, WindowState state)
  89. {
  90. if (state.editSequence.isReadOnly)
  91. return false;
  92. if (!m_IsCaptured)
  93. return false;
  94. var uiClip = m_TrimClipHandler.clipGUI;
  95. if (!m_UndoSaved)
  96. {
  97. UndoExtensions.RegisterClip(uiClip.clip, "Trim Clip");
  98. if (TimelineUtility.IsRecordableAnimationClip(uiClip.clip))
  99. {
  100. TimelineUndo.PushUndo(uiClip.clip.animationClip, "Trim Clip");
  101. }
  102. m_UndoSaved = true;
  103. }
  104. //Reset to original ease values. The trim operation will calculate the proper blend values.
  105. uiClip.clip.easeInDuration = m_OriginalEaseInDuration;
  106. uiClip.clip.easeOutDuration = m_OriginalEaseOutDuration;
  107. if (m_SnapEngine != null)
  108. m_SnapEngine.Snap(evt.mousePosition, evt.modifiers);
  109. RefreshOverlayStrings(m_TrimClipHandler, state);
  110. if (Selection.activeObject != null)
  111. EditorUtility.SetDirty(Selection.activeObject);
  112. // updates the duration of the graph without rebuilding
  113. state.UpdateRootPlayableDuration(state.editSequence.duration);
  114. return true;
  115. }
  116. public override void Overlay(Event evt, WindowState state)
  117. {
  118. if (!m_IsCaptured)
  119. return;
  120. EditMode.DrawTrimGUI(state, m_TrimClipHandler.clipGUI, m_TrimClipHandler.trimDirection);
  121. bool trimStart = m_TrimClipHandler.trimDirection == TrimEdge.Start;
  122. TimeIndicator.Draw(state, trimStart ? m_TrimClipHandler.clipGUI.start : m_TrimClipHandler.clipGUI.end);
  123. if (m_SnapEngine != null)
  124. m_SnapEngine.OnGUI(trimStart, !trimStart);
  125. if (m_OverlayStrings.Count > 0)
  126. {
  127. const float padding = 4.0f;
  128. var labelStyle = TimelineWindow.styles.tinyFont;
  129. var longestLine = labelStyle.CalcSize(
  130. new GUIContent(m_OverlayStrings.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur)));
  131. var stringLength = longestLine.x + padding;
  132. var lineHeight = longestLine.y + padding;
  133. var r = new Rect(evt.mousePosition.x - (stringLength / 2.0f),
  134. m_TrimClipHandler.clipGUI.rect.yMax,
  135. stringLength, lineHeight);
  136. foreach (var s in m_OverlayStrings)
  137. {
  138. GUI.Label(r, s, labelStyle);
  139. r.y += lineHeight;
  140. }
  141. }
  142. }
  143. void RefreshOverlayStrings(TimelineClipHandle handle, WindowState state)
  144. {
  145. m_OverlayStrings.Clear();
  146. m_OverlayText.Length = 0;
  147. var differenceDuration = handle.clipGUI.clip.duration - m_OriginalDuration;
  148. bool hasDurationDelta = Math.Abs(differenceDuration) > kEpsilon;
  149. if (state.timeInFrames)
  150. {
  151. var durationInFrame = handle.clipGUI.clip.duration * state.referenceSequence.frameRate;
  152. m_OverlayText.Append("duration: ").Append(durationInFrame.ToString("f2")).Append(" frames");
  153. if (hasDurationDelta)
  154. {
  155. m_OverlayText.Append(" (");
  156. if (differenceDuration > 0.0)
  157. m_OverlayText.Append("+");
  158. var valueInFrame = differenceDuration * state.referenceSequence.frameRate;
  159. m_OverlayText.Append(valueInFrame.ToString("f2")).Append(" frames)");
  160. }
  161. }
  162. else
  163. {
  164. m_OverlayText.Append("duration: ").Append(handle.clipGUI.clip.duration.ToString("f2")).Append("s");
  165. if (hasDurationDelta)
  166. {
  167. m_OverlayText.Append(" (");
  168. if (differenceDuration > 0.0)
  169. m_OverlayText.Append("+");
  170. m_OverlayText.Append(differenceDuration.ToString("f2")).Append("s)");
  171. }
  172. }
  173. m_OverlayStrings.Add(m_OverlayText.ToString());
  174. m_OverlayText.Length = 0;
  175. var differenceSpeed = m_OriginalTimeScale - handle.clipGUI.clip.timeScale;
  176. if (Math.Abs(differenceSpeed) > kEpsilon)
  177. {
  178. m_OverlayText.Append("speed: ").Append(handle.clipGUI.clip.timeScale.ToString("p2"));
  179. m_OverlayText.Append(" (");
  180. if (differenceSpeed > 0.0)
  181. m_OverlayText.Append("+");
  182. m_OverlayText.Append(differenceSpeed.ToString("p2")).Append(")");
  183. m_OverlayStrings.Add(m_OverlayText.ToString());
  184. }
  185. }
  186. }
  187. }