From c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78 Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Sun, 19 Apr 2020 17:19:32 -0400 Subject: Inital commit --- .../Editor/Manipulators/Move/IMoveItemMode.cs | 28 ++ .../Editor/Manipulators/Move/IMoveItemMode.cs.meta | 11 + .../Editor/Manipulators/Move/MoveItemHandler.cs | 312 +++++++++++++++++++++ .../Manipulators/Move/MoveItemHandler.cs.meta | 11 + .../Editor/Manipulators/Move/MoveItemModeMix.cs | 138 +++++++++ .../Manipulators/Move/MoveItemModeMix.cs.meta | 11 + .../Manipulators/Move/MoveItemModeReplace.cs | 99 +++++++ .../Manipulators/Move/MoveItemModeReplace.cs.meta | 11 + .../Editor/Manipulators/Move/MoveItemModeRipple.cs | 271 ++++++++++++++++++ .../Manipulators/Move/MoveItemModeRipple.cs.meta | 11 + .../Editor/Manipulators/Move/MovingItems.cs | 137 +++++++++ .../Editor/Manipulators/Move/MovingItems.cs.meta | 11 + 12 files changed, 1051 insertions(+) create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/IMoveItemMode.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/IMoveItemMode.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeMix.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeMix.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeReplace.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeReplace.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MovingItems.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MovingItems.cs.meta (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move') diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/IMoveItemMode.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/IMoveItemMode.cs new file mode 100644 index 0000000..ac459ca --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/IMoveItemMode.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UnityEditor.Timeline +{ + interface IMoveItemMode + { + void OnTrackDetach(IEnumerable itemsGroups); + void HandleTrackSwitch(IEnumerable itemsGroups); + bool AllowTrackSwitch(); + + double AdjustStartTime(WindowState state, ItemsPerTrack itemsGroup, double time); + + void OnModeClutchEnter(IEnumerable itemsGroups); + void OnModeClutchExit(IEnumerable itemsGroups); + + void BeginMove(IEnumerable itemsGroups); + void UpdateMove(IEnumerable itemsGroups); + void FinishMove(IEnumerable itemsGroups); + + bool ValidateMove(ItemsPerTrack itemsGroup); + } + + interface IMoveItemDrawer + { + void DrawGUI(WindowState state, IEnumerable movingItems, Color color); + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/IMoveItemMode.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/IMoveItemMode.cs.meta new file mode 100644 index 0000000..619723e --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/IMoveItemMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3ff3d24ea34f9f74cb138e435f5f491e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: 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 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 items, TrackAsset referenceTrack) + { + Grab(items, referenceTrack, Vector2.zero); + } + + public void Grab(IEnumerable 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()) + 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(); + 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); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs.meta new file mode 100644 index 0000000..43dce6a --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6bd368ab00d75c459e2582e017191e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeMix.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeMix.cs new file mode 100644 index 0000000..d4df368 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeMix.cs @@ -0,0 +1,138 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + class MoveItemModeMix : IMoveItemMode, IMoveItemDrawer + { + public void OnTrackDetach(IEnumerable itemsGroups) + { + // Nothing + } + + public void HandleTrackSwitch(IEnumerable itemsGroups) + { + foreach (var itemsGroup in itemsGroups) + { + var targetTrack = itemsGroup.targetTrack; + if (targetTrack != null && itemsGroup.items.Any()) + { + var compatible = itemsGroup.items.First().IsCompatibleWithTrack(targetTrack) && + !EditModeUtils.IsInfiniteTrack(targetTrack); + var track = compatible ? targetTrack : null; + + if (track != null) + TimelineUndo.PushUndo(track, "Move Items"); + + EditModeUtils.SetParentTrack(itemsGroup.items, track); + } + else + { + EditModeUtils.SetParentTrack(itemsGroup.items, null); + } + } + } + + public bool AllowTrackSwitch() + { + return true; + } + + public double AdjustStartTime(WindowState state, ItemsPerTrack itemsGroup, double time) + { + return time; + } + + public void OnModeClutchEnter(IEnumerable itemsGroups) + { + // Nothing + } + + public void OnModeClutchExit(IEnumerable itemsGroups) + { + // Nothing + } + + public void BeginMove(IEnumerable itemsGroups) + { + // Nothing + } + + public void UpdateMove(IEnumerable itemsGroups) + { + // Nothing + } + + public void FinishMove(IEnumerable itemsGroups) + { + // Nothing + } + + public bool ValidateMove(ItemsPerTrack itemsGroup) + { + var track = itemsGroup.targetTrack; + var items = itemsGroup.items; + + if (EditModeUtils.IsInfiniteTrack(track)) + { + double startTime; + double stopTime; + EditModeUtils.GetInfiniteClipBoundaries(track, out startTime, out stopTime); + + return items.All(item => + !EditModeUtils.IsItemWithinRange(item, startTime, stopTime) && + !EditModeUtils.IsRangeWithinItem(startTime, stopTime, item)); + } + + var siblings = ItemsUtils.GetItemsExcept(itemsGroup.targetTrack, items); + return items.All(item => EditModeMixUtils.GetPlacementValidity(item, siblings) == PlacementValidity.Valid); + } + + public void DrawGUI(WindowState state, IEnumerable movingItems, Color color) + { + var selectionHasAnyBlendIn = false; + var selectionHasAnyBlendOut = false; + + foreach (var grabbedItems in movingItems) + { + var bounds = grabbedItems.onTrackItemsBounds; + + var counter = 0; + foreach (var item in grabbedItems.items.OfType()) + { + if (item.hasLeftBlend) + { + EditModeGUIUtils.DrawBoundsEdge(bounds[counter], color, TrimEdge.Start); + selectionHasAnyBlendIn = true; + } + + if (item.hasRightBlend) + { + EditModeGUIUtils.DrawBoundsEdge(bounds[counter], color, TrimEdge.End); + selectionHasAnyBlendOut = true; + } + counter++; + } + } + + if (selectionHasAnyBlendIn && selectionHasAnyBlendOut) + { + TimelineCursors.SetCursor(TimelineCursors.CursorType.MixBoth); + } + else if (selectionHasAnyBlendIn) + { + TimelineCursors.SetCursor(TimelineCursors.CursorType.MixLeft); + } + else if (selectionHasAnyBlendOut) + { + TimelineCursors.SetCursor(TimelineCursors.CursorType.MixRight); + } + else + { + TimelineCursors.ClearCursor(); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeMix.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeMix.cs.meta new file mode 100644 index 0000000..966ebfa --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeMix.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2a8aecb05814e644abbb070fbd91156 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeReplace.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeReplace.cs new file mode 100644 index 0000000..4d55820 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeReplace.cs @@ -0,0 +1,99 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UnityEditor.Timeline +{ + class MoveItemModeReplace : IMoveItemMode, IMoveItemDrawer + { + public void OnTrackDetach(IEnumerable itemsGroups) + { + // Nothing + } + + public void HandleTrackSwitch(IEnumerable itemsGroups) + { + // Nothing + } + + public bool AllowTrackSwitch() + { + return true; + } + + public double AdjustStartTime(WindowState state, ItemsPerTrack itemsGroup, double time) + { + return time; + } + + public void OnModeClutchEnter(IEnumerable itemsGroups) + { + // TODO + } + + public void OnModeClutchExit(IEnumerable itemsGroups) + { + // TODO + } + + public void BeginMove(IEnumerable itemsGroups) + { + foreach (var itemsGroup in itemsGroups) + { + EditModeUtils.SetParentTrack(itemsGroup.items, null); + } + } + + public void UpdateMove(IEnumerable itemsGroups) + { + // Nothing + } + + public void FinishMove(IEnumerable itemsGroups) + { + EditModeReplaceUtils.Insert(itemsGroups); + } + + public bool ValidateMove(ItemsPerTrack itemsGroup) + { + return true; + } + + public void DrawGUI(WindowState state, IEnumerable movingItems, Color color) + { + var operationWillReplace = false; + + foreach (var itemsPerTrack in movingItems) + { + var bounds = itemsPerTrack.onTrackItemsBounds; + + var counter = 0; + foreach (var item in itemsPerTrack.items) + { + if (EditModeUtils.GetFirstIntersectedItem(itemsPerTrack.items, item.start) != null) + { + EditModeGUIUtils.DrawBoundsEdge(bounds[counter], color, TrimEdge.Start); + operationWillReplace = true; + } + + if (EditModeUtils.GetFirstIntersectedItem(itemsPerTrack.items, item.end) != null) + { + EditModeGUIUtils.DrawBoundsEdge(bounds[counter], color, TrimEdge.End); + operationWillReplace = true; + } + + counter++; + // TODO Display swallowed clips? + } + } + + if (operationWillReplace) + { + TimelineCursors.SetCursor(TimelineCursors.CursorType.Replace); + } + else + { + TimelineCursors.ClearCursor(); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeReplace.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeReplace.cs.meta new file mode 100644 index 0000000..abcc2f3 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeReplace.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ea5e2240e8a7d9046a651557deec40b2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs new file mode 100644 index 0000000..aadf5f7 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + class MoveItemModeRipple : IMoveItemMode, IMoveItemDrawer + { + const float k_SnapToEdgeDistance = 30.0f; + + class PrevItemInfo + { + public ITimelineItem item; + public ITimelineItem firstSelectedItem; + public bool blending; + + public PrevItemInfo(ITimelineItem item, ITimelineItem firstSelectedItem) + { + this.item = item; + this.firstSelectedItem = firstSelectedItem; + blending = item != null && item.end > firstSelectedItem.start; + } + } + + readonly Dictionary> m_NextItems = new Dictionary>(); + readonly Dictionary m_PreviousItem = new Dictionary(); + double m_PreviousEnd; + + bool m_TrackLocked; + bool m_Detached; + + public void OnTrackDetach(IEnumerable itemsGroups) + { + if (m_TrackLocked) + return; + + if (m_Detached) + return; + + if (itemsGroups.Any(x => x.markers.Any())) + return; + + // Ripple can either remove or not clips when detaching them from their track. + // Keep it off for now. TODO: add clutch key to toggle this feature? + //EditModeRippleUtils.Remove(manipulatedClipsList); + + StartDetachMode(itemsGroups); + } + + public void HandleTrackSwitch(IEnumerable itemsGroups) + { + // Nothing + } + + public bool AllowTrackSwitch() + { + return !m_TrackLocked; + } + + public double AdjustStartTime(WindowState state, ItemsPerTrack itemsGroup, double time) + { + var track = itemsGroup.targetTrack; + if (track == null) + return time; + + double start; + double end; + + if (EditModeUtils.IsInfiniteTrack(track)) + { + EditModeUtils.GetInfiniteClipBoundaries(track, out start, out end); + } + else + { + var siblings = ItemsUtils.GetItemsExcept(track, itemsGroup.items); + var firstIntersectedItem = EditModeUtils.GetFirstIntersectedItem(siblings, time); + + if (firstIntersectedItem == null) + return time; + + start = firstIntersectedItem.start; + end = firstIntersectedItem.end; + } + + var closestTime = Math.Abs(time - start) < Math.Abs(time - end) ? start : end; + + var pixelTime = state.TimeToPixel(time); + var pixelClosestTime = state.TimeToPixel(closestTime); + + if (Math.Abs(pixelTime - pixelClosestTime) < k_SnapToEdgeDistance) + return closestTime; + + return time; + } + + void StartDetachMode(IEnumerable itemsGroups) + { + m_Detached = true; + + foreach (var itemsGroup in itemsGroups) + EditModeUtils.SetParentTrack(itemsGroup.items, null); + } + + public void OnModeClutchEnter(IEnumerable itemsGroups) + { + StartDetachMode(itemsGroups); + m_TrackLocked = false; + } + + public void OnModeClutchExit(IEnumerable itemsGroups) + { + m_Detached = false; + m_TrackLocked = false; + } + + public void BeginMove(IEnumerable itemsGroups) + { + m_NextItems.Clear(); + m_PreviousItem.Clear(); + var itemTypes = ItemsUtils.GetItemTypes(itemsGroups).ToList(); + + foreach (var itemsGroup in itemsGroups) + { + //can only ripple items of the same type as those selected + var sortedSelectedItems = itemsGroup.items.OrderBy(i => i.start).ToList(); + var siblings = itemsGroup.targetTrack.GetItemsExcept(itemsGroup.items); + var sortedSiblingsToRipple = siblings.Where(i => itemTypes.Contains(i.GetType())).OrderBy(i => i.start).ToList(); + var start = sortedSelectedItems.First().start; + + m_NextItems.Add(itemsGroup.targetTrack, sortedSiblingsToRipple.Where(i => i.start > start).ToList()); + m_PreviousItem.Add(itemsGroup.targetTrack, CalculatePrevItemInfo(sortedSelectedItems, sortedSiblingsToRipple, itemTypes)); + } + + m_PreviousEnd = itemsGroups.Max(m => m.items.Max(c => c.end)); + } + + public void UpdateMove(IEnumerable itemsGroups) + { + if (m_Detached) + return; + + m_TrackLocked = true; + + var overlap = 0.0; + foreach (var itemsGroup in itemsGroups) + { + var track = itemsGroup.targetTrack; + if (track == null) continue; + + var prevItemInfo = m_PreviousItem[track]; + if (prevItemInfo.item != null) + { + var prevItem = prevItemInfo.item; + var firstItem = prevItemInfo.firstSelectedItem; + + if (prevItemInfo.blending) + prevItemInfo.blending = prevItem.end > firstItem.start; + + if (prevItemInfo.blending) + { + var b = EditModeUtils.BlendDuration(firstItem, TrimEdge.End); + overlap = Math.Max(overlap, Math.Max(prevItem.start, prevItem.end - firstItem.end + firstItem.start + b) - firstItem.start); + } + else + { + overlap = Math.Max(overlap, prevItem.end - firstItem.start); + } + } + } + + if (overlap > 0) + { + foreach (var itemsGroup in itemsGroups) + { + foreach (var item in itemsGroup.items) + item.start += overlap; + } + } + + var newEnd = itemsGroups.Max(m => m.items.Max(c => c.end)); + + var offset = newEnd - m_PreviousEnd; + m_PreviousEnd = newEnd; + + foreach (var itemsGroup in itemsGroups) + { + foreach (var item in m_NextItems[itemsGroup.targetTrack]) + item.start += offset; + } + } + + static PrevItemInfo CalculatePrevItemInfo(List orderedSelection, List orderedSiblings, IEnumerable itemTypes) + { + ITimelineItem previousItem = null; + ITimelineItem firstSelectedItem = null; + var gap = double.PositiveInfinity; + + foreach (var type in itemTypes) + { + var firstSelectedItemOfType = orderedSelection.FirstOrDefault(i => i.GetType() == type); + if (firstSelectedItemOfType == null) continue; + + var previousItemOfType = orderedSiblings.LastOrDefault(i => i.GetType() == type && i.start < firstSelectedItemOfType.start); + if (previousItemOfType == null) continue; + + var currentGap = firstSelectedItemOfType.start - previousItemOfType.end; + if (currentGap < gap) + { + gap = currentGap; + firstSelectedItem = firstSelectedItemOfType; + previousItem = previousItemOfType; + } + } + + return new PrevItemInfo(previousItem, firstSelectedItem); + } + + public bool ValidateMove(ItemsPerTrack itemsGroup) + { + return true; + } + + public void FinishMove(IEnumerable itemsGroups) + { + if (m_Detached) + EditModeRippleUtils.Insert(itemsGroups); + + m_Detached = false; + m_TrackLocked = false; + } + + public void DrawGUI(WindowState state, IEnumerable movingItems, Color color) + { + if (m_Detached) + { + var xMin = float.MaxValue; + var xMax = float.MinValue; + + foreach (var grabbedItems in movingItems) + { + xMin = Math.Min(xMin, grabbedItems.onTrackItemsBounds.Min(b => b.xMin)); // TODO Cache this? + xMax = Math.Max(xMax, grabbedItems.onTrackItemsBounds.Max(b => b.xMax)); + } + + foreach (var grabbedItems in movingItems) + { + var bounds = Rect.MinMaxRect(xMin, grabbedItems.onTrackItemsBounds[0].yMin, + xMax, grabbedItems.onTrackItemsBounds[0].yMax); + + EditModeGUIUtils.DrawOverlayRect(bounds, new Color(1.0f, 1.0f, 1.0f, 0.5f)); + + EditModeGUIUtils.DrawBoundsEdge(bounds, color, TrimEdge.Start); + } + } + else + { + foreach (var grabbedItems in movingItems) + { + var bounds = Rect.MinMaxRect(grabbedItems.onTrackItemsBounds.Min(b => b.xMin), grabbedItems.onTrackItemsBounds[0].yMin, + grabbedItems.onTrackItemsBounds.Max(b => b.xMax), grabbedItems.onTrackItemsBounds[0].yMax); + + EditModeGUIUtils.DrawBoundsEdge(bounds, color, TrimEdge.Start); + } + } + + TimelineCursors.SetCursor(TimelineCursors.CursorType.Ripple); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs.meta new file mode 100644 index 0000000..890c3ed --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eebde5009793ce948bf5d4c4435b89b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MovingItems.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MovingItems.cs new file mode 100644 index 0000000..1620269 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MovingItems.cs @@ -0,0 +1,137 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + class MovingItems : ItemsPerTrack + { + TrackAsset m_ReferenceTrack; + readonly bool m_AllowTrackSwitch; + + readonly Rect[] m_ItemsBoundsOnTrack; + readonly Vector2[] m_ItemsMouseOffsets; + + static readonly Rect s_InvisibleBounds = new Rect(float.MaxValue, float.MaxValue, 0.0f, 0.0f); + + public TrackAsset originalTrack { get; } + + public override TrackAsset targetTrack + { + get + { + if (m_AllowTrackSwitch) + return m_ReferenceTrack; + + return originalTrack; + } + } + + public bool canDrop; + + public double start + { + get { return m_ItemsGroup.start; } + set { m_ItemsGroup.start = value; } + } + + public double end + { + get { return m_ItemsGroup.end; } + } + + public Rect[] onTrackItemsBounds + { + get { return m_ItemsBoundsOnTrack; } + } + + public MovingItems(WindowState state, TrackAsset parentTrack, ITimelineItem[] items, TrackAsset referenceTrack, Vector2 mousePosition, bool allowTrackSwitch) + : base(parentTrack, items) + { + originalTrack = parentTrack; + m_ReferenceTrack = referenceTrack; + m_AllowTrackSwitch = allowTrackSwitch; + + m_ItemsBoundsOnTrack = new Rect[items.Length]; + m_ItemsMouseOffsets = new Vector2[items.Length]; + + for (int i = 0; i < items.Length; ++i) + { + var itemGUi = items[i].gui; + + if (itemGUi != null) + { + m_ItemsBoundsOnTrack[i] = itemGUi.rect; + m_ItemsMouseOffsets[i] = mousePosition - m_ItemsBoundsOnTrack[i].position; + } + } + + canDrop = true; + } + + public void SetReferenceTrack(TrackAsset track) + { + m_ReferenceTrack = track; + } + + public bool HasAnyDetachedParents() + { + return m_ItemsGroup.items.Any(x => x.parentTrack == null); + } + + public void RefreshBounds(WindowState state, Vector2 mousePosition) + { + for (int i = 0; i < m_ItemsGroup.items.Length; ++i) + { + var item = m_ItemsGroup.items[i]; + var itemGUI = item.gui; + + if (item.parentTrack != null) + { + m_ItemsBoundsOnTrack[i] = itemGUI.visible ? itemGUI.rect : s_InvisibleBounds; + } + else + { + if (targetTrack != null) + { + var trackGUI = (TimelineTrackGUI)TimelineWindow.instance.allTracks.FirstOrDefault(t => t.track == targetTrack); + if (trackGUI == null) return; + var trackRect = trackGUI.boundingRect; + m_ItemsBoundsOnTrack[i] = itemGUI.RectToTimeline(trackRect, state); + } + else + { + m_ItemsBoundsOnTrack[i].position = mousePosition - m_ItemsMouseOffsets[i]; + } + } + } + } + + public void Draw(bool isValid) + { + for (int i = 0; i < m_ItemsBoundsOnTrack.Length; ++i) + { + var rect = m_ItemsBoundsOnTrack[i]; + DrawItemInternal(m_ItemsGroup.items[i], rect, isValid); + } + } + + static void DrawItemInternal(ITimelineItem item, Rect rect, bool isValid) + { + var clipGUI = item.gui as TimelineClipGUI; + + if (clipGUI != null) + { + if (isValid) + { + clipGUI.DrawGhostClip(rect); + } + else + { + clipGUI.DrawInvalidClip(rect); + } + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MovingItems.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MovingItems.cs.meta new file mode 100644 index 0000000..f3c7fdb --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MovingItems.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 81a142c61a4e14d46bb21b02548ad24d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: -- cgit v1.2.3