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