Keine Beschreibung
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

WindowState.cs 37KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditorInternal;
  5. #if UNITY_2021_2_OR_NEWER
  6. using UnityEditor.SceneManagement;
  7. #else
  8. using UnityEditor.Experimental.SceneManagement;
  9. #endif
  10. using UnityEngine;
  11. using UnityEngine.Playables;
  12. using UnityEngine.Timeline;
  13. #if !UNITY_2020_2_OR_NEWER
  14. using UnityEngine.Experimental.Animations;
  15. #endif
  16. using UnityEngine.Animations;
  17. namespace UnityEditor.Timeline
  18. {
  19. delegate bool PendingUpdateDelegate(WindowState state, Event currentEvent);
  20. /// <summary>
  21. /// Interface for faking purposes
  22. /// </summary>
  23. interface IWindowState
  24. {
  25. ISequenceState masterSequence { get; }
  26. ISequenceState editSequence { get; }
  27. IEnumerable<ISequenceState> allSequences { get; }
  28. void SetCurrentSequence(TimelineAsset timelineAsset, PlayableDirector director, TimelineClip hostClip);
  29. void PopSequencesUntilCount(int count);
  30. IEnumerable<SequenceContext> GetSubSequences();
  31. }
  32. class WindowState : IWindowState
  33. {
  34. const int k_TimeCodeTextFieldId = 3790;
  35. readonly TimelineWindow m_Window;
  36. bool m_Recording;
  37. readonly SpacePartitioner m_SpacePartitioner = new SpacePartitioner();
  38. readonly SpacePartitioner m_HeaderSpacePartitioner = new SpacePartitioner();
  39. readonly List<Manipulator> m_CaptureSession = new List<Manipulator>();
  40. int m_DirtyStamp;
  41. float m_BindingAreaWidth = WindowConstants.defaultBindingAreaWidth;
  42. bool m_MustRebuildGraph;
  43. float m_LastTime;
  44. readonly PropertyCollector m_PropertyCollector = new PropertyCollector();
  45. static AnimationModeDriver s_PreviewDriver;
  46. List<Animator> m_PreviewedAnimators;
  47. List<Component> m_PreviewedComponents;
  48. IEnumerable<IAnimationWindowPreview> previewedComponents =>
  49. m_PreviewedComponents.Where(component => component != null).Cast<IAnimationWindowPreview>();
  50. public static double kTimeEpsilon { get { return TimeUtility.kTimeEpsilon; } }
  51. public static readonly float kMaxShownTime = (float)TimeUtility.k_MaxTimelineDurationInSeconds;
  52. static readonly ISequenceState k_NullSequenceState = new NullSequenceState();
  53. // which tracks are armed for record - only one allowed per 'actor'
  54. Dictionary<TrackAsset, TrackAsset> m_ArmedTracks = new Dictionary<TrackAsset, TrackAsset>();
  55. TimelineWindow.TimelineWindowPreferences m_Preferences;
  56. List<PendingUpdateDelegate> m_OnStartFrameUpdates;
  57. List<PendingUpdateDelegate> m_OnEndFrameUpdates;
  58. readonly SequenceHierarchy m_SequenceHierarchy;
  59. public event Action<WindowState, Event> windowOnGuiStarted;
  60. public event Action<bool> OnPlayStateChange;
  61. public event System.Action OnDirtyStampChange;
  62. public event System.Action OnRebuildGraphChange;
  63. public event System.Action OnTimeChange;
  64. public event System.Action OnRecordingChange;
  65. public event System.Action OnBeforeSequenceChange;
  66. public event System.Action OnAfterSequenceChange;
  67. public WindowState(TimelineWindow w, SequenceHierarchy hierarchy)
  68. {
  69. m_Window = w;
  70. m_Preferences = w.preferences;
  71. hierarchy.Init(this);
  72. m_SequenceHierarchy = hierarchy;
  73. TimelinePlayable.muteAudioScrubbing = muteAudioScrubbing;
  74. }
  75. public static AnimationModeDriver previewDriver
  76. {
  77. get
  78. {
  79. if (s_PreviewDriver == null)
  80. {
  81. s_PreviewDriver = ScriptableObject.CreateInstance<AnimationModeDriver>();
  82. AnimationPreviewUtilities.s_PreviewDriver = s_PreviewDriver;
  83. }
  84. return s_PreviewDriver;
  85. }
  86. }
  87. public EditorWindow editorWindow
  88. {
  89. get { return m_Window; }
  90. }
  91. public ISequenceState editSequence
  92. {
  93. get
  94. {
  95. // Using "null" ISequenceState to avoid checking against null all the time.
  96. // This *should* be removed in a phase 2 of refactoring, where we make sure
  97. // to pass around the correct state object instead of letting clients dig
  98. // into the WindowState for whatever they want.
  99. return m_SequenceHierarchy.editSequence ?? k_NullSequenceState;
  100. }
  101. }
  102. public ISequenceState masterSequence
  103. {
  104. get { return m_SequenceHierarchy.masterSequence ?? k_NullSequenceState; }
  105. }
  106. public ISequenceState referenceSequence
  107. {
  108. get { return timeReferenceMode == TimeReferenceMode.Local ? editSequence : masterSequence; }
  109. }
  110. public IEnumerable<ISequenceState> allSequences
  111. {
  112. get { return m_SequenceHierarchy.allSequences; }
  113. }
  114. public bool rebuildGraph
  115. {
  116. get { return m_MustRebuildGraph; }
  117. set { SyncNotifyValue(ref m_MustRebuildGraph, value, OnRebuildGraphChange); }
  118. }
  119. public float mouseDragLag { get; set; }
  120. public SpacePartitioner spacePartitioner
  121. {
  122. get { return m_SpacePartitioner; }
  123. }
  124. public SpacePartitioner headerSpacePartitioner
  125. {
  126. get { return m_HeaderSpacePartitioner; }
  127. }
  128. public List<Manipulator> captured
  129. {
  130. get { return m_CaptureSession; }
  131. }
  132. public void AddCaptured(Manipulator manipulator)
  133. {
  134. if (!m_CaptureSession.Contains(manipulator))
  135. m_CaptureSession.Add(manipulator);
  136. }
  137. public void RemoveCaptured(Manipulator manipulator)
  138. {
  139. m_CaptureSession.Remove(manipulator);
  140. }
  141. public bool isJogging { get; set; }
  142. public int viewStateHash { get; private set; }
  143. public float bindingAreaWidth
  144. {
  145. get { return m_BindingAreaWidth; }
  146. set { m_BindingAreaWidth = value; }
  147. }
  148. public float sequencerHeaderWidth
  149. {
  150. get { return editSequence.viewModel.sequencerHeaderWidth; }
  151. set
  152. {
  153. editSequence.viewModel.sequencerHeaderWidth = Mathf.Clamp(value, WindowConstants.minHeaderWidth, WindowConstants.maxHeaderWidth);
  154. }
  155. }
  156. public float mainAreaWidth { get; set; }
  157. public float trackScale
  158. {
  159. get { return editSequence.viewModel.trackScale; }
  160. set
  161. {
  162. editSequence.viewModel.trackScale = value;
  163. m_Window.treeView.CalculateRowRects();
  164. }
  165. }
  166. public int dirtyStamp
  167. {
  168. get { return m_DirtyStamp; }
  169. private set { SyncNotifyValue(ref m_DirtyStamp, value, OnDirtyStampChange); }
  170. }
  171. public bool showQuadTree { get; set; }
  172. public bool canRecord
  173. {
  174. get { return AnimationMode.InAnimationMode(previewDriver) || !AnimationMode.InAnimationMode(); }
  175. }
  176. public bool recording
  177. {
  178. get
  179. {
  180. if (!previewMode)
  181. m_Recording = false;
  182. return m_Recording;
  183. }
  184. // set can only be used to disable recording
  185. set
  186. {
  187. if (ignorePreview)
  188. return;
  189. // force preview mode on
  190. if (value)
  191. previewMode = true;
  192. bool newValue = value;
  193. if (!previewMode)
  194. newValue = false;
  195. if (newValue && m_ArmedTracks.Count == 0)
  196. {
  197. Debug.LogError("Cannot enable recording without an armed track");
  198. newValue = false;
  199. }
  200. if (!newValue)
  201. m_ArmedTracks.Clear();
  202. if (newValue != m_Recording)
  203. {
  204. if (newValue)
  205. AnimationMode.StartAnimationRecording();
  206. else
  207. AnimationMode.StopAnimationRecording();
  208. InspectorWindow.RepaintAllInspectors();
  209. }
  210. SyncNotifyValue(ref m_Recording, newValue, OnRecordingChange);
  211. }
  212. }
  213. public bool previewMode
  214. {
  215. get { return ignorePreview || AnimationMode.InAnimationMode(previewDriver); }
  216. set
  217. {
  218. if (ignorePreview)
  219. return;
  220. bool inAnimationMode = AnimationMode.InAnimationMode(previewDriver);
  221. if (!value)
  222. {
  223. if (inAnimationMode)
  224. {
  225. Stop();
  226. OnStopPreview();
  227. AnimationMode.StopAnimationMode(previewDriver);
  228. AnimationPropertyContextualMenu.Instance.SetResponder(null);
  229. previewedDirectors = null;
  230. }
  231. }
  232. else if (!inAnimationMode)
  233. {
  234. editSequence.time = editSequence.viewModel.windowTime;
  235. EvaluateImmediate(); // does appropriate caching prior to enabling
  236. }
  237. }
  238. }
  239. public bool playing
  240. {
  241. get
  242. {
  243. return masterSequence.director != null && masterSequence.director.state == PlayState.Playing;
  244. }
  245. }
  246. public float playbackSpeed { get; set; }
  247. public bool frameSnap
  248. {
  249. get { return TimelinePreferences.instance.snapToFrame; }
  250. set { TimelinePreferences.instance.snapToFrame = value; }
  251. }
  252. public bool edgeSnaps
  253. {
  254. get { return TimelinePreferences.instance.edgeSnap; }
  255. set { TimelinePreferences.instance.edgeSnap = value; }
  256. }
  257. public bool muteAudioScrubbing
  258. {
  259. get { return !TimelinePreferences.instance.audioScrubbing; }
  260. set
  261. {
  262. TimelinePreferences.instance.audioScrubbing = !value;
  263. TimelinePlayable.muteAudioScrubbing = value;
  264. RebuildPlayableGraph();
  265. }
  266. }
  267. public TimeReferenceMode timeReferenceMode
  268. {
  269. get { return m_Preferences.timeReferenceMode; }
  270. set { m_Preferences.timeReferenceMode = value; }
  271. }
  272. public TimeFormat timeFormat
  273. {
  274. get { return TimelinePreferences.instance.timeFormat; }
  275. set { TimelinePreferences.instance.timeFormat = value; }
  276. }
  277. public bool showAudioWaveform
  278. {
  279. get { return TimelinePreferences.instance.showAudioWaveform; }
  280. set { TimelinePreferences.instance.showAudioWaveform = value; }
  281. }
  282. public Vector2 playRange
  283. {
  284. get { return masterSequence.viewModel.timeAreaPlayRange; }
  285. set { masterSequence.viewModel.timeAreaPlayRange = ValidatePlayRange(value); }
  286. }
  287. public bool showMarkerHeader
  288. {
  289. get { return editSequence.asset != null && editSequence.asset.markerTrack != null && editSequence.asset.markerTrack.GetShowMarkers(); }
  290. set { GetWindow().SetShowMarkerHeader(value); }
  291. }
  292. public EditMode.EditType editType
  293. {
  294. get { return m_Preferences.editType; }
  295. set { m_Preferences.editType = value; }
  296. }
  297. public PlaybackScrollMode autoScrollMode
  298. {
  299. get { return TimelinePreferences.instance.playbackScrollMode; }
  300. set { TimelinePreferences.instance.playbackScrollMode = value; }
  301. }
  302. public List<PlayableDirector> previewedDirectors { get; private set; }
  303. public void OnDestroy()
  304. {
  305. if (!ignorePreview)
  306. Stop();
  307. if (m_OnStartFrameUpdates != null)
  308. m_OnStartFrameUpdates.Clear();
  309. if (m_OnEndFrameUpdates != null)
  310. m_OnEndFrameUpdates.Clear();
  311. m_SequenceHierarchy.Clear();
  312. windowOnGuiStarted = null;
  313. }
  314. public void OnSceneSaved()
  315. {
  316. // the director will reset it's time when the scene is saved.
  317. EnsureWindowTimeConsistency();
  318. }
  319. public void SetCurrentSequence(TimelineAsset timelineAsset, PlayableDirector director, TimelineClip hostClip)
  320. {
  321. if (OnBeforeSequenceChange != null)
  322. OnBeforeSequenceChange.Invoke();
  323. OnCurrentDirectorWillChange();
  324. if (hostClip == null || timelineAsset == null)
  325. {
  326. m_PropertyCollector.Clear();
  327. m_SequenceHierarchy.Clear();
  328. }
  329. if (timelineAsset != null)
  330. m_SequenceHierarchy.Add(timelineAsset, director, hostClip);
  331. if (OnAfterSequenceChange != null)
  332. OnAfterSequenceChange.Invoke();
  333. }
  334. public void PopSequencesUntilCount(int count)
  335. {
  336. if (count >= m_SequenceHierarchy.count) return;
  337. if (count < 1) return;
  338. if (OnBeforeSequenceChange != null)
  339. OnBeforeSequenceChange.Invoke();
  340. var nextDirector = m_SequenceHierarchy.GetStateAtIndex(count - 1).director;
  341. OnCurrentDirectorWillChange();
  342. m_SequenceHierarchy.RemoveUntilCount(count);
  343. EnsureWindowTimeConsistency();
  344. if (OnAfterSequenceChange != null)
  345. OnAfterSequenceChange.Invoke();
  346. }
  347. public SequencePath GetCurrentSequencePath()
  348. {
  349. return m_SequenceHierarchy.ToSequencePath();
  350. }
  351. public void SetCurrentSequencePath(SequencePath path, bool forceRebuild)
  352. {
  353. if (!m_SequenceHierarchy.NeedsUpdate(path, forceRebuild))
  354. return;
  355. if (OnBeforeSequenceChange != null)
  356. OnBeforeSequenceChange.Invoke();
  357. m_SequenceHierarchy.FromSequencePath(path, forceRebuild);
  358. if (OnAfterSequenceChange != null)
  359. OnAfterSequenceChange.Invoke();
  360. }
  361. public IEnumerable<ISequenceState> GetAllSequences()
  362. {
  363. return m_SequenceHierarchy.allSequences;
  364. }
  365. public IEnumerable<SequenceContext> GetSubSequences()
  366. {
  367. var contexts =
  368. editSequence.asset?.flattenedTracks
  369. .SelectMany(x => x.clips)
  370. .Where((TimelineUtility.HasCustomEditor))
  371. .SelectMany((clip =>
  372. TimelineUtility.GetSubTimelines(clip, TimelineEditor.inspectedDirector)
  373. .Select(director => new SequenceContext(director, clip))));
  374. return contexts;
  375. }
  376. public void Reset()
  377. {
  378. recording = false;
  379. previewMode = false;
  380. }
  381. public double GetSnappedTimeAtMousePosition(Vector2 mousePos)
  382. {
  383. return TimeReferenceUtility.SnapToFrameIfRequired(ScreenSpacePixelToTimeAreaTime(mousePos.x));
  384. }
  385. static void SyncNotifyValue<T>(ref T oldValue, T newValue, System.Action changeStateCallback)
  386. {
  387. var stateChanged = false;
  388. if (oldValue == null)
  389. {
  390. oldValue = newValue;
  391. stateChanged = true;
  392. }
  393. else
  394. {
  395. if (!oldValue.Equals(newValue))
  396. {
  397. oldValue = newValue;
  398. stateChanged = true;
  399. }
  400. }
  401. if (stateChanged && changeStateCallback != null)
  402. {
  403. changeStateCallback.Invoke();
  404. }
  405. }
  406. public TimelineWindowAnalytics analytics = new TimelineWindowAnalytics();
  407. public void SetTimeAreaTransform(Vector2 newTranslation, Vector2 newScale)
  408. {
  409. m_Window.timeArea.SetTransform(newTranslation, newScale);
  410. TimeAreaChanged();
  411. }
  412. public void SetTimeAreaShownRange(float min, float max)
  413. {
  414. m_Window.timeArea.SetShownHRange(min, max);
  415. TimeAreaChanged();
  416. }
  417. internal void TimeAreaChanged()
  418. {
  419. if (editSequence.asset != null)
  420. {
  421. editSequence.viewModel.timeAreaShownRange = new Vector2(m_Window.timeArea.shownArea.x, m_Window.timeArea.shownArea.xMax);
  422. }
  423. }
  424. public void ResetPreviewMode()
  425. {
  426. var mode = previewMode;
  427. previewMode = false;
  428. previewMode = mode;
  429. }
  430. public bool TimeIsInRange(float value)
  431. {
  432. Rect shownArea = m_Window.timeArea.shownArea;
  433. return value >= shownArea.x && value <= shownArea.xMax;
  434. }
  435. public bool RangeIsVisible(Range range)
  436. {
  437. var shownArea = m_Window.timeArea.shownArea;
  438. return range.start < shownArea.xMax && range.end > shownArea.xMin;
  439. }
  440. public void EnsurePlayHeadIsVisible()
  441. {
  442. double minDisplayedTime = PixelToTime(timeAreaRect.xMin);
  443. double maxDisplayedTime = PixelToTime(timeAreaRect.xMax);
  444. double currentTime = editSequence.time;
  445. if (currentTime >= minDisplayedTime && currentTime <= maxDisplayedTime)
  446. return;
  447. float displayedTimeRange = (float)(maxDisplayedTime - minDisplayedTime);
  448. float minimumTimeToDisplay = (float)currentTime - displayedTimeRange / 2.0f;
  449. float maximumTimeToDisplay = (float)currentTime + displayedTimeRange / 2.0f;
  450. SetTimeAreaShownRange(minimumTimeToDisplay, maximumTimeToDisplay);
  451. }
  452. public void SetPlayHeadToMiddle()
  453. {
  454. double minDisplayedTime = PixelToTime(timeAreaRect.xMin);
  455. double maxDisplayedTime = PixelToTime(timeAreaRect.xMax);
  456. double currentTime = editSequence.time;
  457. float displayedTimeRange = (float)(maxDisplayedTime - minDisplayedTime);
  458. if (currentTime >= minDisplayedTime && currentTime <= maxDisplayedTime)
  459. {
  460. if (currentTime < minDisplayedTime + displayedTimeRange / 2)
  461. return;
  462. }
  463. const float kCatchUpSpeed = 3f;
  464. float realDelta = Mathf.Clamp(Time.realtimeSinceStartup - m_LastTime, 0f, 1f) * kCatchUpSpeed;
  465. float scrollCatchupAmount = kCatchUpSpeed * realDelta * displayedTimeRange / 2;
  466. if (currentTime < minDisplayedTime)
  467. {
  468. SetTimeAreaShownRange((float)currentTime, (float)currentTime + displayedTimeRange);
  469. }
  470. else if (currentTime > maxDisplayedTime)
  471. {
  472. SetTimeAreaShownRange((float)currentTime - displayedTimeRange + scrollCatchupAmount, (float)currentTime + scrollCatchupAmount);
  473. }
  474. else if (currentTime > minDisplayedTime + displayedTimeRange / 2)
  475. {
  476. float targetMinDisplayedTime = Mathf.Min((float)minDisplayedTime + scrollCatchupAmount,
  477. (float)(currentTime - displayedTimeRange / 2));
  478. SetTimeAreaShownRange(targetMinDisplayedTime, targetMinDisplayedTime + displayedTimeRange);
  479. }
  480. }
  481. internal void UpdateLastFrameTime()
  482. {
  483. m_LastTime = Time.realtimeSinceStartup;
  484. }
  485. public Vector2 timeAreaShownRange
  486. {
  487. get
  488. {
  489. if (m_Window.state.editSequence.asset != null)
  490. return editSequence.viewModel.timeAreaShownRange;
  491. return TimelineAssetViewModel.TimeAreaDefaultRange;
  492. }
  493. set
  494. {
  495. SetTimeAreaShownRange(value.x, value.y);
  496. }
  497. }
  498. public Vector2 timeAreaTranslation
  499. {
  500. get { return m_Window.timeArea.translation; }
  501. }
  502. public Vector2 timeAreaScale
  503. {
  504. get { return m_Window.timeArea.scale; }
  505. }
  506. public Rect timeAreaRect
  507. {
  508. get
  509. {
  510. var sequenceContentRect = m_Window.sequenceContentRect;
  511. return new Rect(
  512. sequenceContentRect.x,
  513. WindowConstants.timeAreaYPosition,
  514. Mathf.Max(sequenceContentRect.width, WindowConstants.timeAreaMinWidth),
  515. WindowConstants.timeAreaHeight
  516. );
  517. }
  518. }
  519. public float windowHeight
  520. {
  521. get { return m_Window.position.height; }
  522. }
  523. public bool playRangeEnabled
  524. {
  525. get { return !ignorePreview && masterSequence.viewModel.playRangeEnabled && !IsEditingASubTimeline(); }
  526. set
  527. {
  528. if (!ignorePreview)
  529. masterSequence.viewModel.playRangeEnabled = value;
  530. }
  531. }
  532. public bool ignorePreview
  533. {
  534. get
  535. {
  536. var shouldIgnorePreview = masterSequence.asset != null && !masterSequence.asset.editorSettings.scenePreview;
  537. return Application.isPlaying || shouldIgnorePreview;
  538. }
  539. }
  540. public TimelineWindow GetWindow()
  541. {
  542. return m_Window;
  543. }
  544. public void Play()
  545. {
  546. if (masterSequence.director == null)
  547. return;
  548. if (!previewMode)
  549. previewMode = true;
  550. if (previewMode)
  551. {
  552. if (masterSequence.time > masterSequence.duration)
  553. masterSequence.time = 0;
  554. #if TIMELINE_FRAMEACCURATE
  555. if (TimelinePreferences.instance.playbackLockedToFrame)
  556. {
  557. FrameRate frameRate = FrameRate.DoubleToFrameRate(masterSequence.asset.editorSettings.frameRate);
  558. masterSequence.director.Play(frameRate);
  559. }
  560. else
  561. {
  562. masterSequence.director.Play();
  563. }
  564. #else
  565. masterSequence.director.Play();
  566. #endif
  567. masterSequence.director.ProcessPendingGraphChanges();
  568. PlayableDirector.ResetFrameTiming();
  569. InvokePlayStateChangeCallback(true);
  570. }
  571. }
  572. public void Pause()
  573. {
  574. if (masterSequence.director != null)
  575. {
  576. masterSequence.director.Pause();
  577. masterSequence.director.ProcessPendingGraphChanges();
  578. SynchronizeSequencesAfterPlayback();
  579. InvokePlayStateChangeCallback(false);
  580. }
  581. }
  582. public void SetPlaying(bool start)
  583. {
  584. if (start && !playing)
  585. {
  586. Play();
  587. }
  588. if (!start && playing)
  589. {
  590. Pause();
  591. }
  592. analytics.SendPlayEvent(start);
  593. }
  594. public void Stop()
  595. {
  596. if (masterSequence.director != null)
  597. {
  598. masterSequence.director.Stop();
  599. masterSequence.director.ProcessPendingGraphChanges();
  600. InvokePlayStateChangeCallback(false);
  601. }
  602. }
  603. void InvokePlayStateChangeCallback(bool isPlaying)
  604. {
  605. if (OnPlayStateChange != null)
  606. OnPlayStateChange.Invoke(isPlaying);
  607. }
  608. public void RebuildPlayableGraph()
  609. {
  610. if (masterSequence.director != null)
  611. {
  612. masterSequence.director.RebuildGraph();
  613. // rebuild both the parent and the edit sequences. control tracks don't necessary
  614. // rebuild the subdirector on recreation
  615. if (editSequence.director != null && editSequence.director != masterSequence.director)
  616. {
  617. editSequence.director.RebuildGraph();
  618. }
  619. }
  620. }
  621. public void Evaluate()
  622. {
  623. if (masterSequence.director != null)
  624. {
  625. if (!EditorApplication.isPlaying && !previewMode)
  626. GatherProperties(masterSequence.director);
  627. ForceTimeOnDirector(masterSequence.director);
  628. masterSequence.director.DeferredEvaluate();
  629. if (EditorApplication.isPlaying == false)
  630. {
  631. PlayModeView.RepaintAll();
  632. SceneView.RepaintAll();
  633. AudioMixerWindow.RepaintAudioMixerWindow();
  634. }
  635. }
  636. }
  637. public void EvaluateImmediate()
  638. {
  639. if (masterSequence.director != null && masterSequence.director.isActiveAndEnabled)
  640. {
  641. if (!EditorApplication.isPlaying && !previewMode)
  642. GatherProperties(masterSequence.director);
  643. if (previewMode)
  644. {
  645. ForceTimeOnDirector(masterSequence.director);
  646. masterSequence.director.ProcessPendingGraphChanges();
  647. masterSequence.director.Evaluate();
  648. }
  649. }
  650. }
  651. public void Refresh()
  652. {
  653. CheckRecordingState();
  654. dirtyStamp = dirtyStamp + 1;
  655. rebuildGraph = true;
  656. }
  657. public void UpdateViewStateHash()
  658. {
  659. viewStateHash = timeAreaTranslation.GetHashCode()
  660. .CombineHash(timeAreaScale.GetHashCode())
  661. .CombineHash(trackScale.GetHashCode());
  662. }
  663. public bool IsEditingASubTimeline()
  664. {
  665. return editSequence != masterSequence;
  666. }
  667. public bool IsEditingAnEmptyTimeline()
  668. {
  669. return editSequence.asset == null;
  670. }
  671. public bool IsEditingAPrefabAsset()
  672. {
  673. var stage = PrefabStageUtility.GetCurrentPrefabStage();
  674. return stage != null && editSequence.director != null && stage.IsPartOfPrefabContents(editSequence.director.gameObject);
  675. }
  676. public bool IsCurrentEditingASequencerTextField()
  677. {
  678. if (editSequence.asset == null)
  679. return false;
  680. if (k_TimeCodeTextFieldId == GUIUtility.keyboardControl)
  681. return true;
  682. return editSequence.asset.flattenedTracks.Count(t => t.GetInstanceID() == GUIUtility.keyboardControl) != 0;
  683. }
  684. public float TimeToTimeAreaPixel(double t) // TimeToTimeAreaPixel
  685. {
  686. float pixelX = (float)t;
  687. pixelX *= timeAreaScale.x;
  688. pixelX += timeAreaTranslation.x + sequencerHeaderWidth;
  689. return pixelX;
  690. }
  691. public float TimeToScreenSpacePixel(double time)
  692. {
  693. float pixelX = (float)time;
  694. pixelX *= timeAreaScale.x;
  695. pixelX += timeAreaTranslation.x;
  696. return pixelX;
  697. }
  698. public float TimeToPixel(double time)
  699. {
  700. return m_Window.timeArea.TimeToPixel((float)time, timeAreaRect);
  701. }
  702. public float PixelToTime(float pixel)
  703. {
  704. return m_Window.timeArea.PixelToTime(pixel, timeAreaRect);
  705. }
  706. public float PixelDeltaToDeltaTime(float p)
  707. {
  708. return PixelToTime(p) - PixelToTime(0);
  709. }
  710. public float TimeAreaPixelToTime(float pixel)
  711. {
  712. return PixelToTime(pixel);
  713. }
  714. public float ScreenSpacePixelToTimeAreaTime(float p)
  715. {
  716. // transform into track space by offsetting the pixel by the screen-space offset of the time area
  717. p -= timeAreaRect.x;
  718. return TrackSpacePixelToTimeAreaTime(p);
  719. }
  720. public float TrackSpacePixelToTimeAreaTime(float p)
  721. {
  722. p -= timeAreaTranslation.x;
  723. if (timeAreaScale.x > 0.0f)
  724. return p / timeAreaScale.x;
  725. return p;
  726. }
  727. public void OffsetTimeArea(int pixels)
  728. {
  729. Vector3 tx = timeAreaTranslation;
  730. tx.x += pixels;
  731. SetTimeAreaTransform(tx, timeAreaScale);
  732. }
  733. public GameObject GetSceneReference(TrackAsset asset)
  734. {
  735. if (editSequence.director == null)
  736. return null; // no player bound
  737. return TimelineUtility.GetSceneGameObject(editSequence.director, asset);
  738. }
  739. public void CalculateRowRects()
  740. {
  741. // arming a track might add inline curve tracks, recalc track heights
  742. if (m_Window != null && m_Window.treeView != null)
  743. m_Window.treeView.CalculateRowRects();
  744. }
  745. // Only one track within a 'track' hierarchy can be armed
  746. public void ArmForRecord(TrackAsset track)
  747. {
  748. m_ArmedTracks[TimelineUtility.GetSceneReferenceTrack(track)] = track;
  749. if (track != null && !recording)
  750. recording = true;
  751. if (!recording)
  752. return;
  753. track.OnRecordingArmed(editSequence.director);
  754. CalculateRowRects();
  755. }
  756. public void UnarmForRecord(TrackAsset track)
  757. {
  758. m_ArmedTracks.Remove(TimelineUtility.GetSceneReferenceTrack(track));
  759. if (m_ArmedTracks.Count == 0)
  760. recording = false;
  761. track.OnRecordingUnarmed(editSequence.director);
  762. }
  763. public void UpdateRecordingState()
  764. {
  765. if (recording)
  766. {
  767. foreach (var track in m_ArmedTracks.Values)
  768. {
  769. if (track != null)
  770. track.OnRecordingTimeChanged(editSequence.director);
  771. }
  772. }
  773. }
  774. public bool IsTrackRecordable(TrackAsset track)
  775. {
  776. // A track with animated parameters can always be recorded to
  777. return IsArmedForRecord(track) || track.HasAnyAnimatableParameters();
  778. }
  779. public bool IsArmedForRecord(TrackAsset track)
  780. {
  781. return track == GetArmedTrack(track);
  782. }
  783. public TrackAsset GetArmedTrack(TrackAsset track)
  784. {
  785. TrackAsset outTrack;
  786. m_ArmedTracks.TryGetValue(TimelineUtility.GetSceneReferenceTrack(track), out outTrack);
  787. return outTrack;
  788. }
  789. void CheckRecordingState()
  790. {
  791. // checks for deleted tracks, and makes sure the recording state matches
  792. if (m_ArmedTracks.Any(t => t.Value == null))
  793. {
  794. m_ArmedTracks = m_ArmedTracks.Where(t => t.Value != null).ToDictionary(t => t.Key, t => t.Value);
  795. if (m_ArmedTracks.Count == 0)
  796. recording = false;
  797. }
  798. }
  799. void OnCurrentDirectorWillChange()
  800. {
  801. if (ignorePreview)
  802. return;
  803. SynchronizeViewModelTime(editSequence);
  804. Stop();
  805. rebuildGraph = true; // needed for asset previews
  806. }
  807. public void GatherProperties(PlayableDirector director)
  808. {
  809. if (director == null || Application.isPlaying)
  810. return;
  811. var asset = director.playableAsset as TimelineAsset;
  812. if (asset != null && !asset.editorSettings.scenePreview)
  813. return;
  814. if (!previewMode)
  815. {
  816. AnimationMode.StartAnimationMode(previewDriver);
  817. OnStartPreview(director);
  818. AnimationPropertyContextualMenu.Instance.SetResponder(new TimelineRecordingContextualResponder(this));
  819. if (!previewMode)
  820. return;
  821. EnsureWindowTimeConsistency();
  822. }
  823. if (asset != null)
  824. {
  825. m_PropertyCollector.Reset();
  826. m_PropertyCollector.PushActiveGameObject(null); // avoid overflow on unbound tracks
  827. asset.GatherProperties(director, m_PropertyCollector);
  828. }
  829. }
  830. void OnStartPreview(PlayableDirector director)
  831. {
  832. previewedDirectors = TimelineUtility.GetAllDirectorsInHierarchy(director).ToList();
  833. if (previewedDirectors == null)
  834. return;
  835. m_PreviewedAnimators = TimelineUtility.GetBindingsFromDirectors<Animator>(previewedDirectors).ToList();
  836. m_PreviewedComponents = m_PreviewedAnimators
  837. .SelectMany(animator => animator.GetComponents<IAnimationWindowPreview>()
  838. .Cast<Component>())
  839. .ToList();
  840. foreach (var previewedComponent in previewedComponents)
  841. {
  842. previewedComponent.StartPreview();
  843. }
  844. }
  845. void OnStopPreview()
  846. {
  847. if (m_PreviewedComponents != null)
  848. {
  849. foreach (var previewComponent in previewedComponents)
  850. {
  851. previewComponent.StopPreview();
  852. }
  853. m_PreviewedComponents = null;
  854. }
  855. if (m_PreviewedAnimators != null)
  856. {
  857. foreach (var previewAnimator in m_PreviewedAnimators)
  858. {
  859. if (previewAnimator != null)
  860. {
  861. previewAnimator.UnbindAllHandles();
  862. }
  863. }
  864. m_PreviewedAnimators = null;
  865. }
  866. }
  867. internal void ProcessStartFramePendingUpdates()
  868. {
  869. if (m_OnStartFrameUpdates != null)
  870. m_OnStartFrameUpdates.RemoveAll(callback => callback.Invoke(this, Event.current));
  871. }
  872. internal void ProcessEndFramePendingUpdates()
  873. {
  874. if (m_OnEndFrameUpdates != null)
  875. m_OnEndFrameUpdates.RemoveAll(callback => callback.Invoke(this, Event.current));
  876. }
  877. public void AddStartFrameDelegate(PendingUpdateDelegate updateDelegate)
  878. {
  879. if (m_OnStartFrameUpdates == null)
  880. m_OnStartFrameUpdates = new List<PendingUpdateDelegate>();
  881. if (m_OnStartFrameUpdates.Contains(updateDelegate))
  882. return;
  883. m_OnStartFrameUpdates.Add(updateDelegate);
  884. }
  885. public void AddEndFrameDelegate(PendingUpdateDelegate updateDelegate)
  886. {
  887. if (m_OnEndFrameUpdates == null)
  888. m_OnEndFrameUpdates = new List<PendingUpdateDelegate>();
  889. if (m_OnEndFrameUpdates.Contains(updateDelegate))
  890. return;
  891. m_OnEndFrameUpdates.Add(updateDelegate);
  892. }
  893. internal void InvokeWindowOnGuiStarted(Event evt)
  894. {
  895. if (windowOnGuiStarted != null)
  896. windowOnGuiStarted.Invoke(this, evt);
  897. }
  898. public void UpdateRootPlayableDuration(double duration)
  899. {
  900. if (editSequence.director != null)
  901. {
  902. if (editSequence.director.playableGraph.IsValid())
  903. {
  904. if (editSequence.director.playableGraph.GetRootPlayableCount() > 0)
  905. {
  906. var rootPlayable = editSequence.director.playableGraph.GetRootPlayable(0);
  907. if (rootPlayable.IsValid())
  908. rootPlayable.SetDuration(duration);
  909. }
  910. }
  911. }
  912. }
  913. public void InvokeTimeChangeCallback()
  914. {
  915. if (OnTimeChange != null)
  916. OnTimeChange.Invoke();
  917. }
  918. Vector2 ValidatePlayRange(Vector2 range)
  919. {
  920. if (range == TimelineAssetViewModel.NoPlayRangeSet)
  921. return range;
  922. float minimumPlayRangeTime = (float)(0.01 / Math.Max(1.0, referenceSequence.frameRate));
  923. // Validate min
  924. if (range.y - range.x < minimumPlayRangeTime)
  925. range.x = range.y - minimumPlayRangeTime;
  926. if (range.x < 0.0f)
  927. range.x = 0.0f;
  928. // Validate max
  929. if (range.y > editSequence.duration)
  930. range.y = (float)editSequence.duration;
  931. if (range.y - range.x < minimumPlayRangeTime)
  932. range.y = Mathf.Min(range.x + minimumPlayRangeTime, (float)editSequence.duration);
  933. return range;
  934. }
  935. void EnsureWindowTimeConsistency()
  936. {
  937. if (masterSequence.director != null && masterSequence.viewModel != null && !ignorePreview)
  938. masterSequence.time = masterSequence.viewModel.windowTime;
  939. }
  940. void SynchronizeSequencesAfterPlayback()
  941. {
  942. // Synchronizing editSequence will synchronize all view models up to the master
  943. SynchronizeViewModelTime(editSequence);
  944. }
  945. static void SynchronizeViewModelTime(ISequenceState state)
  946. {
  947. if (state.director == null || state.viewModel == null)
  948. return;
  949. var t = state.time;
  950. state.time = t;
  951. }
  952. // because we may be evaluating outside the duration of the root playable
  953. // we explicitly set the time - this causes the graph to not 'advance' the time
  954. // because advancing it can force it to change due to wrapping to the duration
  955. // This can happen if the graph is force evaluated outside it's duration
  956. // case 910114, 936844 and 943377
  957. static void ForceTimeOnDirector(PlayableDirector director)
  958. {
  959. var directorTime = director.time;
  960. director.time = directorTime;
  961. }
  962. public bool IsPlayableGraphDone()
  963. {
  964. return masterSequence.director != null
  965. && masterSequence.director.playableGraph.IsValid()
  966. && masterSequence.director.playableGraph.IsDone();
  967. }
  968. }
  969. }