From c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78 Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Sun, 19 Apr 2020 17:19:32 -0400 Subject: Inital commit --- .../Editor/Window/TimelineWindow.cs | 541 +++++++++++++++++++++ 1 file changed, 541 insertions(+) create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Window/TimelineWindow.cs (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/Window/TimelineWindow.cs') diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Window/TimelineWindow.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Window/TimelineWindow.cs new file mode 100644 index 0000000..e3e21bc --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Window/TimelineWindow.cs @@ -0,0 +1,541 @@ +using System; +using System.Collections.Generic; +using UnityEditor.Callbacks; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Playables; +using UnityEngine.SceneManagement; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [EditorWindowTitle(title = "Timeline", useTypeNameAsIconName = true)] + partial class TimelineWindow : EditorWindow, IHasCustomMenu + { + [Serializable] + public class TimelineWindowPreferences + { + public bool frameSnap = true; + public bool edgeSnaps = true; + public bool muteAudioScrub = true; + public bool playRangeLoopMode = true; + public PlaybackScrollMode autoScrollMode; + public EditMode.EditType editType = EditMode.EditType.Mix; + public TimeReferenceMode timeReferenceMode = TimeReferenceMode.Local; + } + + [SerializeField] TimelineWindowPreferences m_Preferences = new TimelineWindowPreferences(); + public TimelineWindowPreferences preferences { get { return m_Preferences; } } + + [SerializeField] + EditorGUIUtility.EditorLockTracker m_LockTracker = new EditorGUIUtility.EditorLockTracker(); + + readonly PreviewResizer m_PreviewResizer = new PreviewResizer(); + bool m_LastFrameHadSequence; + bool m_ForceRefreshLastSelection; + int m_CurrentSceneHashCode = -1; + + [NonSerialized] + bool m_HasBeenInitialized; + + [SerializeField] + SequenceHierarchy m_SequenceHierarchy; + static SequenceHierarchy s_LastHierarchy; + + public static TimelineWindow instance { get; private set; } + public Rect clientArea { get; set; } + public bool isDragging { get; set; } + public static DirectorStyles styles { get { return DirectorStyles.Instance; } } + public List allTracks + { + get + { + return treeView != null ? treeView.allTrackGuis : new List(); + } + } + + public WindowState state { get; private set; } + + public bool locked + { + get + { + // we can never be in a locked state if there is no timeline asset + if (state.editSequence.asset == null) + return false; + + return m_LockTracker.isLocked; + } + set { m_LockTracker.isLocked = value; } + } + + public bool hierarchyChangedThisFrame { get; private set; } + + public TimelineWindow() + { + InitializeManipulators(); + m_LockTracker.lockStateChanged.AddPersistentListener(OnLockStateChanged, UnityEventCallState.EditorAndRuntime); + } + + void OnLockStateChanged(bool locked) + { + // Make sure that upon unlocking, any selection change is updated + // Case 1123119 -- only force rebuild if not recording + if (!locked) + RefreshSelection(state != null && !state.recording); + } + + void OnEnable() + { + if (m_SequencePath == null) + m_SequencePath = new SequencePath(); + + if (m_SequenceHierarchy == null) + { + // The sequence hierarchy will become null if maximize on play is used for in/out of playmode + // a static var will hang on to the reference + if (s_LastHierarchy != null) + m_SequenceHierarchy = s_LastHierarchy; + else + m_SequenceHierarchy = SequenceHierarchy.CreateInstance(); + + state = null; + } + s_LastHierarchy = m_SequenceHierarchy; + + titleContent = GetLocalizedTitleContent(); + + m_PreviewResizer.Init("TimelineWindow"); + + // Unmaximize fix : when unmaximizing, a new window is enabled and disabled. Prevent it from overriding the instance pointer. + if (instance == null) + instance = this; + + AnimationClipCurveCache.Instance.OnEnable(); + TrackAsset.OnClipPlayableCreate += m_PlayableLookup.UpdatePlayableLookup; + TrackAsset.OnTrackAnimationPlayableCreate += m_PlayableLookup.UpdatePlayableLookup; + + if (state == null) + { + state = new WindowState(this, s_LastHierarchy); + Initialize(); + RefreshSelection(true); + m_ForceRefreshLastSelection = true; + } + } + + void OnDisable() + { + if (instance == this) + instance = null; + + if (state != null) + state.Reset(); + + if (instance == null) + SelectionManager.RemoveTimelineSelection(); + + AnimationClipCurveCache.Instance.OnDisable(); + TrackAsset.OnClipPlayableCreate -= m_PlayableLookup.UpdatePlayableLookup; + TrackAsset.OnTrackAnimationPlayableCreate -= m_PlayableLookup.UpdatePlayableLookup; + TimelineWindowViewPrefs.SaveAll(); + TimelineWindowViewPrefs.UnloadAllViewModels(); + } + + void OnDestroy() + { + if (state != null) + { + state.OnDestroy(); + } + m_HasBeenInitialized = false; + RemoveEditorCallbacks(); + AnimationClipCurveCache.Instance.Clear(); + TimelineAnimationUtilities.UnlinkAnimationWindow(); + } + + void OnLostFocus() + { + isDragging = false; + + if (state != null) + state.captured.Clear(); + + Repaint(); + } + + void OnFocus() + { + if (state == null) return; + + if (lastSelectedGO != Selection.activeObject) + { + // selection may have changed while Timeline Editor was looking away + RefreshSelection(false); + + // Inline curves may have become out of sync + RefreshInlineCurves(); + } + } + + void OnHierarchyChange() + { + hierarchyChangedThisFrame = true; + Repaint(); + } + + void OnStateChange() + { + state.UpdateRecordingState(); + if (treeView != null && state.editSequence.asset != null) + treeView.Reload(); + if (m_MarkerHeaderGUI != null) + m_MarkerHeaderGUI.Rebuild(); + } + + void OnGUI() + { + InitializeGUIIfRequired(); + UpdateGUIConstants(); + UpdateViewStateHash(); + + EditMode.HandleModeClutch(); // TODO We Want that here? + + DetectStylesChange(); + DetectActiveSceneChanges(); + DetectStateChanges(); + + state.ProcessStartFramePendingUpdates(); + + var clipRect = new Rect(0.0f, 0.0f, position.width, position.height); + clipRect.xMin += state.sequencerHeaderWidth; + + using (new GUIViewportScope(clipRect)) + state.InvokeWindowOnGuiStarted(Event.current); + + if (Event.current.type == EventType.MouseDrag && state != null && state.mouseDragLag > 0.0f) + { + state.mouseDragLag -= Time.deltaTime; + return; + } + + if (PerformUndo()) + return; + + if (EditorApplication.isPlaying) + { + if (state != null) + { + if (state.recording) + state.recording = false; + } + Repaint(); + } + + clientArea = position; + + PlaybackScroller.AutoScroll(state); + DoLayout(); + + // overlays + if (state.captured.Count > 0) + { + using (new GUIViewportScope(clipRect)) + { + foreach (var o in state.captured) + { + o.Overlay(Event.current, state); + } + Repaint(); + } + } + + if (state.showQuadTree) + state.spacePartitioner.DebugDraw(); + + // attempt another rebuild -- this will avoid 1 frame flashes + if (Event.current.type == EventType.Repaint) + { + RebuildGraphIfNecessary(); + state.ProcessEndFramePendingUpdates(); + } + + using (new GUIViewportScope(clipRect)) + { + if (Event.current.type == EventType.Repaint) + EditMode.inputHandler.OnGUI(state, Event.current); + } + + if (Event.current.type == EventType.Repaint) + hierarchyChangedThisFrame = false; + } + + static void DetectStylesChange() + { + DirectorStyles.ReloadStylesIfNeeded(); + } + + void DetectActiveSceneChanges() + { + if (m_CurrentSceneHashCode == -1) + { + m_CurrentSceneHashCode = SceneManager.GetActiveScene().GetHashCode(); + } + + if (m_CurrentSceneHashCode != SceneManager.GetActiveScene().GetHashCode()) + { + bool isSceneStillLoaded = false; + for (int a = 0; a < SceneManager.sceneCount; a++) + { + var scene = SceneManager.GetSceneAt(a); + if (scene.GetHashCode() == m_CurrentSceneHashCode && scene.isLoaded) + { + isSceneStillLoaded = true; + break; + } + } + + if (!isSceneStillLoaded) + { + if (!locked) + ClearCurrentTimeline(); + m_CurrentSceneHashCode = SceneManager.GetActiveScene().GetHashCode(); + } + } + } + + void DetectStateChanges() + { + if (state != null) + { + state.editSequence.ResetIsReadOnly(); //Force reset readonly for asset flag for each frame. + // detect if the sequence was removed under our feet + if (m_LastFrameHadSequence && state.editSequence.asset == null) + { + ClearCurrentTimeline(); + } + m_LastFrameHadSequence = state.editSequence.asset != null; + + // the currentDirector can get set to null by a deletion or scene unloading so polling is required + if (state.editSequence.director == null) + { + state.recording = false; + state.previewMode = false; + + //Case 1201405 : Check if the lock state is valid with the lock tracker state + if (locked != m_LockTracker.isLocked) + m_LockTracker.isLocked = locked; + + if (!locked && m_LastFrameHadSequence) + { + // the user may be adding a new PlayableDirector to a selected GameObject, make sure the timeline editor is shows the proper director if none is already showing + var selectedGameObject = Selection.activeObject != null ? Selection.activeObject as GameObject : null; + var selectedDirector = selectedGameObject != null ? selectedGameObject.GetComponent() : null; + if (selectedDirector != null) + { + SetCurrentTimeline(selectedDirector); + } + } + } + else + { + // the user may have changed the timeline associated with the current director + if (state.editSequence.asset != state.editSequence.director.playableAsset) + { + if (!locked) + { + SetCurrentTimeline(state.editSequence.director); + } + else + { + // Keep locked on the current timeline but set the current director to null since it's not the timeline owner anymore + SetCurrentTimeline(state.editSequence.asset); + } + } + } + } + } + + void Initialize() + { + if (!m_HasBeenInitialized) + { + InitializeStateChange(); + InitializeEditorCallbacks(); + m_HasBeenInitialized = true; + } + } + + void RefreshLastSelectionIfRequired() + { + // case 1088918 - workaround for the instanceID to object cache being update during Awake. + // This corrects any playableDirector ptrs with the correct cached version + // This can happen when going from edit to playmode + if (m_ForceRefreshLastSelection) + { + m_ForceRefreshLastSelection = false; + RestoreLastSelection(true); + } + } + + void InitializeGUIIfRequired() + { + RefreshLastSelectionIfRequired(); + InitializeTimeArea(); + if (treeView == null && state.editSequence.asset != null) + { + treeView = new TimelineTreeViewGUI(this, state.editSequence.asset, position); + } + } + + void UpdateGUIConstants() + { + m_HorizontalScrollBarSize = + GUI.skin.horizontalScrollbar.fixedHeight + GUI.skin.horizontalScrollbar.margin.top; + m_VerticalScrollBarSize = (treeView != null && treeView.showingVerticalScrollBar) + ? GUI.skin.verticalScrollbar.fixedWidth + GUI.skin.verticalScrollbar.margin.left + : 0; + } + + void UpdateViewStateHash() + { + if (Event.current.type == EventType.Layout) + state.UpdateViewStateHash(); + } + + static bool PerformUndo() + { + if (!Event.current.isKey) + return false; + + if (Event.current.keyCode != KeyCode.Z) + return false; + + if (!EditorGUI.actionKey) + return false; + + return true; + } + + public void RebuildGraphIfNecessary(bool evaluate = true) + { + if (state == null || state.editSequence.director == null || state.editSequence.asset == null) + return; + + if (state.rebuildGraph) + { + // rebuilding the graph resets the time + double time = state.editSequence.time; + + var wasPlaying = false; + + // disable preview mode, + if (!EditorApplication.isPlaying) + { + wasPlaying = state.playing; + + state.previewMode = false; + state.GatherProperties(state.masterSequence.director); + } + state.RebuildPlayableGraph(); + state.editSequence.time = time; + + if (wasPlaying) + state.Play(); + + if (evaluate) + { + // put the scene back in the correct state + state.EvaluateImmediate(); + + // this is necessary to see accurate results when inspector refreshes + // case 1154802 - this will property re-force time on the director, so + // the play head won't snap back to the timeline duration on rebuilds + if (!state.playing) + state.Evaluate(); + } + Repaint(); + } + + state.rebuildGraph = false; + } + + // for tests + public new void RepaintImmediately() + { + base.RepaintImmediately(); + } + + internal static bool IsEditingTimelineAsset(TimelineAsset timelineAsset) + { + return instance != null && instance.state != null && instance.state.editSequence.asset == timelineAsset; + } + + internal static void RepaintIfEditingTimelineAsset(TimelineAsset timelineAsset) + { + if (IsEditingTimelineAsset(timelineAsset)) + instance.Repaint(); + } + + internal class DoCreateTimeline : ProjectWindowCallback.EndNameEditAction + { + public override void Action(int instanceId, string pathName, string resourceFile) + { + var timeline = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(timeline, pathName); + ProjectWindowUtil.ShowCreatedAsset(timeline); + } + } + + [MenuItem("Assets/Create/Timeline", false, 450)] + public static void CreateNewTimeline() + { + var icon = EditorGUIUtility.IconContent("TimelineAsset Icon").image as Texture2D; + ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Timeline.playable", icon, null); + } + + [MenuItem("Window/Sequencing/Timeline", false, 1)] + public static void ShowWindow() + { + GetWindow(typeof(SceneView)); + instance.Focus(); + } + + [OnOpenAsset(1)] + public static bool OnDoubleClick(int instanceID, int line) + { + var assetDoubleClicked = EditorUtility.InstanceIDToObject(instanceID) as TimelineAsset; + if (assetDoubleClicked == null) + return false; + + ShowWindow(); + instance.SetCurrentTimeline(assetDoubleClicked); + + return true; + } + + public virtual void AddItemsToMenu(GenericMenu menu) + { + bool disabled = state == null || state.editSequence.asset == null; + + m_LockTracker.AddItemsToMenu(menu, disabled); + } + + protected virtual void ShowButton(Rect r) + { + bool disabled = state == null || state.editSequence.asset == null; + + m_LockTracker.ShowButton(r, DirectorStyles.Instance.lockButton, disabled); + } + + internal void TreeViewKeyboardCallback() + { + if (Event.current.type != EventType.KeyDown) + return; + if (TimelineAction.HandleShortcut(state, Event.current)) + { + Event.current.Use(); + } + } + } +} -- cgit v1.2.3