TimelineEditor.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor.Timeline.Actions;
  5. using UnityEngine;
  6. using UnityEngine.Playables;
  7. using UnityEngine.Timeline;
  8. namespace UnityEditor.Timeline
  9. {
  10. /// <summary>
  11. /// Information currently being edited in the Timeline Editor Window.
  12. /// </summary>
  13. public static class TimelineEditor
  14. {
  15. /// <summary>
  16. /// The PlayableDirector associated with the timeline currently being shown in the Timeline window.
  17. /// </summary>
  18. public static PlayableDirector inspectedDirector => state?.editSequence.director;
  19. /// <summary>
  20. /// The PlayableDirector responsible for the playback of the timeline currently being shown in the Timeline window.
  21. /// </summary>
  22. public static PlayableDirector masterDirector => state?.masterSequence.director;
  23. /// <summary>
  24. /// The TimelineAsset currently being shown in the Timeline window.
  25. /// </summary>
  26. public static TimelineAsset inspectedAsset => state?.editSequence.asset;
  27. /// <summary>
  28. /// The TimelineAsset at the root of the hierarchy currently being shown in the Timeline window.
  29. /// </summary>
  30. public static TimelineAsset masterAsset => state?.masterSequence.asset;
  31. /// <summary>
  32. /// The PlayableDirector currently being shown in the Timeline Editor Window.
  33. /// </summary>
  34. [Obsolete("playableDirector is ambiguous. Please select either inspectedDirector or masterDirector instead.", false)]
  35. public static PlayableDirector playableDirector
  36. {
  37. get { return inspectedDirector; }
  38. }
  39. /// <summary>
  40. /// The TimelineAsset currently being shown in the Timeline Editor Window.
  41. /// </summary>
  42. [Obsolete("timelineAsset is ambiguous. Please select either inspectedAsset or masterAsset instead.", false)]
  43. public static TimelineAsset timelineAsset
  44. {
  45. get { return inspectedAsset; }
  46. }
  47. /// <summary>
  48. /// <para>
  49. /// Refreshes the different components affected by the currently inspected
  50. /// <see cref="UnityEngine.Timeline.TimelineAsset"/>, based on the <see cref="RefreshReason"/> provided.
  51. /// </para>
  52. /// <para>
  53. /// For better performance, it is recommended that you invoke this method once, after you modify the
  54. /// <see cref="UnityEngine.Timeline.TimelineAsset"/>. You should also combine reasons using the <c>|</c> operator.
  55. /// </para>
  56. /// </summary>
  57. /// <remarks>
  58. /// Note: This operation is not synchronous. It is performed during the next GUI loop.
  59. /// </remarks>
  60. /// <param name="reason">The reason why a refresh should be performed.</param>
  61. public static void Refresh(RefreshReason reason)
  62. {
  63. if (state == null)
  64. return;
  65. if ((reason & RefreshReason.ContentsAddedOrRemoved) != 0)
  66. {
  67. state.Refresh();
  68. }
  69. else if ((reason & RefreshReason.ContentsModified) != 0)
  70. {
  71. state.rebuildGraph = true;
  72. }
  73. else if ((reason & RefreshReason.SceneNeedsUpdate) != 0)
  74. {
  75. state.Evaluate();
  76. }
  77. window.Repaint();
  78. }
  79. internal static TimelineWindow window => TimelineWindow.instance;
  80. internal static WindowState state => window == null ? null : window.state;
  81. internal static readonly Clipboard clipboard = new Clipboard();
  82. /// <summary>
  83. /// The list of clips selected in the TimelineEditor.
  84. /// </summary>
  85. public static TimelineClip[] selectedClips
  86. {
  87. get { return Selection.GetFiltered<EditorClip>(SelectionMode.Unfiltered).Select(e => e.clip).Where(x => x != null).ToArray(); }
  88. set
  89. {
  90. if (value == null || value.Length == 0)
  91. {
  92. Selection.objects = null;
  93. }
  94. else
  95. {
  96. var objects = new List<UnityEngine.Object>();
  97. foreach (var clip in value)
  98. {
  99. if (clip == null)
  100. continue;
  101. var editorClip = EditorClipFactory.GetEditorClip(clip);
  102. if (editorClip != null)
  103. objects.Add(editorClip);
  104. }
  105. Selection.objects = objects.ToArray();
  106. }
  107. }
  108. }
  109. /// <summary>
  110. /// The clip selected in the TimelineEditor.
  111. /// </summary>
  112. /// <remarks>
  113. /// If there are multiple clips selected, this property returns the first clip.
  114. /// </remarks>
  115. public static TimelineClip selectedClip
  116. {
  117. get
  118. {
  119. var editorClip = Selection.activeObject as EditorClip;
  120. if (editorClip != null)
  121. return editorClip.clip;
  122. return null;
  123. }
  124. set
  125. {
  126. var editorClip = (value != null) ? EditorClipFactory.GetEditorClip(value) : null;
  127. Selection.activeObject = editorClip;
  128. }
  129. }
  130. /// <summary>
  131. /// Local time (in seconds) of the inspected sequence.
  132. /// </summary>
  133. /// <exception cref="InvalidOperationException">Thrown if timeline window is not available.</exception>
  134. internal static double inspectedSequenceTime
  135. {
  136. get => state?.editSequence.time ?? 0;
  137. set
  138. {
  139. if (state == null)
  140. throw new InvalidOperationException("Cannot set time. Timeline Window may not be available.");
  141. state.editSequence.time = value;
  142. }
  143. }
  144. /// <summary>
  145. /// Global time (in seconds) of the master timeline.
  146. /// Same as local time if not inspected a subtimeline.
  147. /// </summary>
  148. /// <exception cref="InvalidOperationException">Thrown if timeline window is not available.</exception>
  149. internal static double masterSequenceTime
  150. {
  151. get => state?.editSequence.ToGlobalTime(state.editSequence.time) ?? 0;
  152. set
  153. {
  154. if (state == null)
  155. throw new InvalidOperationException("Cannot set time. Timeline Window may not be available.");
  156. state.masterSequence.time = value;
  157. }
  158. }
  159. /// <summary>
  160. /// Visible time range (in seconds) in Editor.
  161. /// x : min time
  162. /// y : max time
  163. /// </summary>
  164. /// <exception cref="InvalidOperationException">Thrown if timeline window is not available.</exception>
  165. internal static Vector2 visibleTimeRange
  166. {
  167. get => state?.timeAreaShownRange ?? TimelineAssetViewModel.TimeAreaDefaultRange;
  168. set
  169. {
  170. if (state == null)
  171. throw new InvalidOperationException("Cannot set visible time range. Timeline Window may not be available.");
  172. state.timeAreaShownRange = value;
  173. }
  174. }
  175. internal static ActionContext CurrentContext(Vector2? mousePos = null)
  176. {
  177. return new ActionContext
  178. {
  179. invocationTime = mousePos != null ? TimelineHelpers.GetCandidateTime(mousePos) : (double?)null,
  180. clips = SelectionManager.SelectedClips(),
  181. tracks = SelectionManager.SelectedTracks(),
  182. markers = SelectionManager.SelectedMarkers(),
  183. timeline = inspectedAsset,
  184. director = inspectedDirector
  185. };
  186. }
  187. }
  188. /// <summary>
  189. /// <see cref="TimelineEditor.Refresh"/> uses these flags to determine what needs to be refreshed or updated.
  190. /// </summary>
  191. /// <remarks>
  192. /// Use the <c>|</c> operator to combine flags.
  193. /// <example>
  194. /// <code source="../DocCodeExamples/TimelineEditorExamples.cs" region="declare-refreshReason" title="refreshReason"/>
  195. /// </example>
  196. /// </remarks>
  197. [Flags]
  198. public enum RefreshReason
  199. {
  200. /// <summary>
  201. /// Use this flag when a change to the Timeline requires that the Timeline window be redrawn.
  202. /// </summary>
  203. WindowNeedsRedraw = 1 << 0,
  204. /// <summary>
  205. /// Use this flag when a change to the Timeline requires that the Scene be updated.
  206. /// </summary>
  207. SceneNeedsUpdate = 1 << 1,
  208. /// <summary>
  209. /// Use this flag when a Timeline element was modified.
  210. /// </summary>
  211. ContentsModified = 1 << 2,
  212. /// <summary>
  213. /// Use this flag when an element was added to or removed from the Timeline.
  214. /// </summary>
  215. ContentsAddedOrRemoved = 1 << 3
  216. }
  217. }