public void BeginMove(IEnumerable <ItemsPerTrack> itemsGroups) { foreach (var itemsGroup in itemsGroups) { EditModeUtils.SetParentTrack(itemsGroup.items, null); } }
public void Drop() { if (IsValidDrop()) { foreach (var grabbedItems in movingItems) { var track = grabbedItems.targetTrack; UndoExtensions.RegisterTrack(track, L10n.Tr("Move Items")); if (EditModeUtils.IsInfiniteTrack(track) && grabbedItems.clips.Any()) { ((AnimationTrack)track).ConvertToClipMode(); } } EditMode.FinishMove(); Done(); } else { Cancel(); } EditMode.ClearEditMode(); }
static void FinalizeInsertItemsUsingCurrentEditMode(WindowState state, IList <ItemsPerTrack> itemsGroups, double candidateTime) { EditMode.FinalizeInsertItemsAtTime(itemsGroups, candidateTime); SelectionManager.Clear(); foreach (var itemsGroup in itemsGroups) { var track = itemsGroup.targetTrack; var items = itemsGroup.items; EditModeUtils.SetParentTrack(items, track); track.SortClips(); TrackExtensions.ComputeBlendsFromOverlaps(track.clips); track.CalculateExtrapolationTimes(); foreach (var item in items) { if (item.gui != null) { item.gui.Select(); } } } var allItems = itemsGroups.SelectMany(x => x.items).ToList(); foreach (var item in allItems) { SelectionManager.Add(item); } FrameItems(state, allItems); }
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(); }
//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); } } } } }
void StartDetachMode(IEnumerable <ItemsPerTrack> itemsGroups) { m_Detached = true; foreach (var itemsGroup in itemsGroups) { EditModeUtils.SetParentTrack(itemsGroup.items, null); } }
public static void SetItemsStartTime(IEnumerable <ItemsPerTrack> newItems, double time) { var startTimes = newItems.Select(d => d.items.Min(x => x.start)).ToList(); var min = startTimes.Min(); startTimes = startTimes.Select(x => x - min + time).ToList(); for (int i = 0; i < newItems.Count(); ++i) { EditModeUtils.SetStart(newItems.ElementAt(i).items, startTimes[i]); } }
static void Insert(TrackAsset track, IEnumerable <ITimelineItem> items) { if (track == null) { return; } var orderedItems = ItemsUtils.GetItemsExcept(track, items) .OfType <ITrimmable>() .OrderBy(i => i.start).ToArray(); foreach (var item in items.OfType <ITrimmable>()) { var from = item.start; var to = item.end; var overlappedItems = orderedItems.Where(i => EditModeUtils.Overlaps(i, from, to)); foreach (var overlappedItem in overlappedItems) { if (EditModeUtils.IsItemWithinRange(overlappedItem, from, to)) { overlappedItem.Delete(); } else { if (overlappedItem.start >= from) { overlappedItem.TrimStart(to); } else { overlappedItem.TrimEnd(from); } } } var includingItems = orderedItems.Where(c => c.start <from && c.end> to); foreach (var includingItem in includingItems) { var newItem = includingItem.CloneTo(track, includingItem.start) as ITrimmable; includingItem.TrimStart(to); if (newItem != null) { newItem.SetEnd(from, false); } } } }
public void DrawGUI(WindowState state, Rect bounds, Color color, TrimEdge edge) { if (EditModeUtils.HasBlends(m_Item, edge)) { EditModeGUIUtils.DrawBoundsEdge(bounds, color, edge); var cursorType = (edge == TrimEdge.End) ? TimelineCursors.CursorType.MixRight : TimelineCursors.CursorType.MixLeft; TimelineCursors.SetCursor(cursorType); } else { TimelineCursors.ClearCursor(); } }
internal static void DeleteItems(IEnumerable <ITimelineItem> items) { var tracks = items.GroupBy(c => c.parentTrack); foreach (var track in tracks) { TimelineUndo.PushUndo(track.Key, "Delete Items"); } TimelineAnimationUtilities.UnlinkAnimationWindowFromClips(items.OfType <ClipItem>().Select(i => i.clip)); EditMode.PrepareItemsDelete(ItemsUtils.ToItemsPerTrack(items)); EditModeUtils.Delete(items); SelectionManager.RemoveAllClips(); }
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); }
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 HandleTrackSwitch(IEnumerable <ItemsPerTrack> 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; UndoExtensions.RegisterTrack(track, L10n.Tr("Move Items")); EditModeUtils.SetParentTrack(itemsGroup.items, track); } else { EditModeUtils.SetParentTrack(itemsGroup.items, null); } } }
public void DrawGUI(WindowState state, IEnumerable <MovingItems> 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(); } }
public void HandleTrackSwitch(IEnumerable <ItemsPerTrack> 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 void DrawGUI(WindowState state, Rect bounds, Color color, TrimEdge edge) { bool shouldDraw = m_ItemToBeReplaced != null && (edge == TrimEdge.End && m_Item.end > m_ClipOriginalEdgeValue) || (edge == TrimEdge.Start && m_Item.start < m_ClipOriginalEdgeValue); if (shouldDraw) { var cursorType = TimelineCursors.CursorType.Replace; if (EditModeUtils.HasBlends(m_Item, edge)) { color = DirectorStyles.kMixToolColor; cursorType = (edge == TrimEdge.End) ? TimelineCursors.CursorType.MixRight : TimelineCursors.CursorType.MixLeft; } EditModeGUIUtils.DrawBoundsEdge(bounds, color, edge); TimelineCursors.SetCursor(cursorType); } else { TimelineCursors.ClearCursor(); } }
public void OnBeforeTrim(ITrimmable item, TrimEdge trimDirection) { m_Item = item; var sortedItems = ItemsUtils.GetItemsExcept(item.parentTrack, new[] { item }) .OfType <ITrimmable>() .OrderBy(c => c.start); var itemStart = (DiscreteTime)item.start; var itemEnd = (DiscreteTime)item.end; var overlapped = sortedItems.LastOrDefault(c => (DiscreteTime)c.start == itemStart && (DiscreteTime)c.end == itemEnd); ITrimmable nextItem; ITrimmable prevItem; m_Min = 0.0; m_Max = double.PositiveInfinity; var blendableItem = item as IBlendable; if (blendableItem != null && blendableItem.supportsBlending) { if (trimDirection == TrimEdge.Start) { nextItem = sortedItems.FirstOrDefault(c => (DiscreteTime)c.start >= itemStart && (DiscreteTime)c.end > itemEnd); prevItem = sortedItems.LastOrDefault(c => (DiscreteTime)c.start <= itemStart && (DiscreteTime)c.end < itemEnd); if (prevItem != null) { m_Min = prevItem.start + EditModeUtils.BlendDuration(prevItem, TrimEdge.Start); } if (nextItem != null) { m_Max = nextItem.start; } } else { nextItem = sortedItems.FirstOrDefault(c => c != overlapped && (DiscreteTime)c.start >= itemStart && (DiscreteTime)c.end >= itemEnd); prevItem = sortedItems.LastOrDefault(c => c != overlapped && (DiscreteTime)c.start <= itemStart && (DiscreteTime)c.end <= itemEnd); if (prevItem != null) { m_Min = prevItem.end; } if (nextItem != null) { m_Max = nextItem.end - EditModeUtils.BlendDuration(nextItem, TrimEdge.End); } } } else { nextItem = sortedItems.FirstOrDefault(c => (DiscreteTime)c.start > itemStart); prevItem = sortedItems.LastOrDefault(c => (DiscreteTime)c.start < itemStart); if (prevItem != null) { m_Min = prevItem.end; } if (nextItem != null) { m_Max = nextItem.start; } } }
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 = itemsGroup.items.OrderBy(c => c.start).First(); 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; } } }
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); }
public void OnBeforeTrim(ITrimmable item, TrimEdge trimDirection) { m_Item = item; var sortedClips = ItemsUtils.GetItemsExcept(item.parentTrack, new[] { item }) .OfType <ITrimmable>() .OrderBy(c => c.start); var clipStart = (DiscreteTime)item.start; var clipEnd = (DiscreteTime)item.end; var overlapped = sortedClips.LastOrDefault(c => (DiscreteTime)c.start == clipStart && (DiscreteTime)c.end == clipEnd); ITrimmable nextItem; ITrimmable prevItem; m_Min = 0.0; m_Max = double.PositiveInfinity; if (trimDirection == TrimEdge.Start) { nextItem = sortedClips.FirstOrDefault(c => (DiscreteTime)c.start >= clipStart && (DiscreteTime)c.end > clipEnd); prevItem = sortedClips.LastOrDefault(c => (DiscreteTime)c.start <= clipStart && (DiscreteTime)c.end < clipEnd); if (prevItem != null) { m_Min = prevItem.start + EditModeUtils.BlendDuration(prevItem, TrimEdge.Start) + TimelineClip.kMinDuration; } if (nextItem != null) { m_Max = nextItem.start; } m_ItemToBeReplaced = prevItem; if (m_ItemToBeReplaced != null) { m_ClipOriginalEdgeValue = m_ItemToBeReplaced.end; } } else { nextItem = sortedClips.FirstOrDefault(c => c != overlapped && (DiscreteTime)c.start >= clipStart && (DiscreteTime)c.end >= clipEnd); prevItem = sortedClips.LastOrDefault(c => c != overlapped && (DiscreteTime)c.start <= clipStart && (DiscreteTime)c.end <= clipEnd); if (prevItem != null) { m_Min = prevItem.end; } if (nextItem != null) { m_Max = nextItem.end - EditModeUtils.BlendDuration(nextItem, TrimEdge.End) - TimelineClip.kMinDuration; } m_ItemToBeReplaced = nextItem; if (m_ItemToBeReplaced != null) { m_ClipOriginalEdgeValue = m_ItemToBeReplaced.start; } } m_TrimReplace = false; }