123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- using System;
- using System.Collections.Generic;
- #if UNITY_2021_2_OR_NEWER
- using UnityEditor.SceneManagement;
- #else
- using UnityEditor.Experimental.SceneManagement;
- #endif
- using UnityEngine;
- using UnityEngine.Timeline;
- namespace UnityEditor.Timeline
- {
- partial class TimelineWindow
- {
- struct MarkerOverlay
- {
- public IMarker marker;
- public Rect rect;
- public bool isSelected;
- public bool isCollapsed;
- public MarkerEditor editor;
- }
- enum TimelineItemArea
- {
- Header,
- Lines
- }
- [SerializeField] float m_HierarchySplitterPerc = WindowConstants.hierarchySplitterDefaultPercentage;
- static internal readonly TimelineMode s_ActiveMode = new TimelineActiveMode();
- static internal readonly TimelineMode s_EditAssetMode = new TimelineAssetEditionMode();
- static internal readonly TimelineMode s_InactiveMode = new TimelineInactiveMode();
- static internal readonly TimelineMode s_DisabledMode = new TimelineDisabledMode();
- static internal readonly TimelineMode s_PrefabOutOfContextMode = new TimelineAssetEditionMode();
- static internal readonly TimelineMode s_ReadonlyMode = new TimelineReadOnlyMode();
- int m_SplitterCaptured;
- float m_VerticalScrollBarSize, m_HorizontalScrollBarSize;
- List<MarkerOverlay> m_OverlayQueue = new List<MarkerOverlay>(100);
- float headerHeight
- {
- get
- {
- return WindowConstants.markerRowYPosition + (state.showMarkerHeader ? WindowConstants.markerRowHeight : 0.0f);
- }
- }
- public Rect markerHeaderRect
- {
- get { return new Rect(0.0f, WindowConstants.markerRowYPosition, state.sequencerHeaderWidth, WindowConstants.markerRowHeight); }
- }
- public Rect markerContentRect
- {
- get { return Rect.MinMaxRect(state.sequencerHeaderWidth, WindowConstants.markerRowYPosition, position.width, WindowConstants.markerRowYPosition + WindowConstants.markerRowHeight); }
- }
- Rect trackRect
- {
- get
- {
- var yMinHeight = headerHeight;
- return new Rect(0, yMinHeight, position.width, position.height - yMinHeight - horizontalScrollbarHeight);
- }
- }
- public Rect sequenceRect
- {
- get { return new Rect(0.0f, WindowConstants.markerRowYPosition, position.width - WindowConstants.sliderWidth, position.height - WindowConstants.timeAreaYPosition); }
- }
- public Rect sequenceHeaderRect
- {
- get { return new Rect(0.0f, WindowConstants.markerRowYPosition, state.sequencerHeaderWidth, position.height - WindowConstants.timeAreaYPosition); }
- }
- public Rect sequenceContentRect
- {
- get
- {
- return new Rect(
- state.sequencerHeaderWidth,
- WindowConstants.markerRowYPosition,
- position.width - state.sequencerHeaderWidth - (treeView != null && treeView.showingVerticalScrollBar ? WindowConstants.sliderWidth : 0),
- position.height - WindowConstants.markerRowYPosition - horizontalScrollbarHeight);
- }
- }
- public float verticalScrollbarWidth
- {
- get
- {
- return m_VerticalScrollBarSize;
- }
- }
- public float horizontalScrollbarHeight
- {
- get { return m_HorizontalScrollBarSize; }
- }
- internal TimelineMode currentMode
- {
- get
- {
- if (state == null || state.editSequence.asset == null)
- return s_InactiveMode;
- if (state.editSequence.isReadOnly)
- return s_ReadonlyMode;
- if (state.editSequence.director == null || state.masterSequence.director == null)
- return s_EditAssetMode;
- if (PrefabUtility.IsPartOfPrefabAsset(state.editSequence.director))
- {
- var stage = PrefabStageUtility.GetCurrentPrefabStage();
- if (stage == null || !stage.IsPartOfPrefabContents(state.editSequence.director.gameObject))
- return s_PrefabOutOfContextMode;
- }
- if (!state.masterSequence.director.isActiveAndEnabled)
- return s_DisabledMode;
- return s_ActiveMode;
- }
- }
- void DoLayout()
- {
- var rawType = Event.current.rawType; // TODO: rawType seems to be broken after calling Use(), use this Hack and remove it once it's fixed.
- var mousePosition = Event.current.mousePosition; // mousePosition is also affected by this bug and does not reflect the original position after a Use()
- Initialize();
- HandleSplitterResize();
- var processManipulators = Event.current.type != EventType.Repaint && Event.current.type != EventType.Layout;
- if (processManipulators)
- {
- // Update what's under mouse the cursor
- PickerUtils.DoPick(state, mousePosition);
- if (state.editSequence.asset != null)
- m_PreTreeViewControl.HandleManipulatorsEvents(state);
- }
- SequencerGUI();
- if (processManipulators)
- {
- if (state.editSequence.asset != null)
- m_PostTreeViewControl.HandleManipulatorsEvents(state);
- }
- m_RectangleSelect.OnGUI(state, rawType, mousePosition);
- m_RectangleZoom.OnGUI(state, rawType, mousePosition);
- }
- void SplitterGUI()
- {
- if (!state.IsEditingAnEmptyTimeline())
- {
- var splitterLineRect = new Rect(state.sequencerHeaderWidth - 1.0f, WindowConstants.timeAreaYPosition + 2.0f, 2.0f, clientArea.height);
- EditorGUI.DrawRect(splitterLineRect, DirectorStyles.Instance.customSkin.colorTopOutline3);
- }
- }
- void TrackViewsGUI()
- {
- using (new GUIViewportScope(trackRect))
- {
- TracksGUI(trackRect, state, currentMode.TrackState(state));
- }
- }
- void UserOverlaysGUI()
- {
- if (Event.current.type != EventType.Repaint)
- return;
- // the rect containing the time area plus the time ruler
- var screenRect = new Rect(
- state.sequencerHeaderWidth,
- WindowConstants.timeAreaYPosition,
- position.width - state.sequencerHeaderWidth - (treeView != null && treeView.showingVerticalScrollBar ? WindowConstants.sliderWidth : 0),
- position.height - WindowConstants.timeAreaYPosition - horizontalScrollbarHeight);
- var startTime = state.PixelToTime(screenRect.xMin);
- var endTime = state.PixelToTime(screenRect.xMax);
- using (new GUIViewportScope(screenRect))
- {
- foreach (var entry in m_OverlayQueue)
- {
- var uiState = MarkerUIStates.None;
- if (entry.isCollapsed)
- uiState |= MarkerUIStates.Collapsed;
- if (entry.isSelected)
- uiState |= MarkerUIStates.Selected;
- var region = new MarkerOverlayRegion(GUIClip.Clip(entry.rect), screenRect, startTime, endTime);
- try
- {
- entry.editor.DrawOverlay(entry.marker, uiState, region);
- }
- catch (Exception e)
- {
- Debug.LogException(e);
- }
- }
- }
- m_OverlayQueue.Clear();
- }
- void DrawHeaderBackground()
- {
- var rect = state.timeAreaRect;
- rect.xMin = 0.0f;
- EditorGUI.DrawRect(rect, DirectorStyles.Instance.customSkin.colorTimelineBackground);
- }
- void HandleBottomFillerDragAndDrop(Rect rect)
- {
- if (Event.current.type != EventType.DragUpdated &&
- Event.current.type != EventType.DragExited &&
- Event.current.type != EventType.DragPerform)
- return;
- if (instance.treeView == null || instance.treeView.timelineDragging == null)
- return;
- if (!rect.Contains(Event.current.mousePosition))
- return;
- instance.treeView.timelineDragging.DragElement(null, new Rect(), -1);
- }
- void DrawHeaderBackgroundBottomFiller()
- {
- var rect = sequenceRect;
- rect.yMin = rect.yMax;
- rect.yMax = rect.yMax + WindowConstants.sliderWidth;
- if (state.editSequence.asset != null && !state.IsEditingAnEmptyTimeline())
- {
- rect.width = state.sequencerHeaderWidth;
- }
- using (new GUIViewportScope(rect))
- {
- Graphics.DrawBackgroundRect(state, rect);
- }
- HandleBottomFillerDragAndDrop(rect);
- }
- void SequencerGUI()
- {
- var duration = state.editSequence.duration;
- DrawHeaderBackground();
- DurationGUI(TimelineItemArea.Header, duration);
- DrawToolbar();
- TrackViewsGUI();
- MarkerHeaderGUI();
- UserOverlaysGUI();
- DurationGUI(TimelineItemArea.Lines, duration);
- PlayRangeGUI(TimelineItemArea.Lines);
- TimeCursorGUI(TimelineItemArea.Lines);
- DrawHeaderBackgroundBottomFiller();
- SubTimelineRangeGUI();
- PlayRangeGUI(TimelineItemArea.Header);
- TimeCursorGUI(TimelineItemArea.Header);
- SplitterGUI();
- }
- void DrawToolbar()
- {
- DrawOptions();
- using (new GUILayout.VerticalScope())
- {
- using (new GUILayout.HorizontalScope(EditorStyles.toolbar))
- {
- using (new GUILayout.HorizontalScope())
- {
- DrawTransportToolbar();
- }
- DrawSequenceSelector();
- DrawBreadcrumbs();
- GUILayout.FlexibleSpace();
- DrawOptions();
- }
- using (new GUILayout.HorizontalScope())
- {
- DrawHeaderEditButtons();
- DrawTimelineRuler();
- }
- }
- }
- void SubTimelineRangeGUI()
- {
- if (!state.IsEditingASubTimeline() || state.IsEditingAnEmptyTimeline()) return;
- var subTimelineOverlayColor = DirectorStyles.Instance.customSkin.colorSubSequenceOverlay;
- var range = state.editSequence.GetEvaluableRange();
- var area = new Vector2(state.TimeToPixel(range.start), state.TimeToPixel(range.end));
- var fullRect = sequenceContentRect;
- fullRect.yMin = WindowConstants.timeAreaYPosition + 1.0f;
- if (fullRect.xMin < area.x)
- {
- var before = fullRect;
- before.xMin = fullRect.xMin;
- before.xMax = Mathf.Min(area.x, fullRect.xMax);
- EditorGUI.DrawRect(before, subTimelineOverlayColor);
- }
- if (fullRect.xMax > area.y)
- {
- var after = fullRect;
- after.xMin = Mathf.Max(area.y, fullRect.xMin);
- after.xMax = fullRect.xMax;
- EditorGUI.DrawRect(after, subTimelineOverlayColor);
- // Space above the vertical scrollbar
- after.xMin = after.xMax;
- after.width = verticalScrollbarWidth;
- after.yMax = state.timeAreaRect.y + state.timeAreaRect.height + (state.showMarkerHeader ? WindowConstants.markerRowHeight : 0.0f);
- EditorGUI.DrawRect(after, subTimelineOverlayColor);
- }
- }
- void HandleSplitterResize()
- {
- state.mainAreaWidth = position.width;
- if (state.editSequence.asset == null)
- return;
- // Sequencer Header Splitter : The splitter has 6 pixels wide,center it around m_State.sequencerHeaderWidth. That's why there's this -3.
- Rect sequencerHeaderSplitterRect = new Rect(state.sequencerHeaderWidth - 3.0f, 0.0f, 6.0f, clientArea.height);
- EditorGUIUtility.AddCursorRect(sequencerHeaderSplitterRect, MouseCursor.SplitResizeLeftRight);
- if (Event.current.type == EventType.MouseDown)
- {
- if (sequencerHeaderSplitterRect.Contains(Event.current.mousePosition))
- m_SplitterCaptured = 1;
- }
- if (m_SplitterCaptured > 0)
- {
- if (Event.current.type == EventType.MouseUp)
- {
- m_SplitterCaptured = 0;
- Event.current.Use();
- }
- if (Event.current.type == EventType.MouseDrag)
- {
- if (m_SplitterCaptured == 1)
- {
- var percInc = Event.current.delta.x / position.width;
- m_HierarchySplitterPerc = Mathf.Clamp(m_HierarchySplitterPerc + percInc, WindowConstants.minHierarchySplitter, WindowConstants.maxHierarchySplitter);
- state.sequencerHeaderWidth += Event.current.delta.x;
- }
- Event.current.Use();
- }
- }
- }
- void DrawOptions()
- {
- if (currentMode.headerState.options == TimelineModeGUIState.Hidden || state.editSequence.asset == null)
- return;
- using (new EditorGUI.DisabledScope(currentMode.headerState.options == TimelineModeGUIState.Disabled))
- {
- var rect = new Rect(position.width - WindowConstants.cogButtonWidth, 0, WindowConstants.cogButtonWidth, WindowConstants.timeAreaYPosition);
- if (EditorGUI.DropdownButton(rect, DirectorStyles.optionsCogIcon, FocusType.Keyboard, EditorStyles.toolbarButton))
- {
- GenericMenu menu = new GenericMenu();
- menu.AddItem(EditorGUIUtility.TrTextContent("Preferences Page..."), false, () => SettingsWindow.Show(SettingsScope.User, "Preferences/Timeline"));
- menu.AddSeparator("");
- menu.AddItem(EditorGUIUtility.TrTextContent("Seconds"), !state.timeInFrames, ChangeTimeCode, "seconds");
- menu.AddItem(EditorGUIUtility.TrTextContent("Frames"), state.timeInFrames, ChangeTimeCode, "frames");
- menu.AddSeparator("");
- TimeAreaContextMenu.AddTimeAreaMenuItems(menu, state);
- menu.AddSeparator("");
- bool standardFrameRate = false;
- for (int i = 0; i < TimelineProjectSettings.framerateValues.Length; i++)
- {
- standardFrameRate |= AddStandardFrameRateMenu(menu, "Frame Rate/" + TimelineProjectSettings.framerateLabels[i], TimelineProjectSettings.framerateValues[i]);
- }
- if (standardFrameRate)
- menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Frame Rate/Custom"));
- else
- menu.AddItem(EditorGUIUtility.TrTextContent("Frame Rate/Custom (" + state.editSequence.frameRate + ")"), true, () => {});
- menu.AddSeparator("");
- if (state.playRangeEnabled)
- {
- menu.AddItem(EditorGUIUtility.TrTextContent("Play Range Mode/Loop"), state.playRangeLoopMode, () => state.playRangeLoopMode = true);
- menu.AddItem(EditorGUIUtility.TrTextContent("Play Range Mode/Once"), !state.playRangeLoopMode, () => state.playRangeLoopMode = false);
- }
- else
- {
- menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Play Range Mode"));
- }
- if (Unsupported.IsDeveloperMode())
- {
- menu.AddSeparator("");
- menu.AddItem(EditorGUIUtility.TrTextContent("Show Snapping Debug"), SnapEngine.displayDebugLayout,
- () => SnapEngine.displayDebugLayout = !SnapEngine.displayDebugLayout);
- menu.AddItem(EditorGUIUtility.TrTextContent("Debug TimeArea"), false,
- () =>
- Debug.LogFormat("translation: {0} scale: {1} rect: {2} shownRange: {3}", m_TimeArea.translation, m_TimeArea.scale, m_TimeArea.rect, m_TimeArea.shownArea));
- menu.AddItem(EditorGUIUtility.TrTextContent("Edit Skin"), false, () => Selection.activeObject = DirectorStyles.Instance.customSkin);
- menu.AddItem(EditorGUIUtility.TrTextContent("Show QuadTree Debugger"), state.showQuadTree,
- () => state.showQuadTree = !state.showQuadTree);
- }
- menu.DropDown(rect);
- }
- }
- }
- bool AddStandardFrameRateMenu(GenericMenu menu, string name, float value)
- {
- bool on = state.editSequence.frameRate.Equals(value);
- if (state.editSequence.isReadOnly)
- {
- menu.AddDisabledItem(EditorGUIUtility.TextContent(name), on);
- }
- else
- {
- menu.AddItem(EditorGUIUtility.TextContent(name), on, r =>
- {
- state.editSequence.frameRate = value;
- }, value);
- }
- return on;
- }
- void ChangeTimeCode(object obj)
- {
- string format = obj.ToString();
- if (format == "frames")
- {
- state.timeInFrames = true;
- }
- else
- {
- state.timeInFrames = false;
- }
- }
- public void AddUserOverlay(IMarker marker, Rect rect, MarkerEditor editor, bool collapsed, bool selected)
- {
- if (marker == null)
- throw new ArgumentNullException("marker");
- if (editor == null)
- throw new ArgumentNullException("editor");
- m_OverlayQueue.Add(new MarkerOverlay()
- {
- isCollapsed = collapsed,
- isSelected = selected,
- marker = marker,
- rect = rect,
- editor = editor
- }
- );
- }
- }
- }
|