暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

TrimClip.cs 7.4KB

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