A game about forced loneliness, made by TACStudios
1using System.Linq;
2using UnityEngine;
3using UnityEngine.Timeline;
4
5namespace UnityEditor.Timeline
6{
7 partial class TimelineWindow
8 {
9 static readonly GUIContent[] k_TimeReferenceGUIContents =
10 {
11 L10n.TextContent("Local", "Display time based on the current timeline."),
12 L10n.TextContent("Global", "Display time based on the master timeline.")
13 };
14
15 TimelineMarkerHeaderGUI m_MarkerHeaderGUI;
16
17 void MarkerHeaderGUI()
18 {
19 var timelineAsset = state.editSequence.asset;
20 if (timelineAsset == null)
21 return;
22
23 if (m_MarkerHeaderGUI == null)
24 m_MarkerHeaderGUI = new TimelineMarkerHeaderGUI(timelineAsset, state);
25 m_MarkerHeaderGUI.Draw(markerHeaderRect, markerContentRect, state);
26 }
27
28 void DrawTransportToolbar()
29 {
30 using (new EditorGUI.DisabledScope(currentMode.PreviewState(state) == TimelineModeGUIState.Disabled))
31 {
32 PreviewModeButtonGUI();
33 }
34
35 using (new EditorGUI.DisabledScope(currentMode.ToolbarState(state) == TimelineModeGUIState.Disabled))
36 {
37 GotoBeginingSequenceGUI();
38 PreviousEventButtonGUI();
39 PlayButtonGUI();
40 NextEventButtonGUI();
41 GotoEndSequenceGUI();
42 PlayRangeButtonGUI();
43 TimeCodeGUI();
44 ReferenceTimeGUI();
45 }
46 }
47
48 void PreviewModeButtonGUI()
49 {
50 if (state.ignorePreview && !Application.isPlaying)
51 {
52 GUILayout.Label(DirectorStyles.previewDisabledContent, DirectorStyles.Instance.previewButtonDisabled);
53 return;
54 }
55
56 EditorGUI.BeginChangeCheck();
57 var enabled = state.previewMode;
58 enabled = GUILayout.Toggle(enabled, DirectorStyles.previewContent, EditorStyles.toolbarButton);
59 if (EditorGUI.EndChangeCheck())
60 {
61 // turn off auto play as well, so it doesn't auto reenable
62 if (!enabled)
63 {
64 state.SetPlaying(false);
65 state.recording = false;
66 }
67
68 state.previewMode = enabled;
69
70 // if we are successfully enabled, rebuild the graph so initial states work correctly
71 // Note: testing both values because previewMode setter can "fail"
72 if (enabled && state.previewMode)
73 state.rebuildGraph = true;
74 }
75 }
76
77 void GotoBeginingSequenceGUI()
78 {
79 if (GUILayout.Button(DirectorStyles.gotoBeginingContent, EditorStyles.toolbarButton))
80 {
81 state.editSequence.time = 0;
82 state.EnsurePlayHeadIsVisible();
83 }
84 }
85
86 // in the editor the play button starts/stops simulation
87 void PlayButtonGUIEditor()
88 {
89 EditorGUI.BeginChangeCheck();
90 var isPlaying = GUILayout.Toggle(state.playing, DirectorStyles.playContent, EditorStyles.toolbarButton);
91 if (EditorGUI.EndChangeCheck())
92 {
93 state.SetPlaying(isPlaying);
94 }
95 }
96
97 // in playmode the button reflects the playing state.
98 // needs to disabled if playing is not possible
99 void PlayButtonGUIPlayMode()
100 {
101 bool buttonEnabled = state.masterSequence.director != null &&
102 state.masterSequence.director.isActiveAndEnabled;
103 using (new EditorGUI.DisabledScope(!buttonEnabled))
104 {
105 PlayButtonGUIEditor();
106 }
107 }
108
109 void PlayButtonGUI()
110 {
111 if (!Application.isPlaying)
112 PlayButtonGUIEditor();
113 else
114 PlayButtonGUIPlayMode();
115 }
116
117 void NextEventButtonGUI()
118 {
119 if (GUILayout.Button(DirectorStyles.nextFrameContent, EditorStyles.toolbarButton))
120 {
121 state.referenceSequence.frame += 1;
122 }
123 }
124
125 void PreviousEventButtonGUI()
126 {
127 if (GUILayout.Button(DirectorStyles.previousFrameContent, EditorStyles.toolbarButton))
128 {
129 state.referenceSequence.frame -= 1;
130 }
131 }
132
133 void GotoEndSequenceGUI()
134 {
135 if (GUILayout.Button(DirectorStyles.gotoEndContent, EditorStyles.toolbarButton))
136 {
137 state.editSequence.time = state.editSequence.asset.duration;
138 state.EnsurePlayHeadIsVisible();
139 }
140 }
141
142 void PlayRangeButtonGUI()
143 {
144 using (new EditorGUI.DisabledScope(state.ignorePreview || state.IsEditingASubTimeline()))
145 {
146 state.playRangeEnabled = GUILayout.Toggle(state.playRangeEnabled, DirectorStyles.Instance.playrangeContent, EditorStyles.toolbarButton);
147 }
148 }
149
150 void AddButtonGUI()
151 {
152 if (currentMode.trackOptionsState.newButton == TimelineModeGUIState.Hidden)
153 return;
154
155 using (new EditorGUI.DisabledScope(currentMode.trackOptionsState.newButton == TimelineModeGUIState.Disabled))
156 {
157 if (EditorGUILayout.DropdownButton(DirectorStyles.newContent, FocusType.Passive, EditorStyles.toolbarPopup))
158 {
159 // if there is 1 and only 1 track selected, AND it's a group, add to that group
160 var groupTracks = SelectionManager.SelectedTracks().ToList();
161 if (groupTracks.Any(x => x.GetType() != typeof(GroupTrack) || x.lockedInHierarchy))
162 groupTracks = null;
163
164 SequencerContextMenu.ShowNewTracksContextMenu(groupTracks, state, EditorGUILayout.s_LastRect);
165 }
166 }
167 }
168
169 void ShowMarkersButton()
170 {
171 var asset = state.editSequence.asset;
172 if (asset == null)
173 return;
174
175 var content = state.showMarkerHeader ? DirectorStyles.showMarkersOn : DirectorStyles.showMarkersOff;
176 SetShowMarkerHeader(GUILayout.Toggle(state.showMarkerHeader, content, DirectorStyles.Instance.showMarkersBtn));
177 }
178
179 internal void SetShowMarkerHeader(bool newValue)
180 {
181 TimelineAsset asset = state.editSequence.asset;
182 if (state.showMarkerHeader == newValue || asset == null)
183 return;
184
185 string undoOperation = L10n.Tr("Toggle Show Markers");
186 if (newValue)
187 {
188 //Create the marker track if it does not exist
189 TimelineUndo.PushUndo(asset, undoOperation);
190 asset.CreateMarkerTrack();
191 }
192 else
193 {
194 SelectionManager.Remove(asset.markerTrack);
195
196 if (asset.markerTrack != null && asset.markerTrack.isEmpty)
197 {
198 TimelineUndo.PushUndo(asset, undoOperation);
199 asset.RemoveMarkerTrack();
200 }
201 }
202
203 if (asset.markerTrack != null)
204 {
205 asset.markerTrack.SetShowTrackMarkers(newValue);
206 }
207 }
208
209 static void EditModeToolbarGUI(TimelineMode mode)
210 {
211 using (new EditorGUI.DisabledScope(mode.EditModeButtonsState(instance.state) == TimelineModeGUIState.Disabled))
212 {
213 var editType = EditMode.editType;
214
215 EditorGUI.BeginChangeCheck();
216 var mixIcon = editType == EditMode.EditType.Mix ? DirectorStyles.mixOn : DirectorStyles.mixOff;
217 GUILayout.Toggle(editType == EditMode.EditType.Mix, mixIcon, DirectorStyles.Instance.editModeBtn);
218 if (EditorGUI.EndChangeCheck())
219 EditMode.editType = EditMode.EditType.Mix;
220
221 EditorGUI.BeginChangeCheck();
222 var rippleIcon = editType == EditMode.EditType.Ripple ? DirectorStyles.rippleOn : DirectorStyles.rippleOff;
223 GUILayout.Toggle(editType == EditMode.EditType.Ripple, rippleIcon, DirectorStyles.Instance.editModeBtn);
224 if (EditorGUI.EndChangeCheck())
225 EditMode.editType = EditMode.EditType.Ripple;
226
227 EditorGUI.BeginChangeCheck();
228 var replaceIcon = editType == EditMode.EditType.Replace ? DirectorStyles.replaceOn : DirectorStyles.replaceOff;
229 GUILayout.Toggle(editType == EditMode.EditType.Replace, replaceIcon, DirectorStyles.Instance.editModeBtn);
230 if (EditorGUI.EndChangeCheck())
231 EditMode.editType = EditMode.EditType.Replace;
232 }
233 }
234
235 // Draws the box to enter the time field
236 void TimeCodeGUI()
237 {
238 const string timeFieldHint = "TimelineWindow-TimeCodeGUI";
239
240 EditorGUI.BeginChangeCheck();
241 var currentTime = state.editSequence.asset != null ? TimeReferenceUtility.ToTimeString(state.editSequence.time, "0.####") : "0";
242 var r = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.toolbarTextField, GUILayout.Width(WindowConstants.timeCodeWidth));
243 var id = GUIUtility.GetControlID(timeFieldHint.GetHashCode(), FocusType.Keyboard, r);
244 var newCurrentTime = EditorGUI.DelayedTextFieldInternal(r, id, GUIContent.none, currentTime, null, EditorStyles.toolbarTextField);
245
246 if (EditorGUI.EndChangeCheck())
247 state.editSequence.time = TimeReferenceUtility.FromTimeString(newCurrentTime);
248 }
249
250 void ReferenceTimeGUI()
251 {
252 if (!state.IsEditingASubTimeline())
253 return;
254
255 EditorGUI.BeginChangeCheck();
256 state.timeReferenceMode = (TimeReferenceMode)EditorGUILayout.CycleButton((int)state.timeReferenceMode, k_TimeReferenceGUIContents, DirectorStyles.Instance.timeReferenceButton);
257 if (EditorGUI.EndChangeCheck())
258 OnTimeReferenceModeChanged();
259 }
260
261 void OnTimeReferenceModeChanged()
262 {
263 m_TimeAreaDirty = true;
264 InitTimeAreaFrameRate();
265 SyncTimeAreaShownRange();
266
267 foreach (var inspector in InspectorWindow.GetAllInspectorWindows())
268 {
269 inspector.Repaint();
270 }
271 }
272
273 void DrawHeaderEditButtons()
274 {
275 if (state.editSequence.asset == null)
276 return;
277
278 using (new GUILayout.HorizontalScope(EditorStyles.toolbar, GUILayout.Width(sequenceHeaderRect.width)))
279 {
280 GUILayout.Space(DirectorStyles.kBaseIndent);
281 AddButtonGUI();
282 GUILayout.FlexibleSpace();
283 EditModeToolbarGUI(currentMode);
284 ShowMarkersButton();
285 EditorGUILayout.Space();
286 }
287 }
288 }
289}