123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEditor.Timeline.Actions;
- using UnityEngine;
- using UnityEngine.Timeline;
- using Object = UnityEngine.Object;
-
- namespace UnityEditor.Timeline
- {
- static class SequencerContextMenu
- {
- static class Styles
- {
- public static readonly string addItemFromAssetTemplate = L10n.Tr("Add {0} From {1}");
- public static readonly string addSingleItemFromAssetTemplate = L10n.Tr("Add From {1}");
- public static readonly string addItemTemplate = L10n.Tr("Add {0}");
- public static readonly string typeSelectorTemplate = L10n.Tr("Select {0}");
- public static readonly string trackGroup = L10n.Tr("Track Group");
- public static readonly string trackSubGroup = L10n.Tr("Track Sub-Group");
- public static readonly string addTrackLayer = L10n.Tr("Add Layer");
- public static readonly string layerName = L10n.Tr("Layer {0}");
- }
-
- public static void ShowNewTracksContextMenu(ICollection<TrackAsset> tracks, WindowState state)
- {
- var menu = new GenericMenu();
- List<MenuActionItem> items = new List<MenuActionItem>(100);
- BuildNewTracksContextMenu(items, tracks, state);
- ActionManager.BuildMenu(menu, items);
- menu.ShowAsContext();
- }
-
- public static void ShowNewTracksContextMenu(ICollection<TrackAsset> tracks, WindowState state, Rect rect)
- {
- var menu = new GenericMenu();
- List<MenuActionItem> items = new List<MenuActionItem>(100);
- BuildNewTracksContextMenu(items, tracks, state);
- ActionManager.BuildMenu(menu, items);
- menu.DropDown(rect);
- }
-
- public static void ShowTrackContextMenu(Vector2? mousePosition)
- {
- var items = new List<MenuActionItem>();
- var menu = new GenericMenu();
- BuildTrackContextMenu(items, mousePosition);
- ActionManager.BuildMenu(menu, items);
- menu.ShowAsContext();
- }
-
- public static void ShowItemContextMenu(Vector2 mousePosition)
- {
- var menu = new GenericMenu();
- var items = new List<MenuActionItem>();
- BuildItemContextMenu(items, mousePosition);
- ActionManager.BuildMenu(menu, items);
- menu.ShowAsContext();
- }
-
- public static void BuildItemContextMenu(List<MenuActionItem> items, Vector2 mousePosition)
- {
- ActionManager.GetMenuEntries(ActionManager.TimelineActions, mousePosition, items);
- ActionManager.GetMenuEntries(ActionManager.ClipActions, items);
- ActionManager.GetMenuEntries(ActionManager.MarkerActions, items);
-
- var clips = TimelineEditor.selectedClips;
- if (clips.Length > 0)
- AddMarkerMenuCommands(items, clips.Select(c => c.GetParentTrack()).Distinct().ToList(), TimelineHelpers.GetCandidateTime(mousePosition));
- }
-
- public static void BuildNewTracksContextMenu(List<MenuActionItem> menuItems, ICollection<TrackAsset> parentTracks, WindowState state, string format = null)
- {
- if (parentTracks == null)
- parentTracks = new TrackAsset[0];
-
- if (string.IsNullOrEmpty(format))
- format = "{0}";
-
- // Add Group or SubGroup
- var title = string.Format(format, parentTracks.Any(t => t != null) ? Styles.trackSubGroup : Styles.trackGroup);
- var menuState = ActionValidity.Valid;
- if (state.editSequence.isReadOnly)
- menuState = ActionValidity.Invalid;
- if (parentTracks.Any() && parentTracks.Any(t => t != null && t.lockedInHierarchy))
- menuState = ActionValidity.Invalid;
-
- GenericMenu.MenuFunction command = () =>
- {
- SelectionManager.Clear();
- if (parentTracks.Count == 0)
- Selection.Add(TimelineHelpers.CreateTrack<GroupTrack>(null, title));
-
- foreach (var parentTrack in parentTracks)
- Selection.Add(TimelineHelpers.CreateTrack<GroupTrack>(parentTrack, title));
-
- TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved);
- };
-
- menuItems.Add(
- new MenuActionItem()
- {
- category = string.Empty,
- entryName = title,
- isActiveInMode = true,
- priority = MenuPriority.AddItem.addGroup,
- state = menuState,
- isChecked = false,
- callback = command
- }
- );
-
-
- var allTypes = TypeUtility.AllTrackTypes().Where(x => x != typeof(GroupTrack) && !TypeUtility.IsHiddenInMenu(x)).ToList();
-
- int builtInPriority = MenuPriority.AddItem.addTrack;
- int customPriority = MenuPriority.AddItem.addCustomTrack;
- foreach (var trackType in allTypes)
- {
- var trackItemType = trackType;
-
- command = () =>
- {
- SelectionManager.Clear();
-
- if (parentTracks.Count == 0)
- SelectionManager.Add(TimelineHelpers.CreateTrack((Type)trackItemType, null));
-
- foreach (var parentTrack in parentTracks)
- SelectionManager.Add(TimelineHelpers.CreateTrack((Type)trackItemType, parentTrack));
- };
-
- menuItems.Add(
- new MenuActionItem()
- {
- category = TimelineHelpers.GetTrackCategoryName(trackType),
- entryName = string.Format(format, TimelineHelpers.GetTrackMenuName(trackItemType)),
- isActiveInMode = true,
- priority = TypeUtility.IsBuiltIn(trackType) ? builtInPriority++ : customPriority++,
- state = menuState,
- callback = command
- }
- );
- }
- }
-
- public static void BuildTrackContextMenu(List<MenuActionItem> items, Vector2? mousePosition)
- {
- var tracks = SelectionManager.SelectedTracks().ToArray();
- if (tracks.Length == 0)
- return;
-
- ActionManager.GetMenuEntries(ActionManager.TimelineActions, mousePosition, items);
- ActionManager.GetMenuEntries(ActionManager.TrackActions, items);
- AddLayeredTrackCommands(items, tracks);
-
- var first = tracks.First().GetType();
- var allTheSame = tracks.All(t => t.GetType() == first);
- if (allTheSame)
- {
- if (first != typeof(GroupTrack))
- {
- var candidateTime = TimelineHelpers.GetCandidateTime(mousePosition, tracks);
- AddClipMenuCommands(items, tracks, candidateTime);
- AddMarkerMenuCommands(items, tracks, candidateTime);
- }
- else
- {
- BuildNewTracksContextMenu(items, tracks, TimelineWindow.instance.state, Styles.addItemTemplate);
- }
- }
- }
-
- static void AddLayeredTrackCommands(List<MenuActionItem> menuItems, ICollection<TrackAsset> tracks)
- {
- if (tracks.Count == 0)
- return;
-
- var layeredType = tracks.First().GetType();
- // animation tracks have a special menu.
- if (layeredType == typeof(AnimationTrack))
- return;
-
- // must implement ILayerable
- if (!typeof(UnityEngine.Timeline.ILayerable).IsAssignableFrom(layeredType))
- return;
-
- if (tracks.Any(t => t.GetType() != layeredType))
- return;
-
- // only supported on the master track no nesting.
- if (tracks.Any(t => t.isSubTrack))
- return;
-
- var enabled = tracks.All(t => t != null && !t.lockedInHierarchy) && !TimelineWindow.instance.state.editSequence.isReadOnly;
- int priority = MenuPriority.AddTrackMenu.addLayerTrack;
- GenericMenu.MenuFunction menuCallback = () =>
- {
- foreach (var track in tracks)
- TimelineHelpers.CreateTrack(layeredType, track, string.Format(Styles.layerName, track.GetChildTracks().Count() + 1));
- };
-
- var entryName = Styles.addTrackLayer;
- menuItems.Add(
- new MenuActionItem()
- {
- category = string.Empty,
- entryName = entryName,
- isActiveInMode = true,
- priority = priority++,
- state = enabled ? ActionValidity.Valid : ActionValidity.Invalid,
- callback = menuCallback
- }
- );
- }
-
- static void AddClipMenuCommands(List<MenuActionItem> menuItems, ICollection<TrackAsset> tracks, double candidateTime)
- {
- if (!tracks.Any())
- return;
-
- var trackAsset = tracks.First();
- var trackType = trackAsset.GetType();
- if (tracks.Any(t => t.GetType() != trackType))
- return;
-
- var enabled = tracks.All(t => t != null && !t.lockedInHierarchy) && !TimelineWindow.instance.state.editSequence.isReadOnly;
- var assetTypes = TypeUtility.GetPlayableAssetsHandledByTrack(trackType);
- var visibleAssetTypes = TypeUtility.GetVisiblePlayableAssetsHandledByTrack(trackType);
-
- // skips the name if there is only a single type
- var commandNameTemplate = assetTypes.Count() == 1 ? Styles.addSingleItemFromAssetTemplate : Styles.addItemFromAssetTemplate;
- int builtInPriority = MenuPriority.AddItem.addClip;
- int customPriority = MenuPriority.AddItem.addCustomClip;
- foreach (var assetType in assetTypes)
- {
- var assetItemType = assetType;
- var category = TimelineHelpers.GetItemCategoryName(assetType);
- Action<Object> onObjectChanged = obj =>
- {
- if (obj != null)
- {
- foreach (var t in tracks)
- {
- TimelineHelpers.CreateClipOnTrack(assetItemType, obj, t, candidateTime);
- }
- }
- };
-
- foreach (var objectReference in TypeUtility.ObjectReferencesForType(assetType))
- {
- var isSceneReference = objectReference.isSceneReference;
- var dataType = objectReference.type;
- GenericMenu.MenuFunction menuCallback = () =>
- {
- ObjectSelector.get.Show(null, dataType, null, isSceneReference, null, (obj) => onObjectChanged(obj), null);
- ObjectSelector.get.titleContent = EditorGUIUtility.TrTextContent(string.Format(Styles.typeSelectorTemplate, TypeUtility.GetDisplayName(dataType)));
- };
-
- menuItems.Add(
- new MenuActionItem()
- {
- category = category,
- entryName = string.Format(commandNameTemplate, TypeUtility.GetDisplayName(assetType), TypeUtility.GetDisplayName(objectReference.type)),
- isActiveInMode = true,
- priority = TypeUtility.IsBuiltIn(assetType) ? builtInPriority++ : customPriority++,
- state = enabled ? ActionValidity.Valid : ActionValidity.Invalid,
- callback = menuCallback
- }
- );
- }
- }
-
- foreach (var assetType in visibleAssetTypes)
- {
- var assetItemType = assetType;
- var category = TimelineHelpers.GetItemCategoryName(assetType);
- var commandName = string.Format(Styles.addItemTemplate, TypeUtility.GetDisplayName(assetType));
- GenericMenu.MenuFunction command = () =>
- {
- foreach (var t in tracks)
- {
- TimelineHelpers.CreateClipOnTrack(assetItemType, t, candidateTime);
- }
- };
-
- menuItems.Add(
- new MenuActionItem()
- {
- category = category,
- entryName = commandName,
- isActiveInMode = true,
- priority = TypeUtility.IsBuiltIn(assetItemType) ? builtInPriority++ : customPriority++,
- state = enabled ? ActionValidity.Valid : ActionValidity.Invalid,
- callback = command
- }
- );
- }
- }
-
- static void AddMarkerMenuCommands(List<MenuActionItem> menu, IEnumerable<Type> markerTypes, Action<Type, Object> addMarkerCommand, bool enabled)
- {
- int builtInPriority = MenuPriority.AddItem.addMarker;
- int customPriority = MenuPriority.AddItem.addCustomMarker;
- foreach (var markerType in markerTypes)
- {
- var markerItemType = markerType;
- string category = TimelineHelpers.GetItemCategoryName(markerItemType);
- menu.Add(
- new MenuActionItem()
- {
- category = category,
- entryName = string.Format(Styles.addItemTemplate, TypeUtility.GetDisplayName(markerType)),
- isActiveInMode = true,
- priority = TypeUtility.IsBuiltIn(markerType) ? builtInPriority++ : customPriority++,
- state = enabled ? ActionValidity.Valid : ActionValidity.Invalid,
- callback = () => addMarkerCommand(markerItemType, null)
- }
- );
-
- foreach (var objectReference in TypeUtility.ObjectReferencesForType(markerType))
- {
- var isSceneReference = objectReference.isSceneReference;
- GenericMenu.MenuFunction menuCallback = () =>
- {
- Type assetDataType = objectReference.type;
- ObjectSelector.get.titleContent = EditorGUIUtility.TrTextContent(string.Format(Styles.typeSelectorTemplate, TypeUtility.GetDisplayName(assetDataType)));
- ObjectSelector.get.Show(null, assetDataType, null, isSceneReference, null, obj =>
- {
- if (obj != null)
- addMarkerCommand(markerItemType, obj);
- }, null);
- };
-
- menu.Add(
- new MenuActionItem
- {
- category = TimelineHelpers.GetItemCategoryName(markerItemType),
- entryName = string.Format(Styles.addItemFromAssetTemplate, TypeUtility.GetDisplayName(markerType), TypeUtility.GetDisplayName(objectReference.type)),
- isActiveInMode = true,
- priority = TypeUtility.IsBuiltIn(markerType) ? builtInPriority++ : customPriority++,
- state = enabled ? ActionValidity.Valid : ActionValidity.Invalid,
- callback = menuCallback
- }
- );
- }
- }
- }
-
- static void AddMarkerMenuCommands(List<MenuActionItem> menuItems, ICollection<TrackAsset> tracks, double candidateTime)
- {
- if (tracks.Count == 0)
- return;
-
- var enabled = tracks.All(t => !t.lockedInHierarchy) && !TimelineWindow.instance.state.editSequence.isReadOnly;
- var addMarkerCommand = new Action<Type, Object>((type, obj) => AddMarkersCallback(tracks, type, candidateTime, obj));
-
- AddMarkerMenuCommands(menuItems, tracks, addMarkerCommand, enabled);
- }
-
- static void AddMarkerMenuCommands(List<MenuActionItem> menuItems, ICollection<TrackAsset> tracks, Action<Type, Object> command, bool enabled)
- {
- var markerTypes = TypeUtility.GetBuiltInMarkerTypes().Union(TypeUtility.GetUserMarkerTypes());
- if (tracks != null)
- markerTypes = markerTypes.Where(x => tracks.All(track => (track == null) || TypeUtility.DoesTrackSupportMarkerType(track, x))); // null track indicates marker track to be created
-
- AddMarkerMenuCommands(menuItems, markerTypes, command, enabled);
- }
-
- static void AddMarkersCallback(ICollection<TrackAsset> targets, Type markerType, double time, Object obj)
- {
- SelectionManager.Clear();
- foreach (var target in targets)
- {
- var marker = TimelineHelpers.CreateMarkerOnTrack(markerType, obj, target, time);
- SelectionManager.Add(marker);
- }
- TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved);
- }
- }
- }
|