Maze / Library /PackageCache /com.unity.timeline@1.6.5 /Editor /Manipulators /Utils /EditModeMixUtils.cs
| using System.Collections.Generic; | |
| using System.Linq; | |
| using UnityEngine.Timeline; | |
| namespace UnityEditor.Timeline | |
| { | |
| static class EditModeMixUtils | |
| { | |
| static readonly List<PlacementValidity> k_UnrecoverablePlacements = new List<PlacementValidity> | |
| { | |
| PlacementValidity.InvalidIsWithin, | |
| PlacementValidity.InvalidStartsInBlend, | |
| PlacementValidity.InvalidContainsBlend, | |
| PlacementValidity.InvalidOverlapWithNonBlendableClip | |
| }; | |
| public static bool CanInsert(IEnumerable<ItemsPerTrack> itemsGroups) | |
| { | |
| foreach (var itemsGroup in itemsGroups) | |
| { | |
| List<ITimelineItem> siblings = ItemsUtils.GetItemsExcept(itemsGroup.targetTrack, itemsGroup.items).ToList(); | |
| foreach (var item in itemsGroup.items) | |
| { | |
| var placementValidity = GetPlacementValidity(item, siblings); | |
| if (k_UnrecoverablePlacements.Contains(placementValidity)) | |
| { | |
| return false; | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| //Corrects clips durations to fit at insertion point, if needed | |
| public static void PrepareItemsForInsertion(IEnumerable<ItemsPerTrack> itemsGroups) | |
| { | |
| foreach (var itemsGroup in itemsGroups) | |
| { | |
| var siblings = ItemsUtils.GetItemsExcept(itemsGroup.targetTrack, itemsGroup.items); | |
| foreach (var item in itemsGroup.items.OfType<ITrimmable>()) | |
| { | |
| var eatenItems = siblings.Where(c => EditModeUtils.IsItemWithinRange(c, item.start, item.end)).ToList(); | |
| var intersectedItem = EditModeUtils.GetFirstIntersectedItem(siblings, item.end); | |
| if (intersectedItem != null) | |
| eatenItems.Add(intersectedItem); | |
| var blendableItems = eatenItems.OfType<IBlendable>(); | |
| if (blendableItems.Any()) | |
| { | |
| var minTime = blendableItems.Min(c => c.end - c.rightBlendDuration); | |
| if (item.end > minTime) | |
| item.SetEnd(minTime, false); | |
| } | |
| } | |
| } | |
| } | |
| public static PlacementValidity GetPlacementValidity(ITimelineItem item, IEnumerable<ITimelineItem> otherItems) | |
| { | |
| if (item.duration <= 0.0) | |
| return PlacementValidity.Valid; //items without any duration can always be placed | |
| var sortedItems = otherItems.Where(i => i.duration > 0.0).OrderBy(c => c.start); | |
| var candidates = new List<ITimelineItem>(); | |
| foreach (var sortedItem in sortedItems) | |
| { | |
| if ((DiscreteTime)sortedItem.start >= (DiscreteTime)item.end) | |
| { | |
| // No need to process further | |
| break; | |
| } | |
| if ((DiscreteTime)sortedItem.end <= (DiscreteTime)item.start) | |
| { | |
| // Skip | |
| continue; | |
| } | |
| candidates.Add(sortedItem); | |
| } | |
| var discreteStart = (DiscreteTime)item.start; | |
| var discreteEnd = (DiscreteTime)item.end; | |
| // Note: Order of tests matters | |
| for (int i = 0, n = candidates.Count; i < n; i++) | |
| { | |
| var candidate = candidates[i]; | |
| var blendItem = item as IBlendable; | |
| if (blendItem != null && blendItem.supportsBlending) | |
| { | |
| if (EditModeUtils.Contains(candidate.start, candidate.end, item)) | |
| return PlacementValidity.InvalidIsWithin; | |
| if (i < n - 1) | |
| { | |
| var nextCandidate = candidates[i + 1]; | |
| var discreteNextCandidateStart = (DiscreteTime)nextCandidate.start; | |
| var discreteCandidateEnd = (DiscreteTime)candidate.end; | |
| if (discreteCandidateEnd > discreteNextCandidateStart) | |
| { | |
| if (discreteStart >= discreteNextCandidateStart) | |
| { | |
| // Note: In case the placement is fully within a blend, | |
| // InvalidStartsInBlend MUST have priority | |
| return PlacementValidity.InvalidStartsInBlend; | |
| } | |
| if (discreteEnd > discreteNextCandidateStart && discreteEnd <= discreteCandidateEnd) | |
| return PlacementValidity.InvalidEndsInBlend; | |
| if (discreteStart < discreteNextCandidateStart && discreteEnd > discreteCandidateEnd) | |
| return PlacementValidity.InvalidContainsBlend; | |
| } | |
| } | |
| if (EditModeUtils.Contains(item.start, item.end, candidate)) | |
| return PlacementValidity.InvalidContains; | |
| } | |
| else | |
| { | |
| if (EditModeUtils.Overlaps(item, candidate.start, candidate.end) | |
| || EditModeUtils.Overlaps(candidate, item.start, item.end)) | |
| return PlacementValidity.InvalidOverlapWithNonBlendableClip; | |
| } | |
| } | |
| return PlacementValidity.Valid; | |
| } | |
| } | |
| } | |