No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EditModeMixUtils.cs 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEngine.Timeline;
  4. namespace UnityEditor.Timeline
  5. {
  6. static class EditModeMixUtils
  7. {
  8. static readonly List<PlacementValidity> k_UnrecoverablePlacements = new List<PlacementValidity>
  9. {
  10. PlacementValidity.InvalidIsWithin,
  11. PlacementValidity.InvalidStartsInBlend,
  12. PlacementValidity.InvalidContainsBlend,
  13. PlacementValidity.InvalidOverlapWithNonBlendableClip
  14. };
  15. public static bool CanInsert(IEnumerable<ItemsPerTrack> itemsGroups)
  16. {
  17. foreach (var itemsGroup in itemsGroups)
  18. {
  19. List<ITimelineItem> siblings = ItemsUtils.GetItemsExcept(itemsGroup.targetTrack, itemsGroup.items).ToList();
  20. foreach (var item in itemsGroup.items)
  21. {
  22. var placementValidity = GetPlacementValidity(item, siblings);
  23. if (k_UnrecoverablePlacements.Contains(placementValidity))
  24. {
  25. return false;
  26. }
  27. }
  28. }
  29. return true;
  30. }
  31. //Corrects clips durations to fit at insertion point, if needed
  32. public static void PrepareItemsForInsertion(IEnumerable<ItemsPerTrack> itemsGroups)
  33. {
  34. foreach (var itemsGroup in itemsGroups)
  35. {
  36. var siblings = ItemsUtils.GetItemsExcept(itemsGroup.targetTrack, itemsGroup.items);
  37. foreach (var item in itemsGroup.items.OfType<ITrimmable>())
  38. {
  39. var eatenItems = siblings.Where(c => EditModeUtils.IsItemWithinRange(c, item.start, item.end)).ToList();
  40. var intersectedItem = EditModeUtils.GetFirstIntersectedItem(siblings, item.end);
  41. if (intersectedItem != null)
  42. eatenItems.Add(intersectedItem);
  43. var blendableItems = eatenItems.OfType<IBlendable>();
  44. if (blendableItems.Any())
  45. {
  46. var minTime = blendableItems.Min(c => c.end - c.rightBlendDuration);
  47. if (item.end > minTime)
  48. item.SetEnd(minTime, false);
  49. }
  50. }
  51. }
  52. }
  53. public static PlacementValidity GetPlacementValidity(ITimelineItem item, IEnumerable<ITimelineItem> otherItems)
  54. {
  55. if (item.duration <= 0.0)
  56. return PlacementValidity.Valid; //items without any duration can always be placed
  57. var sortedItems = otherItems.Where(i => i.duration > 0.0).OrderBy(c => c.start);
  58. var candidates = new List<ITimelineItem>();
  59. foreach (var sortedItem in sortedItems)
  60. {
  61. if ((DiscreteTime)sortedItem.start >= (DiscreteTime)item.end)
  62. {
  63. // No need to process further
  64. break;
  65. }
  66. if ((DiscreteTime)sortedItem.end <= (DiscreteTime)item.start)
  67. {
  68. // Skip
  69. continue;
  70. }
  71. candidates.Add(sortedItem);
  72. }
  73. var discreteStart = (DiscreteTime)item.start;
  74. var discreteEnd = (DiscreteTime)item.end;
  75. // Note: Order of tests matters
  76. for (int i = 0, n = candidates.Count; i < n; i++)
  77. {
  78. var candidate = candidates[i];
  79. var blendItem = item as IBlendable;
  80. if (blendItem != null && blendItem.supportsBlending)
  81. {
  82. if (EditModeUtils.Contains(candidate.start, candidate.end, item))
  83. return PlacementValidity.InvalidIsWithin;
  84. if (i < n - 1)
  85. {
  86. var nextCandidate = candidates[i + 1];
  87. var discreteNextCandidateStart = (DiscreteTime)nextCandidate.start;
  88. var discreteCandidateEnd = (DiscreteTime)candidate.end;
  89. if (discreteCandidateEnd > discreteNextCandidateStart)
  90. {
  91. if (discreteStart >= discreteNextCandidateStart)
  92. {
  93. // Note: In case the placement is fully within a blend,
  94. // InvalidStartsInBlend MUST have priority
  95. return PlacementValidity.InvalidStartsInBlend;
  96. }
  97. if (discreteEnd > discreteNextCandidateStart && discreteEnd <= discreteCandidateEnd)
  98. return PlacementValidity.InvalidEndsInBlend;
  99. if (discreteStart < discreteNextCandidateStart && discreteEnd > discreteCandidateEnd)
  100. return PlacementValidity.InvalidContainsBlend;
  101. }
  102. }
  103. if (EditModeUtils.Contains(item.start, item.end, candidate))
  104. return PlacementValidity.InvalidContains;
  105. }
  106. else
  107. {
  108. if (EditModeUtils.Overlaps(item, candidate.start, candidate.end)
  109. || EditModeUtils.Overlaps(candidate, item.start, item.end))
  110. return PlacementValidity.InvalidOverlapWithNonBlendableClip;
  111. }
  112. }
  113. return PlacementValidity.Valid;
  114. }
  115. }
  116. }