diff options
| author | Andrew Lee <alee14498@protonmail.com> | 2020-04-19 17:19:32 -0400 |
|---|---|---|
| committer | Andrew Lee <alee14498@protonmail.com> | 2020-04-19 17:19:32 -0400 |
| commit | c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78 (patch) | |
| tree | ee4d51c7c1d633e11f46453ef1edd3c77c4ef9f7 /Library/PackageCache/com.unity.timeline@1.2.13/Editor/Trackhead.cs | |
| download | Project-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.tar.gz Project-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.tar.bz2 Project-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.zip | |
Inital commit
Diffstat (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/Trackhead.cs')
| -rw-r--r-- | Library/PackageCache/com.unity.timeline@1.2.13/Editor/Trackhead.cs | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Trackhead.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Trackhead.cs new file mode 100644 index 0000000..8a562b6 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Trackhead.cs @@ -0,0 +1,363 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + static class Gaps + { + static readonly string kInsertTime = "Insert Time"; + + public static void Insert(TimelineAsset asset, double at, double amount, double tolerance) + { + // gather all clips + var clips = asset.flattenedTracks.SelectMany(x => x.clips).Where(x => (x.start - at) >= -tolerance).ToList(); + var markers = asset.flattenedTracks.SelectMany(x => x.GetMarkers()).Where(x => (x.time - at) >= -tolerance).ToList(); + + if (!clips.Any() && !markers.Any()) + return; + + // push undo on the tracks for the clips that are being modified + foreach (var t in clips.Select(x => x.parentTrack).Distinct()) + { + TimelineUndo.PushUndo(t, kInsertTime); + } + + // push the clips + foreach (var clip in clips) + { + clip.start += amount; + } + + // push undos and move the markers + foreach (var marker in markers) + { + var obj = marker as UnityEngine.Object; + if (obj != null) + TimelineUndo.PushUndo(obj, kInsertTime); + marker.time += amount; + } + + TimelineEditor.Refresh(RefreshReason.ContentsModified); + } + } + + class PlayheadContextMenu : Manipulator + { + readonly TimeAreaItem m_TimeAreaItem; + static readonly int[] kFrameInsertionValues = {5, 10, 25, 100}; + + public PlayheadContextMenu(TimeAreaItem timeAreaItem) + { + m_TimeAreaItem = timeAreaItem; + } + + protected override bool ContextClick(Event evt, WindowState state) + { + if (!m_TimeAreaItem.bounds.Contains(evt.mousePosition)) + return false; + + var tolerance = TimeUtility.GetEpsilon(state.editSequence.time, state.referenceSequence.frameRate); + var menu = new GenericMenu(); + + if (!TimelineWindow.instance.state.editSequence.isReadOnly) + { + menu.AddItem(EditorGUIUtility.TrTextContent("Insert/Frame/Single"), false, () => + Gaps.Insert(state.editSequence.asset, state.editSequence.time, 1.0 / state.referenceSequence.frameRate, tolerance) + ); + + for (var i = 0; i != kFrameInsertionValues.Length; ++i) + { + double f = kFrameInsertionValues[i]; + menu.AddItem(EditorGUIUtility.TrTextContent("Insert/Frame/" + kFrameInsertionValues[i] + " Frames"), false, () => + Gaps.Insert(state.editSequence.asset, state.editSequence.time, f / state.referenceSequence.frameRate, tolerance) + ); + } + + var playRangeTime = state.playRange; + if (playRangeTime.y > playRangeTime.x) + { + menu.AddItem(EditorGUIUtility.TrTextContent("Insert/Selected Time"), false, () => + Gaps.Insert(state.editSequence.asset, playRangeTime.x, playRangeTime.y - playRangeTime.x, TimeUtility.GetEpsilon(playRangeTime.x, state.referenceSequence.frameRate)) + ); + } + } + + menu.AddItem(EditorGUIUtility.TrTextContent("Select/Clips Ending Before"), false, () => SelectMenuCallback(x => x.end < state.editSequence.time + tolerance, state)); + menu.AddItem(EditorGUIUtility.TrTextContent("Select/Clips Starting Before"), false, () => SelectMenuCallback(x => x.start < state.editSequence.time + tolerance, state)); + menu.AddItem(EditorGUIUtility.TrTextContent("Select/Clips Ending After"), false, () => SelectMenuCallback(x => x.end - state.editSequence.time >= -tolerance, state)); + menu.AddItem(EditorGUIUtility.TrTextContent("Select/Clips Starting After"), false, () => SelectMenuCallback(x => x.start - state.editSequence.time >= -tolerance, state)); + menu.AddItem(EditorGUIUtility.TrTextContent("Select/Clips Intersecting"), false, () => SelectMenuCallback(x => x.start <= state.editSequence.time && state.editSequence.time <= x.end, state)); + menu.AddItem(EditorGUIUtility.TrTextContent("Select/Blends Intersecting"), false, () => SelectMenuCallback(x => SelectBlendingIntersecting(x, state.editSequence.time), state)); + menu.ShowAsContext(); + + return true; + } + + static bool SelectBlendingIntersecting(TimelineClip clip, double time) + { + return clip.start <= time && time <= clip.end && ( + (time <= clip.start + clip.blendInDuration) || + (time >= clip.end - clip.blendOutDuration) + ); + } + + static void SelectMenuCallback(Func<TimelineClip, bool> selector, WindowState state) + { + var allClips = state.GetWindow().treeView.allClipGuis; + if (allClips == null) + return; + + SelectionManager.Clear(); + for (var i = 0; i != allClips.Count; ++i) + { + var c = allClips[i]; + + if (c != null && c.clip != null && selector(c.clip)) + { + SelectionManager.Add(c.clip); + } + } + } + } + + class TimeAreaContextMenu : Manipulator + { + protected override bool ContextClick(Event evt, WindowState state) + { + if (state.timeAreaRect.Contains(Event.current.mousePosition)) + { + var menu = new GenericMenu(); + AddTimeAreaMenuItems(menu, state); + menu.ShowAsContext(); + return true; + } + return false; + } + + internal static void AddTimeAreaMenuItems(GenericMenu menu, WindowState state) + { + foreach (var value in Enum.GetValues(typeof(TimelineAsset.DurationMode))) + { + var mode = (TimelineAsset.DurationMode)value; + var item = EditorGUIUtility.TextContent(string.Format(TimelineWindow.Styles.DurationModeText, L10n.Tr(ObjectNames.NicifyVariableName(mode.ToString())))); + + if (state.recording || state.IsEditingASubTimeline() || state.editSequence.asset == null + || state.editSequence.isReadOnly) + menu.AddDisabledItem(item); + else + menu.AddItem(item, state.editSequence.asset.durationMode == mode, () => SelectDurationCallback(state, mode)); + + menu.AddItem(DirectorStyles.showMarkersOnTimeline, state.showMarkerHeader, () => new ToggleShowMarkersOnTimeline().Execute(state)); + } + } + + static void SelectDurationCallback(WindowState state, TimelineAsset.DurationMode mode) + { + if (mode == state.editSequence.asset.durationMode) + return; + + TimelineUndo.PushUndo(state.editSequence.asset, "Duration Mode"); + + + // if we switched from Auto to Fixed, use the auto duration as the new fixed duration so the end marker stay in the same position. + if (state.editSequence.asset.durationMode == TimelineAsset.DurationMode.BasedOnClips && mode == TimelineAsset.DurationMode.FixedLength) + { + state.editSequence.asset.fixedDuration = state.editSequence.duration; + } + + state.editSequence.asset.durationMode = mode; + state.UpdateRootPlayableDuration(state.editSequence.duration); + } + } + + class Scrub : Manipulator + { + readonly Func<Event, WindowState, bool> m_OnMouseDown; + readonly Action<double> m_OnMouseDrag; + readonly Action m_OnMouseUp; + + bool m_IsCaptured; + + public Scrub(Func<Event, WindowState, bool> onMouseDown, Action<double> onMouseDrag, Action onMouseUp) + { + m_OnMouseDown = onMouseDown; + m_OnMouseDrag = onMouseDrag; + m_OnMouseUp = onMouseUp; + } + + protected override bool MouseDown(Event evt, WindowState state) + { + if (evt.button != 0) + return false; + + if (!m_OnMouseDown(evt, state)) + return false; + + state.AddCaptured(this); + m_IsCaptured = true; + + return true; + } + + protected override bool MouseUp(Event evt, WindowState state) + { + if (!m_IsCaptured) + return false; + + m_IsCaptured = false; + state.RemoveCaptured(this); + + m_OnMouseUp(); + + return true; + } + + protected override bool MouseDrag(Event evt, WindowState state) + { + if (!m_IsCaptured) + return false; + + m_OnMouseDrag(state.GetSnappedTimeAtMousePosition(evt.mousePosition)); + + return true; + } + } + + class TimeAreaItem : Control + { + public Color headColor { get; set; } + public Color lineColor { get; set; } + public bool drawLine { get; set; } + public bool drawHead { get; set; } + public bool canMoveHead { get; set; } + public string tooltip { get; set; } + public Vector2 boundOffset { get; set; } + + readonly GUIContent m_HeaderContent = new GUIContent(); + readonly GUIStyle m_Style; + readonly Tooltip m_Tooltip; + + Rect m_BoundingRect; + + float widgetHeight { get { return m_Style.fixedHeight; } } + float widgetWidth { get { return m_Style.fixedWidth; } } + + public Rect bounds + { + get + { + Rect r = m_BoundingRect; + r.y = TimelineWindow.instance.state.timeAreaRect.yMax - widgetHeight; + r.position += boundOffset; + + return r; + } + } + + public GUIStyle style + { + get { return m_Style; } + } + + + public bool showTooltip { get; set; } + + // is this the first frame the drag callback is being invoked + public bool firstDrag { get; private set; } + + public TimeAreaItem(GUIStyle style, Action<double> onDrag) + { + m_Style = style; + headColor = Color.white; + var scrub = new Scrub( + (evt, state) => + { + firstDrag = true; + return state.timeAreaRect.Contains(evt.mousePosition) && bounds.Contains(evt.mousePosition); + }, + (d) => + { + if (onDrag != null) + onDrag(d); + firstDrag = false; + }, + () => + { + showTooltip = false; + firstDrag = false; + } + ); + AddManipulator(scrub); + lineColor = m_Style.normal.textColor; + drawLine = true; + drawHead = true; + canMoveHead = false; + tooltip = string.Empty; + boundOffset = Vector2.zero; + m_Tooltip = new Tooltip(DirectorStyles.Instance.displayBackground, DirectorStyles.Instance.tinyFont); + } + + public void Draw(Rect rect, WindowState state, double time) + { + var clipRect = new Rect(0.0f, 0.0f, TimelineWindow.instance.position.width, TimelineWindow.instance.position.height); + clipRect.xMin += state.sequencerHeaderWidth; + + using (new GUIViewportScope(clipRect)) + { + Vector2 windowCoordinate = rect.min; + windowCoordinate.y += 4.0f; + + windowCoordinate.x = state.TimeToPixel(time); + + m_BoundingRect = new Rect((windowCoordinate.x - widgetWidth / 2.0f), windowCoordinate.y, widgetWidth, widgetHeight); + + // Do not paint if the time cursor goes outside the timeline bounds... + if (Event.current.type == EventType.Repaint) + { + if (m_BoundingRect.xMax < state.timeAreaRect.xMin) + return; + if (m_BoundingRect.xMin > state.timeAreaRect.xMax) + return; + } + + var top = new Vector3(windowCoordinate.x, rect.y - DirectorStyles.kDurationGuiThickness); + var bottom = new Vector3(windowCoordinate.x, rect.yMax); + + if (drawLine) + { + Rect lineRect = Rect.MinMaxRect(top.x - 0.5f, top.y, bottom.x + 0.5f, bottom.y); + EditorGUI.DrawRect(lineRect, lineColor); + } + + if (drawHead) + { + Color c = GUI.color; + GUI.color = headColor; + GUI.Box(bounds, m_HeaderContent, m_Style); + GUI.color = c; + + if (canMoveHead) + EditorGUIUtility.AddCursorRect(bounds, MouseCursor.MoveArrow); + } + + if (showTooltip) + { + m_Tooltip.text = TimeReferenceUtility.ToTimeString(time); + + Vector2 position = bounds.position; + position.y = state.timeAreaRect.y; + position.y -= m_Tooltip.bounds.height; + position.x -= Mathf.Abs(m_Tooltip.bounds.width - bounds.width) / 2.0f; + + Rect tooltipBounds = bounds; + tooltipBounds.position = position; + m_Tooltip.bounds = tooltipBounds; + + m_Tooltip.Draw(); + } + } + } + } +} |
