|
|
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;
FrameRange(area.x, area.x + area.width, 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); } }}
|