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