123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
- using UnityEditor.ShortcutManagement;
- using UnityEngine;
- using UnityEngine.Timeline;
- using MenuEntryPair = System.Collections.Generic.KeyValuePair<UnityEngine.GUIContent, UnityEditor.Timeline.TimelineAction>;
- namespace UnityEditor.Timeline
- {
- [ActiveInMode(TimelineModes.Default)]
- abstract class TimelineAction : MenuItemActionBase
- {
- public abstract bool Execute(WindowState state);
- public virtual MenuActionDisplayState GetDisplayState(WindowState state)
- {
- return MenuActionDisplayState.Visible;
- }
- public virtual bool IsChecked(WindowState state)
- {
- return false;
- }
- protected string GetDisplayName(WindowState state)
- {
- return menuName;
- }
- bool CanExecute(WindowState state)
- {
- return GetDisplayState(state) == MenuActionDisplayState.Visible;
- }
- public static void Invoke<T>(WindowState state) where T : TimelineAction
- {
- var action = AllActions.FirstOrDefault(x => x.GetType() == typeof(T));
- if (action != null && action.CanExecute(state))
- action.Execute(state);
- }
- // an instance of all TimelineActions
- public static readonly TimelineAction[] AllActions = GetActionsOfType(typeof(TimelineAction)).Select(x => (TimelineAction)x.GetConstructors()[0].Invoke(null)).ToArray();
- // an instance of all TimelineActions that should appear in a regular contextMenu
- public static readonly TimelineAction[] MenuActions = AllActions.Where(a => a.showInMenu && !(a is MarkerHeaderAction)).ToArray();
- public static void GetMenuEntries(IEnumerable<TimelineAction> actions, Vector2? mousePos, List<MenuActionItem> items)
- {
- var state = TimelineWindow.instance.state;
- var mode = TimelineWindow.instance.currentMode.mode;
- foreach (var action in actions)
- {
- var actionItem = action;
- action.mousePosition = mousePos;
- items.Add(
- new MenuActionItem()
- {
- category = action.category,
- entryName = action.GetDisplayName(state),
- shortCut = action.shortCut,
- isChecked = action.IsChecked(state),
- isActiveInMode = IsActionActiveInMode(action, mode),
- priority = action.priority,
- state = action.GetDisplayState(state),
- callback = () =>
- {
- actionItem.mousePosition = mousePos;
- actionItem.Execute(state);
- actionItem.mousePosition = null;
- }
- }
- );
- action.mousePosition = null;
- }
- }
- public static bool HandleShortcut(WindowState state, Event evt)
- {
- if (EditorGUI.IsEditingTextField())
- return false;
- foreach (var action in AllActions)
- {
- var attr = action.GetType().GetCustomAttributes(typeof(ShortcutAttribute), true);
- foreach (ShortcutAttribute shortcut in attr)
- {
- if (shortcut.MatchesEvent(evt))
- {
- if (s_ShowActionTriggeredByShortcut)
- Debug.Log(action.GetType().Name);
- if (!IsActionActiveInMode(action, TimelineWindow.instance.currentMode.mode))
- return false;
- var handled = action.Execute(state);
- if (handled)
- return true;
- }
- }
- }
- return false;
- }
- protected static bool DoInternal(Type t, WindowState state)
- {
- var action = (TimelineAction)t.GetConstructors()[0].Invoke(null);
- if (action.CanExecute(state))
- return action.Execute(state);
- return false;
- }
- }
- // indicates the action only applies to the marker header menu
- abstract class MarkerHeaderAction : TimelineAction
- {
- }
- [MenuEntry("Copy", MenuOrder.TimelineAction.Copy)]
- [Shortcut("Main Menu/Edit/Copy", EventCommandNames.Copy)]
- class CopyAction : TimelineAction
- {
- public static bool Do(WindowState state)
- {
- return DoInternal(typeof(CopyAction), state);
- }
- public override MenuActionDisplayState GetDisplayState(WindowState state)
- {
- return SelectionManager.Count() > 0 ? MenuActionDisplayState.Visible : MenuActionDisplayState.Disabled;
- }
- public override bool Execute(WindowState state)
- {
- TimelineEditor.clipboard.Clear();
- var clips = SelectionManager.SelectedClips().ToArray();
- if (clips.Length > 0)
- {
- ItemAction<TimelineClip>.Invoke<CopyClipsToClipboard>(state, clips);
- }
- var markers = SelectionManager.SelectedMarkers().ToArray();
- if (markers.Length > 0)
- {
- ItemAction<IMarker>.Invoke<CopyMarkersToClipboard>(state, markers);
- }
- var tracks = SelectionManager.SelectedTracks().ToArray();
- if (tracks.Length > 0)
- {
- CopyTracksToClipboard.Do(state, tracks);
- }
- return true;
- }
- }
- [MenuEntry("Paste", MenuOrder.TimelineAction.Paste)]
- [Shortcut("Main Menu/Edit/Paste", EventCommandNames.Paste)]
- class PasteAction : TimelineAction
- {
- public static bool Do(WindowState state)
- {
- return DoInternal(typeof(PasteAction), state);
- }
- public override MenuActionDisplayState GetDisplayState(WindowState state)
- {
- return CanPaste(state) ? MenuActionDisplayState.Visible : MenuActionDisplayState.Disabled;
- }
- public override bool Execute(WindowState state)
- {
- if (!CanPaste(state))
- return false;
- PasteItems(state, mousePosition);
- PasteTracks(state);
- state.Refresh();
- mousePosition = null;
- return true;
- }
- bool CanPaste(WindowState state)
- {
- var copiedItems = TimelineEditor.clipboard.GetCopiedItems().ToList();
- if (!copiedItems.Any())
- return TimelineEditor.clipboard.GetTracks().Any();
- return CanPasteItems(copiedItems, state, mousePosition);
- }
- static bool CanPasteItems(ICollection<ItemsPerTrack> itemsGroups, WindowState state, Vector2? mousePosition)
- {
- var hasItemsCopiedFromMultipleTracks = itemsGroups.Count > 1;
- var allItemsCopiedFromCurrentAsset = itemsGroups.All(x => x.targetTrack.timelineAsset == state.editSequence.asset);
- var hasUsedShortcut = mousePosition == null;
- var anySourceLocked = itemsGroups.Any(x => x.targetTrack != null && x.targetTrack.lockedInHierarchy);
- var targetTrack = GetPickedTrack();
- if (targetTrack == null)
- targetTrack = SelectionManager.SelectedTracks().FirstOrDefault();
- //do not paste if the user copied items from another timeline
- //if the copied items comes from > 1 track (since we do not know where to paste the copied items)
- //or if a keyboard shortcut was used (since the user will not see the paste result)
- if (!allItemsCopiedFromCurrentAsset)
- {
- var isSelectedTrackInCurrentAsset = targetTrack != null && targetTrack.timelineAsset == state.editSequence.asset;
- if (hasItemsCopiedFromMultipleTracks || (hasUsedShortcut && !isSelectedTrackInCurrentAsset))
- return false;
- }
- if (hasUsedShortcut)
- return !anySourceLocked; // copy/paste to same track
- if (hasItemsCopiedFromMultipleTracks)
- {
- //do not paste if the track which received the paste action does not contain a copied clip
- return !anySourceLocked && itemsGroups.Select(x => x.targetTrack).Contains(targetTrack);
- }
- var copiedItems = itemsGroups.SelectMany(i => i.items);
- return IsTrackValidForItems(targetTrack, copiedItems);
- }
- static void PasteItems(WindowState state, Vector2? mousePosition)
- {
- var copiedItems = TimelineEditor.clipboard.GetCopiedItems().ToList();
- var numberOfUniqueParentsInClipboard = copiedItems.Count();
- if (numberOfUniqueParentsInClipboard == 0) return;
- List<ITimelineItem> newItems;
- //if the copied items were on a single parent, then use the mouse position to get the parent OR the original parent
- if (numberOfUniqueParentsInClipboard == 1)
- {
- var itemsGroup = copiedItems.First();
- TrackAsset target = null;
- if (mousePosition.HasValue)
- target = GetPickedTrack();
- if (target == null)
- target = FindSuitableParentForSingleTrackPasteWithoutMouse(itemsGroup);
- var candidateTime = TimelineHelpers.GetCandidateTime(state, mousePosition, target);
- newItems = TimelineHelpers.DuplicateItemsUsingCurrentEditMode(state, TimelineEditor.clipboard.exposedPropertyTable, TimelineEditor.inspectedDirector, itemsGroup, target, candidateTime, "Paste Items").ToList();
- }
- //if copied items were on multiple parents, then the destination parents are the same as the original parents
- else
- {
- var time = TimelineHelpers.GetCandidateTime(state, mousePosition, copiedItems.Select(c => c.targetTrack).ToArray());
- newItems = TimelineHelpers.DuplicateItemsUsingCurrentEditMode(state, TimelineEditor.clipboard.exposedPropertyTable, TimelineEditor.inspectedDirector, copiedItems, time, "Paste Items").ToList();
- }
- TimelineHelpers.FrameItems(state, newItems);
- SelectionManager.RemoveTimelineSelection();
- foreach (var item in newItems)
- {
- SelectionManager.Add(item);
- }
- }
- static TrackAsset FindSuitableParentForSingleTrackPasteWithoutMouse(ItemsPerTrack itemsGroup)
- {
- var groupParent = itemsGroup.targetTrack; //set a main parent in the clipboard
- var selectedTracks = SelectionManager.SelectedTracks();
- if (selectedTracks.Contains(groupParent))
- {
- return groupParent;
- }
- //find a selected track suitable for all items
- var itemsToPaste = itemsGroup.items;
- var compatibleTrack = selectedTracks.FirstOrDefault(t => IsTrackValidForItems(t, itemsToPaste));
- return compatibleTrack != null ? compatibleTrack : groupParent;
- }
- static bool IsTrackValidForItems(TrackAsset track, IEnumerable<ITimelineItem> items)
- {
- if (track == null || track.lockedInHierarchy) return false;
- return items.All(i => i.IsCompatibleWithTrack(track));
- }
- static TrackAsset GetPickedTrack()
- {
- var rowGUI = PickerUtils.pickedElements.OfType<IRowGUI>().FirstOrDefault();
- if (rowGUI != null)
- return rowGUI.asset;
- return null;
- }
- static void PasteTracks(WindowState state)
- {
- var trackData = TimelineEditor.clipboard.GetTracks().ToList();
- if (trackData.Any())
- {
- SelectionManager.RemoveTimelineSelection();
- }
- foreach (var track in trackData)
- {
- var newTrack = track.item.Duplicate(TimelineEditor.clipboard.exposedPropertyTable, TimelineEditor.inspectedDirector, TimelineEditor.inspectedAsset);
- SelectionManager.Add(newTrack);
- foreach (var childTrack in newTrack.GetFlattenedChildTracks())
- {
- SelectionManager.Add(childTrack);
- }
- if (track.parent != null && track.parent.timelineAsset == state.editSequence.asset)
- {
- TrackExtensions.ReparentTracks(new List<TrackAsset> { newTrack }, track.parent, track.item);
- }
- }
- }
- }
- [MenuEntry("Duplicate", MenuOrder.TimelineAction.Duplicate)]
- [Shortcut("Main Menu/Edit/Duplicate", EventCommandNames.Duplicate)]
- class DuplicateAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return Execute(state, (item1, item2) => ItemsUtils.TimeGapBetweenItems(item1, item2, state));
- }
- internal bool Execute(WindowState state, Func<ITimelineItem, ITimelineItem, double> gapBetweenItems)
- {
- var selectedItems = SelectionManager.SelectedItems().ToItemsPerTrack().ToList();
- if (selectedItems.Any())
- {
- var requestedTime = CalculateDuplicateTime(selectedItems, gapBetweenItems);
- var duplicatedItems = TimelineHelpers.DuplicateItemsUsingCurrentEditMode(state, TimelineEditor.inspectedDirector, TimelineEditor.inspectedDirector, selectedItems, requestedTime, "Duplicate Items");
- TimelineHelpers.FrameItems(state, duplicatedItems);
- SelectionManager.RemoveTimelineSelection();
- foreach (var item in duplicatedItems)
- SelectionManager.Add(item);
- }
- var tracks = SelectionManager.SelectedTracks().ToArray();
- if (tracks.Length > 0)
- TrackAction.Invoke<DuplicateTracks>(state, tracks);
- state.Refresh();
- return true;
- }
- static double CalculateDuplicateTime(IEnumerable<ItemsPerTrack> duplicatedItems, Func<ITimelineItem, ITimelineItem, double> gapBetweenItems)
- {
- //Find the end time of the rightmost item
- var itemsOnTracks = duplicatedItems.SelectMany(i => i.targetTrack.GetItems()).ToList();
- var time = itemsOnTracks.Max(i => i.end);
- //From all the duplicated items, select the leftmost items
- var firstDuplicatedItems = duplicatedItems.Select(i => i.leftMostItem);
- var leftMostDuplicatedItems = firstDuplicatedItems.OrderBy(i => i.start).GroupBy(i => i.start).FirstOrDefault();
- if (leftMostDuplicatedItems == null) return 0.0;
- foreach (var leftMostItem in leftMostDuplicatedItems)
- {
- var siblings = leftMostItem.parentTrack.GetItems();
- var rightMostSiblings = siblings.OrderByDescending(i => i.end).GroupBy(i => i.end).FirstOrDefault();
- if (rightMostSiblings == null) continue;
- foreach (var sibling in rightMostSiblings)
- time = Math.Max(time, sibling.end + gapBetweenItems(leftMostItem, sibling));
- }
- return time;
- }
- }
- [MenuEntry("Delete", MenuOrder.TimelineAction.Delete)]
- [Shortcut("Main Menu/Edit/Delete", EventCommandNames.Delete)]
- [ShortcutPlatformOverride(RuntimePlatform.OSXEditor, KeyCode.Backspace, ShortcutModifiers.Action)]
- [ActiveInMode(TimelineModes.Default)]
- class DeleteAction : TimelineAction
- {
- public override MenuActionDisplayState GetDisplayState(WindowState state)
- {
- return CanDelete(state) ? MenuActionDisplayState.Visible : MenuActionDisplayState.Disabled;
- }
- static bool CanDelete(WindowState state)
- {
- if (state.editSequence.isReadOnly)
- return false;
- // All() returns true when empty
- return SelectionManager.SelectedTracks().All(x => !x.lockedInHierarchy) &&
- SelectionManager.SelectedItems().All(x => x.parentTrack == null || !x.parentTrack.lockedInHierarchy);
- }
- public override bool Execute(WindowState state)
- {
- if (SelectionManager.GetCurrentInlineEditorCurve() != null)
- return false;
- if (!CanDelete(state))
- return false;
- var selectedItems = SelectionManager.SelectedItems();
- DeleteItems(selectedItems);
- var tracks = SelectionManager.SelectedTracks().ToArray();
- if (tracks.Any())
- TrackAction.Invoke<DeleteTracks>(state, tracks);
- state.Refresh();
- return selectedItems.Any() || tracks.Length > 0;
- }
- internal static void DeleteItems(IEnumerable<ITimelineItem> items)
- {
- var tracks = items.GroupBy(c => c.parentTrack);
- foreach (var track in tracks)
- TimelineUndo.PushUndo(track.Key, "Delete Items");
- TimelineAnimationUtilities.UnlinkAnimationWindowFromClips(items.OfType<ClipItem>().Select(i => i.clip));
- EditMode.PrepareItemsDelete(ItemsUtils.ToItemsPerTrack(items));
- EditModeUtils.Delete(items);
- SelectionManager.RemoveAllClips();
- }
- }
- [MenuEntry("Match Content", MenuOrder.TimelineAction.MatchContent)]
- [Shortcut(Shortcuts.Timeline.matchContent)]
- class MatchContent : TimelineAction
- {
- public override MenuActionDisplayState GetDisplayState(WindowState state)
- {
- var clips = SelectionManager.SelectedClips().ToArray();
- if (!clips.Any() || SelectionManager.GetCurrentInlineEditorCurve() != null)
- return MenuActionDisplayState.Hidden;
- return clips.Any(TimelineHelpers.HasUsableAssetDuration)
- ? MenuActionDisplayState.Visible
- : MenuActionDisplayState.Disabled;
- }
- public override bool Execute(WindowState state)
- {
- if (SelectionManager.GetCurrentInlineEditorCurve() != null)
- return false;
- var clips = SelectionManager.SelectedClips().ToArray();
- return clips.Length > 0 && ClipModifier.MatchContent(clips);
- }
- }
- [Shortcut(Shortcuts.Timeline.play)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class PlayTimelineAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- var currentState = state.playing;
- state.SetPlaying(!currentState);
- return true;
- }
- }
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class SelectAllAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- // otherwise select all tracks.
- SelectionManager.Clear();
- state.GetWindow().allTracks.ForEach(x => SelectionManager.Add(x.track));
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.previousFrame)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class PreviousFrameAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- state.editSequence.frame--;
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.nextFrame)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class NextFrameAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- state.editSequence.frame++;
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.frameAll)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class FrameAllAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- var inlineCurveEditor = SelectionManager.GetCurrentInlineEditorCurve();
- if (inlineCurveEditor != null && inlineCurveEditor.inlineCurvesSelected)
- {
- FrameSelectedAction.FrameInlineCurves(inlineCurveEditor, state, false);
- return true;
- }
- if (state.IsEditingASubItem())
- return false;
- var w = state.GetWindow();
- if (w == null || w.treeView == null)
- return false;
- var visibleTracks = w.treeView.visibleTracks.ToList();
- if (state.editSequence.asset != null && state.editSequence.asset.markerTrack != null)
- visibleTracks.Add(state.editSequence.asset.markerTrack);
- if (visibleTracks.Count == 0)
- return false;
- var startTime = float.MaxValue;
- var endTime = float.MinValue;
- foreach (var t in visibleTracks)
- {
- if (t == null)
- continue;
- double trackStart, trackEnd;
- t.GetItemRange(out trackStart, out trackEnd);
- startTime = Mathf.Min(startTime, (float)trackStart);
- endTime = Mathf.Max(endTime, (float)(trackEnd));
- }
- if (startTime != float.MinValue)
- {
- FrameSelectedAction.FrameRange(startTime, endTime, state);
- return true;
- }
- return false;
- }
- }
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class FrameSelectedAction : TimelineAction
- {
- public static void FrameRange(float startTime, float endTime, WindowState state)
- {
- if (startTime > endTime)
- {
- return;
- }
- var halfDuration = endTime - Math.Max(0.0f, startTime);
- if (halfDuration > 0.0f)
- {
- state.SetTimeAreaShownRange(Mathf.Max(-10.0f, startTime - (halfDuration * 0.1f)),
- endTime + (halfDuration * 0.1f));
- }
- else
- {
- // start == end
- // keep the zoom level constant, only pan the time area to center the item
- var currentRange = state.timeAreaShownRange.y - state.timeAreaShownRange.x;
- state.SetTimeAreaShownRange(startTime - currentRange / 2, startTime + currentRange / 2);
- }
- TimelineZoomManipulator.InvalidateWheelZoom();
- state.Evaluate();
- }
- public override bool Execute(WindowState state)
- {
- var inlineCurveEditor = SelectionManager.GetCurrentInlineEditorCurve();
- if (inlineCurveEditor != null && inlineCurveEditor.inlineCurvesSelected)
- {
- FrameInlineCurves(inlineCurveEditor, state, true);
- return true;
- }
- if (state.IsEditingASubItem())
- return false;
- if (SelectionManager.Count() == 0)
- return false;
- var startTime = float.MaxValue;
- var endTime = float.MinValue;
- var clips = SelectionManager.SelectedClipGUI();
- var markers = SelectionManager.SelectedMarkers();
- if (!clips.Any() && !markers.Any())
- return false;
- foreach (var c in clips)
- {
- startTime = Mathf.Min(startTime, (float)c.clip.start);
- endTime = Mathf.Max(endTime, (float)c.clip.end);
- if (c.clipCurveEditor != null)
- {
- c.clipCurveEditor.FrameClip();
- }
- }
- foreach (var marker in markers)
- {
- startTime = Mathf.Min(startTime, (float)marker.time);
- endTime = Mathf.Max(endTime, (float)marker.time);
- }
- FrameRange(startTime, endTime, state);
- return true;
- }
- public static void FrameInlineCurves(IClipCurveEditorOwner curveEditorOwner, WindowState state, bool selectionOnly)
- {
- var curveEditor = curveEditorOwner.clipCurveEditor.curveEditor;
- var frameBounds = selectionOnly ? curveEditor.GetSelectionBounds() : curveEditor.GetClipBounds();
- var clipGUI = curveEditorOwner as TimelineClipGUI;
- var areaOffset = 0.0f;
- if (clipGUI != null)
- {
- areaOffset = (float)Math.Max(0.0, clipGUI.clip.FromLocalTimeUnbound(0.0));
- var timeScale = (float)clipGUI.clip.timeScale; // Note: The getter for clip.timeScale is guaranteed to never be zero.
- // Apply scaling
- var newMin = frameBounds.min.x / timeScale;
- var newMax = (frameBounds.max.x - frameBounds.min.x) / timeScale + newMin;
- frameBounds.SetMinMax(
- new Vector3(newMin, frameBounds.min.y, frameBounds.min.z),
- new Vector3(newMax, frameBounds.max.y, frameBounds.max.z));
- }
- curveEditor.Frame(frameBounds, true, true);
- var area = curveEditor.shownAreaInsideMargins;
- area.x += areaOffset;
- var curveStart = curveEditorOwner.clipCurveEditor.dataSource.start;
- FrameRange(curveStart + frameBounds.min.x, curveStart + frameBounds.max.x, state);
- }
- }
- [Shortcut(Shortcuts.Timeline.previousKey)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class PrevKeyAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- var keyTraverser = new Utilities.KeyTraverser(state.editSequence.asset, 0.01f / state.referenceSequence.frameRate);
- var time = keyTraverser.GetPrevKey((float)state.editSequence.time, state.dirtyStamp);
- if (time != state.editSequence.time)
- {
- state.editSequence.time = time;
- }
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.nextKey)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class NextKeyAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- var keyTraverser = new Utilities.KeyTraverser(state.editSequence.asset, 0.01f / state.referenceSequence.frameRate);
- var time = keyTraverser.GetNextKey((float)state.editSequence.time, state.dirtyStamp);
- if (time != state.editSequence.time)
- {
- state.editSequence.time = time;
- }
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.goToStart)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class GotoStartAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- state.editSequence.time = 0.0f;
- state.EnsurePlayHeadIsVisible();
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.goToEnd)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class GotoEndAction : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- state.editSequence.time = state.editSequence.duration;
- state.EnsurePlayHeadIsVisible();
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.zoomIn)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class ZoomIn : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- TimelineZoomManipulator.Instance.DoZoom(1.15f, state);
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.zoomOut)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class ZoomOut : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- TimelineZoomManipulator.Instance.DoZoom(0.85f, state);
- return true;
- }
- }
- [Shortcut(Shortcuts.Timeline.collapseGroup)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class CollapseGroup : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.CollapseGroup(state);
- }
- }
- [Shortcut(Shortcuts.Timeline.unCollapseGroup)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class UnCollapseGroup : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.UnCollapseGroup(state);
- }
- }
- [Shortcut(Shortcuts.Timeline.selectLeftItem)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class SelectLeftClip : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- // Switches to track header if no left track exists
- return KeyboardNavigation.SelectLeftItem(state);
- }
- }
- [Shortcut(Shortcuts.Timeline.selectRightItem)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class SelectRightClip : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.SelectRightItem(state);
- }
- }
- [Shortcut(Shortcuts.Timeline.selectUpItem)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class SelectUpClip : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.SelectUpItem(state);
- }
- }
- [Shortcut(Shortcuts.Timeline.selectUpTrack)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class SelectUpTrack : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.SelectUpTrack();
- }
- }
- [Shortcut(Shortcuts.Timeline.selectDownItem)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class SelectDownClip : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.SelectDownItem(state);
- }
- }
- [Shortcut(Shortcuts.Timeline.selectDownTrack)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class SelectDownTrack : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- if (!KeyboardNavigation.ClipAreaActive() && !KeyboardNavigation.TrackHeadActive())
- return KeyboardNavigation.FocusFirstVisibleItem(state);
- else
- return KeyboardNavigation.SelectDownTrack();
- }
- }
- [Shortcut(Shortcuts.Timeline.multiSelectLeft)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class MultiselectLeftClip : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.SelectLeftItem(state, true);
- }
- }
- [Shortcut(Shortcuts.Timeline.multiSelectRight)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class MultiselectRightClip : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.SelectRightItem(state, true);
- }
- }
- [Shortcut(Shortcuts.Timeline.multiSelectUp)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class MultiselectUpTrack : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.SelectUpTrack(true);
- }
- }
- [Shortcut(Shortcuts.Timeline.multiSelectDown)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class MultiselectDownTrack : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- return KeyboardNavigation.SelectDownTrack(true);
- }
- }
- [Shortcut(Shortcuts.Timeline.toggleClipTrackArea)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class ToggleClipTrackArea : TimelineAction
- {
- public override bool Execute(WindowState state)
- {
- if (KeyboardNavigation.TrackHeadActive())
- return KeyboardNavigation.FocusFirstVisibleItem(state, SelectionManager.SelectedTracks());
- if (!KeyboardNavigation.ClipAreaActive())
- return KeyboardNavigation.FocusFirstVisibleItem(state);
- var item = KeyboardNavigation.GetVisibleSelectedItems().LastOrDefault();
- if (item != null)
- SelectionManager.SelectOnly(item.parentTrack);
- return true;
- }
- }
- [MenuEntry("Mute", MenuOrder.TrackAction.MuteTrack)]
- class ToggleMuteMarkersOnTimeline : MarkerHeaderAction
- {
- public override bool IsChecked(WindowState state)
- {
- return IsMarkerTrackValid(state) && state.editSequence.asset.markerTrack.muted;
- }
- public override bool Execute(WindowState state)
- {
- if (state.showMarkerHeader)
- ToggleMute(state);
- return true;
- }
- static void ToggleMute(WindowState state)
- {
- var timeline = state.editSequence.asset;
- timeline.CreateMarkerTrack();
- TimelineUndo.PushUndo(timeline.markerTrack, "Toggle Mute");
- timeline.markerTrack.muted = !timeline.markerTrack.muted;
- }
- static bool IsMarkerTrackValid(WindowState state)
- {
- var timeline = state.editSequence.asset;
- return timeline != null && timeline.markerTrack != null;
- }
- }
- [MenuEntry("Show Markers", MenuOrder.TrackAction.ShowHideMarkers)]
- [ActiveInMode(TimelineModes.Default | TimelineModes.ReadOnly)]
- class ToggleShowMarkersOnTimeline : MarkerHeaderAction
- {
- public override bool IsChecked(WindowState state)
- {
- return state.showMarkerHeader;
- }
- public override bool Execute(WindowState state)
- {
- ToggleShow(state);
- return true;
- }
- static void ToggleShow(WindowState state)
- {
- state.GetWindow().SetShowMarkerHeader(!state.showMarkerHeader);
- }
- }
- }
|