diff options
Diffstat (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs')
| -rw-r--r-- | Library/PackageCache/com.unity.timeline@1.2.13/Editor/Manipulators/Move/MoveItemModeRipple.cs | 271 |
1 files changed, 271 insertions, 0 deletions
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<Object, List<ITimelineItem>> m_NextItems = new Dictionary<Object, List<ITimelineItem>>(); + readonly Dictionary<Object, PrevItemInfo> m_PreviousItem = new Dictionary<Object, PrevItemInfo>(); + double m_PreviousEnd; + + bool m_TrackLocked; + bool m_Detached; + + public void OnTrackDetach(IEnumerable<ItemsPerTrack> 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<ItemsPerTrack> 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<ItemsPerTrack> itemsGroups) + { + m_Detached = true; + + foreach (var itemsGroup in itemsGroups) + EditModeUtils.SetParentTrack(itemsGroup.items, null); + } + + public void OnModeClutchEnter(IEnumerable<ItemsPerTrack> itemsGroups) + { + StartDetachMode(itemsGroups); + m_TrackLocked = false; + } + + public void OnModeClutchExit(IEnumerable<ItemsPerTrack> itemsGroups) + { + m_Detached = false; + m_TrackLocked = false; + } + + public void BeginMove(IEnumerable<ItemsPerTrack> 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<ItemsPerTrack> 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<ITimelineItem> orderedSelection, List<ITimelineItem> orderedSiblings, IEnumerable<Type> 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<ItemsPerTrack> itemsGroups) + { + if (m_Detached) + EditModeRippleUtils.Insert(itemsGroups); + + m_Detached = false; + m_TrackLocked = false; + } + + public void DrawGUI(WindowState state, IEnumerable<MovingItems> 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); + } + } +} |
