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();
        }
예제 #3
0
        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();
        }
예제 #5
0
        //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);
            }
        }
예제 #7
0
        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();
            }
        }
예제 #10
0
        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);
        }
예제 #12
0
        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));
        }
예제 #13
0
        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;
                }
            }
        }
예제 #19
0
        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;
        }