WindowState.cs 37 KB

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