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/Manipulators/Move/MoveItemHandler.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/Manipulators/Move/MoveItemHandler.cs')
| -rw-r--r-- | Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs new file mode 100644 index 0000000..aac3e4d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs @@ -0,0 +1,312 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + class MoveItemHandler : IAttractable, IAttractionHandler + { + bool m_Grabbing; + + MovingItems m_LeftMostMovingItems; + MovingItems m_RightMostMovingItems; + + HashSet<TimelineItemGUI> m_ItemGUIs; + ItemsGroup m_ItemsGroup; + + public TrackAsset targetTrack { get; private set; } + + public bool allowTrackSwitch { get; private set; } + + int m_GrabbedModalUndoGroup = -1; + + readonly WindowState m_State; + + public MovingItems[] movingItems { get; private set; } + + public MoveItemHandler(WindowState state) + { + m_State = state; + } + + public void Grab(IEnumerable<ITimelineItem> items, TrackAsset referenceTrack) + { + Grab(items, referenceTrack, Vector2.zero); + } + + public void Grab(IEnumerable<ITimelineItem> items, TrackAsset referenceTrack, Vector2 mousePosition) + { + if (items == null) return; + + items = items.ToArray(); // Cache enumeration result + + if (!items.Any()) return; + + m_GrabbedModalUndoGroup = Undo.GetCurrentGroup(); + + var trackItems = items.GroupBy(c => c.parentTrack).ToArray(); + var trackItemsCount = trackItems.Length; + var tracks = items.Select(c => c.parentTrack).Where(x => x != null).Distinct(); + + movingItems = new MovingItems[trackItemsCount]; + + allowTrackSwitch = trackItemsCount == 1 && !trackItems.SelectMany(x => x).Any(x => x is MarkerItem); // For now, track switch is only supported when all items are on the same track and there are no items + foreach (var sourceTrack in tracks) + { + // one push per track handles all the clips on the track + TimelineUndo.PushUndo(sourceTrack, "Move Items"); + + // push all markers on the track because of ripple + foreach (var marker in sourceTrack.GetMarkers().OfType<ScriptableObject>()) + TimelineUndo.PushUndo(marker, "Move Items"); + } + + for (var i = 0; i < trackItemsCount; ++i) + { + var track = trackItems[i].Key; + var grabbedItems = new MovingItems(m_State, track, trackItems[i].ToArray(), referenceTrack, mousePosition, allowTrackSwitch); + movingItems[i] = grabbedItems; + } + + m_LeftMostMovingItems = null; + m_RightMostMovingItems = null; + + foreach (var grabbedTrackItems in movingItems) + { + if (m_LeftMostMovingItems == null || m_LeftMostMovingItems.start > grabbedTrackItems.start) + m_LeftMostMovingItems = grabbedTrackItems; + + if (m_RightMostMovingItems == null || m_RightMostMovingItems.end < grabbedTrackItems.end) + m_RightMostMovingItems = grabbedTrackItems; + } + + m_ItemGUIs = new HashSet<TimelineItemGUI>(); + m_ItemsGroup = new ItemsGroup(items); + + foreach (var item in items) + m_ItemGUIs.Add(item.gui); + + targetTrack = referenceTrack; + + EditMode.BeginMove(this); + m_Grabbing = true; + } + + public void Drop() + { + if (IsValidDrop()) + { + foreach (var grabbedItems in movingItems) + { + var track = grabbedItems.targetTrack; + TimelineUndo.PushUndo(track, "Move Items"); + + if (EditModeUtils.IsInfiniteTrack(track) && grabbedItems.clips.Any()) + ((AnimationTrack)track).ConvertToClipMode(); + } + + EditMode.FinishMove(); + + Done(); + } + else + { + Cancel(); + } + + EditMode.ClearEditMode(); + } + + bool IsValidDrop() + { + return movingItems.All(g => g.canDrop); + } + + void Cancel() + { + if (!m_Grabbing) + return; + + // TODO fix undo reselection persistency + // identify the clips by their playable asset, since that reference will survive the undo + // This is a workaround, until a more persistent fix for selection of clips across Undo can be found + var assets = movingItems.SelectMany(x => x.clips).Select(x => x.asset); + + Undo.RevertAllDownToGroup(m_GrabbedModalUndoGroup); + + // reselect the clips from the original clip + var clipsToSelect = movingItems.Select(x => x.originalTrack).SelectMany(x => x.GetClips()).Where(x => assets.Contains(x.asset)).ToArray(); + SelectionManager.RemoveTimelineSelection(); + + foreach (var c in clipsToSelect) + SelectionManager.Add(c); + + Done(); + } + + void Done() + { + foreach (var movingItem in movingItems) + { + foreach (var item in movingItem.items) + { + if (item.gui != null) + item.gui.isInvalid = false; + } + } + + movingItems = null; + m_LeftMostMovingItems = null; + m_RightMostMovingItems = null; + m_Grabbing = false; + + m_State.Refresh(); + } + + public double start { get { return m_ItemsGroup.start; } } + + public double end { get { return m_ItemsGroup.end; } } + + public bool ShouldSnapTo(ISnappable snappable) + { + var itemGUI = snappable as TimelineItemGUI; + return itemGUI != null && !m_ItemGUIs.Contains(itemGUI); + } + + public void UpdateTrackTarget(TrackAsset track) + { + if (!EditMode.AllowTrackSwitch()) + return; + + targetTrack = track; + + var targetTracksChanged = false; + + foreach (var grabbedItem in movingItems) + { + var prevTrackGUI = grabbedItem.targetTrack; + + grabbedItem.SetReferenceTrack(track); + + targetTracksChanged = grabbedItem.targetTrack != prevTrackGUI; + } + + if (targetTracksChanged) + EditMode.HandleTrackSwitch(movingItems); + + RefreshPreviewItems(); + + m_State.rebuildGraph |= targetTracksChanged; + } + + public void OnGUI(Event evt) + { + if (!m_Grabbing) + return; + + if (evt.type != EventType.Repaint) + return; + + var isValid = IsValidDrop(); + + using (new GUIViewportScope(m_State.GetWindow().sequenceContentRect)) + { + foreach (var grabbedClip in movingItems) + { + grabbedClip.RefreshBounds(m_State, evt.mousePosition); + + if (!grabbedClip.HasAnyDetachedParents()) + continue; + + grabbedClip.Draw(isValid); + } + + if (isValid) + { + EditMode.DrawMoveGUI(m_State, movingItems); + } + else + { + TimelineCursors.ClearCursor(); + } + } + } + + public void OnAttractedEdge(IAttractable attractable, ManipulateEdges manipulateEdges, AttractedEdge edge, double time) + { + double offset; + + if (edge == AttractedEdge.Right) + { + var duration = end - start; + var startTime = time - duration; + startTime = EditMode.AdjustStartTime(m_State, m_RightMostMovingItems, startTime); + + offset = startTime + duration - end; + } + else + { + if (edge == AttractedEdge.Left) + time = EditMode.AdjustStartTime(m_State, m_LeftMostMovingItems, time); + + offset = time - start; + } + + if (start + offset < 0.0) + offset = -start; + + if (!offset.Equals(0.0)) + { + foreach (var grabbedClips in movingItems) + grabbedClips.start += offset; + + EditMode.UpdateMove(); + + RefreshPreviewItems(); + } + } + + public void RefreshPreviewItems() + { + foreach (var movingItemsGroup in movingItems) + { + // Check validity + var valid = ValidateItemDrag(movingItemsGroup); + + foreach (var item in movingItemsGroup.items) + { + if (item.gui != null) + item.gui.isInvalid = !valid; + } + + movingItemsGroup.canDrop = valid; + } + } + + static bool ValidateItemDrag(ItemsPerTrack itemsGroup) + { + //TODO-marker: this is to prevent the drag operation from being canceled when moving only markers + if (itemsGroup.clips.Any()) + { + if (itemsGroup.targetTrack == null) + return false; + + if (itemsGroup.targetTrack.lockedInHierarchy) + return false; + + if (itemsGroup.items.Any(i => !i.IsCompatibleWithTrack(itemsGroup.targetTrack))) + return false; + + return EditMode.ValidateDrag(itemsGroup); + } + + return true; + } + + public void OnTrackDetach() + { + EditMode.OnTrackDetach(movingItems); + } + } +} |
