internal void ItemDoubleClickedCallback(int id) { var gui = m_TreeView.FindItem(id); var trackGUI = gui as TimelineTrackGUI; if (trackGUI != null) { if (trackGUI.track == null || trackGUI.track.lockedInHierarchy) { return; } var selection = SelectionManager.SelectedItems().ToList(); var items = ItemsUtils.GetItems(trackGUI.track).ToList(); var addToSelection = !selection.SequenceEqual(items); foreach (var i in items) { if (addToSelection) { SelectionManager.Add(i); } else { SelectionManager.Remove(i); } } return; } if (gui is TimelineGroupGUI groupGUI) { KeyboardNavigation.ToggleCollapseGroup(new[] { groupGUI.track }); } }
void ItemDoubleClickedCallback(int id) { var trackGUI = m_TreeView.FindItem(id) as TimelineTrackGUI; if (trackGUI == null) { return; } if (trackGUI.track == null || trackGUI.track.lockedInHierarchy) { return; } var selection = SelectionManager.SelectedItems().ToList(); var items = ItemsUtils.GetItems(trackGUI.track).ToList(); var addToSelection = !selection.SequenceEqual(items); foreach (var i in items) { if (addToSelection) { SelectionManager.Add(i); } else { SelectionManager.Remove(i); } } }
//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); } } } } }
static void Remove(TrackAsset track, IEnumerable <ITimelineItem> items) { if (track == null) { return; } //can only ripple items of the same type as those selected var itemTypes = ItemsUtils.GetItemTypes(items); var siblingsToRipple = ItemsUtils.GetItemsExcept(track, items) .Where(i => itemTypes.Contains(i.GetType())) .OrderBy(c => c.start) .ToArray(); var orderedItems = items .OrderBy(c => c.start) .ToArray(); var cumulativeOffset = 0.0; foreach (var item in orderedItems) { var offset = item.end - item.start; var start = item.start - cumulativeOffset; var end = item.end - cumulativeOffset; var nextItem = siblingsToRipple.FirstOrDefault(c => (DiscreteTime)c.start > (DiscreteTime)start && (DiscreteTime)c.start < (DiscreteTime)end); if (nextItem != null) { offset -= end - nextItem.start; } var prevItem = siblingsToRipple.FirstOrDefault(c => (DiscreteTime)c.end > (DiscreteTime)start && (DiscreteTime)c.end < (DiscreteTime)end); if (prevItem != null) { offset -= prevItem.end - start; } if (offset <= 0.0) { continue; } cumulativeOffset += offset; for (int i = siblingsToRipple.Length - 1; i >= 0; --i) { var c = siblingsToRipple[i]; if ((DiscreteTime)c.start < (DiscreteTime)start) { break; } c.start = c.start - offset; } } }
public void InsertItemsAtTime(IEnumerable <ItemsPerTrack> itemsGroups, double requestedTime) { ItemsUtils.SetItemsStartTime(itemsGroups, requestedTime); EditModeMixUtils.PrepareItemsForInsertion(itemsGroups); if (!EditModeMixUtils.CanInsert(itemsGroups)) { var validTime = itemsGroups.Select(c => c.targetTrack).Max(parent => parent.end); ItemsUtils.SetItemsStartTime(itemsGroups, validTime); } }
protected override bool MouseDown(Event evt, WindowState state) { var handle = PickerUtils.PickedLayerableOfType <TimelineClipHandle>(); if (handle == null) { return(false); } if (handle.clipGUI.clip.parentTrack != null && handle.clipGUI.clip.parentTrack.lockedInHierarchy) { return(false); } if (ItemSelection.CanClearSelection(evt)) { SelectionManager.Clear(); } if (!SelectionManager.Contains(handle.clipGUI.clip)) { SelectionManager.Add(handle.clipGUI.clip); } m_TrimClipHandler = handle; m_IsCaptured = true; state.AddCaptured(this); m_UndoSaved = false; var clip = m_TrimClipHandler.clipGUI.clip; m_OriginalDuration = clip.duration; m_OriginalTimeScale = clip.timeScale; m_OriginalEaseInDuration = clip.easeInDuration; m_OriginalEaseOutDuration = clip.easeOutDuration; RefreshOverlayStrings(m_TrimClipHandler, state); // in ripple trim, the right edge moves and needs to snap var edges = ManipulateEdges.Right; if (EditMode.editType != EditMode.EditType.Ripple && m_TrimClipHandler.trimDirection == TrimEdge.Start) { edges = ManipulateEdges.Left; } m_SnapEngine = new SnapEngine(m_TrimClipHandler.clipGUI, new TrimClipAttractionHandler(), edges, state, evt.mousePosition); EditMode.BeginTrim(ItemsUtils.ToItem(clip), m_TrimClipHandler.trimDirection); return(true); }
public override bool Execute(ActionContext actionContext) { var inlineCurveEditor = SelectionManager.GetCurrentInlineEditorCurve(); if (FrameSelectedAction.ShouldHandleInlineCurve(inlineCurveEditor)) { FrameSelectedAction.FrameInlineCurves(inlineCurveEditor, false); return(true); } if (TimelineWindow.instance.state.IsCurrentEditingASequencerTextField()) { return(false); } var visibleTracks = TimelineWindow.instance.treeView.visibleTracks.ToList(); if (TimelineEditor.inspectedAsset != null && TimelineEditor.inspectedAsset.markerTrack != null) { visibleTracks.Add(TimelineEditor.inspectedAsset.markerTrack); } if (visibleTracks.Count == 0) { return(false); } var startTime = float.MaxValue; var endTime = float.MinValue; foreach (var t in visibleTracks) { if (t == null) { continue; } // time range based on track's curves and clips. double trackStart, trackEnd, trackDuration; t.GetSequenceTime(out trackStart, out trackDuration); trackEnd = trackStart + trackDuration; // take track's markers into account double itemsStart, itemsEnd; ItemsUtils.GetItemRange(t, out itemsStart, out itemsEnd); startTime = Mathf.Min(startTime, (float)trackStart, (float)itemsStart); endTime = Mathf.Max(endTime, (float)(trackEnd), (float)itemsEnd); } FrameSelectedAction.FrameRange(startTime, endTime); return(true); }
void DrawStartTimeField() { var inputEvent = InputEvent.None; var newStart = TimelineInspectorUtility.TimeFieldUsingTimeReference(Styles.StartName, m_SelectionInfo.multipleClipStart, false, m_SelectionInfo.hasMultipleStartValues, currentFrameRate, 0.0, TimelineClip.kMaxTimeValue, ref inputEvent); if (inputEvent.InputHasBegun() && m_SelectionInfo.hasMultipleStartValues) { var items = ItemsUtils.ToItems(m_SelectionInfo.clips); EditMode.inputHandler.SetValueForEdge(items, AttractedEdge.Left, newStart); //if the field has multiple values, set the same start on all selected clips m_SelectionInfo.Update(); //clips could have moved relative to each other, recalculate } EditMode.inputHandler.ProcessMove(inputEvent, newStart); }
public static void TrimClipWithEditMode(TimelineClip clip, TrimEdge edge, double time) { var clipItem = ItemsUtils.ToItem(clip); EditMode.BeginTrim(clipItem, edge); if (edge == TrimEdge.Start) { EditMode.TrimStart(clipItem, time); } else { EditMode.TrimEnd(clipItem, time, false); } EditMode.FinishTrim(); }
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); } } } }
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 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); }
public static void Insert(IEnumerable <ItemsPerTrack> itemsGroups) { var start = double.MaxValue; var end = double.MinValue; foreach (var itemsGroup in itemsGroups) { start = Math.Min(start, itemsGroup.items.Min(c => c.start)); end = Math.Max(end, itemsGroup.items.Max(c => c.end)); } var offset = 0.0; var discreteStart = (DiscreteTime)start; var discreteEnd = (DiscreteTime)end; var itemTypes = ItemsUtils.GetItemTypes(itemsGroups); var siblingsToRipple = new List <ITimelineItem>(); foreach (var itemsGroup in itemsGroups) { //can only ripple items of the same type as those selected siblingsToRipple.AddRange(ItemsUtils.GetItemsExcept(itemsGroup.targetTrack, itemsGroup.items).Where(i => itemTypes.Contains(i.GetType()))); foreach (var item in siblingsToRipple) { var discreteItemStart = (DiscreteTime)item.start; var discreteItemEnd = (DiscreteTime)item.end; if ((discreteItemStart < discreteStart && discreteItemEnd > discreteStart) || (discreteItemStart >= discreteStart && discreteItemStart < discreteEnd)) { offset = Math.Max(offset, end - item.start); } } } if (offset > 0.0) { foreach (var sibling in siblingsToRipple) { if ((DiscreteTime)sibling.end > (DiscreteTime)start) { sibling.start += offset; } } } }
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 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 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 OnAttractedEdge(IAttractable attractable, ManipulateEdges manipulateEdges, AttractedEdge edge, double time) { var clipGUI = attractable as TimelineClipGUI; if (clipGUI == null) { return; } var clipItem = ItemsUtils.ToItem(clipGUI.clip); if (manipulateEdges == ManipulateEdges.Right) { bool affectTimeScale = Event.current.modifiers == EventModifiers.Shift; // TODO Do not use Event.current from here. EditMode.TrimEnd(clipItem, time, affectTimeScale); } else if (manipulateEdges == ManipulateEdges.Left) { EditMode.TrimStart(clipItem, time); } }
public void BeginMove(IEnumerable <ItemsPerTrack> itemsGroups) { m_NextItems.Clear(); m_PreviousItem.Clear(); var itemTypes = ItemsUtils.GetItemTypes(itemsGroups); foreach (var itemsGroup in itemsGroups) { //can only ripple items of the same type as those selected var siblingsToRipple = itemsGroup.targetTrack.GetItemsExcept(itemsGroup.items).Where(i => itemTypes.Contains(i.GetType())); var start = itemsGroup.items.Min(i => i.start); //TODO-marker: have a method to get the start of the group (already cached) m_NextItems.Add(itemsGroup.targetTrack, siblingsToRipple.Where(i => i.start > start).ToList()); var prevItem = siblingsToRipple.Where(i => i.duration > 0.0).OrderBy(i => i.start).LastOrDefault(i => i.start <= start); m_PreviousItem.Add(itemsGroup.targetTrack, new PrevItemInfo { item = prevItem, blending = prevItem != null && prevItem.end > start }); } m_PreviousEnd = itemsGroups.Max(m => m.items.Max(c => c.end)); }
public void OnAttractedEdge(IAttractable attractable, ManipulateEdges manipulateEdges, AttractedEdge edge, double time) { var clipGUI = attractable as TimelineClipGUI; if (clipGUI == null) { return; } var clipItem = ItemsUtils.ToItem(clipGUI.clip); if (manipulateEdges == ManipulateEdges.Right) { bool affectTimeScale = IsAffectingTimeScale(clipGUI.clip); EditMode.TrimEnd(clipItem, time, affectTimeScale); } else if (manipulateEdges == ManipulateEdges.Left) { bool affectTimeScale = IsAffectingTimeScale(clipGUI.clip); EditMode.TrimStart(clipItem, time, affectTimeScale); } }
public void OnBeforeTrim(ITrimmable item, TrimEdge trimDirection) { m_OriginalClipStart = item.start; m_OriginalClipEnd = item.end; m_TrimStartShift = 0.0; var sortedClips = ItemsUtils.GetItemsExcept(item.parentTrack, new[] { item }) .OfType <ITrimmable>() .OrderBy(c => c.start); var clipStart = (DiscreteTime)item.start; var clipEnd = (DiscreteTime)item.end; m_NextItems = sortedClips.Where(c => (DiscreteTime)c.start >= clipStart && (DiscreteTime)c.end >= clipEnd).ToArray(); var overlapped = sortedClips.LastOrDefault(c => (DiscreteTime)c.start == clipStart && (DiscreteTime)c.end == clipEnd); if (overlapped != null) { m_BlendDuration = overlapped.end - overlapped.start; } else { m_BlendDuration = 0.0; var prevClip = sortedClips.LastOrDefault(c => (DiscreteTime)c.start <= clipStart && (DiscreteTime)c.end <= clipEnd); if (prevClip != null) { m_BlendDuration += Math.Max(prevClip.end - item.start, 0.0); } var nextClip = sortedClips.FirstOrDefault(c => (DiscreteTime)c.start >= clipStart && (DiscreteTime)c.end >= clipEnd); if (nextClip != null) { m_BlendDuration += Math.Max(item.end - nextClip.start, 0.0); } } }
public static void CreateMarkersFromObjects(Type assetType, TrackAsset targetTrack, double candidateTime, IEnumerable <Object> objects) { var mList = new List <ITimelineItem>(); foreach (var obj in objects) { if (ObjectReferenceField.FindObjectReferences(assetType).Any(f => f.IsAssignable(obj))) { var marker = CreateMarkerOnTrack(assetType, obj, targetTrack, candidateTime); mList.Add(marker.ToItem()); } } var state = TimelineWindow.instance.state; for (var i = 1; i < mList.Count; ++i) { var delta = ItemsUtils.TimeGapBetweenItems(mList[i - 1], mList[i], state); mList[i].start += delta; } FinalizeInsertItemsUsingCurrentEditMode(state, new[] { new ItemsPerTrack(targetTrack, mList) }, candidateTime); state.Refresh(); }
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 InsertItemsAtTime(IEnumerable <ItemsPerTrack> itemsGroups, double requestedTime) { ItemsUtils.SetItemsStartTime(itemsGroups, requestedTime); EditModeReplaceUtils.Insert(itemsGroups); }
public static void RangeSelectItems(ITimelineItem lastItemToSelect) { var selectSorted = SelectionManager.SelectedItems().ToList(); var firstSelect = selectSorted.FirstOrDefault(); if (firstSelect == null) { SelectionManager.Add(lastItemToSelect); return; } var allItems = TimelineWindow.instance.allTracks.OfType <TimelineTrackGUI>().SelectMany(ttGui => ItemsUtils.GetItems(ttGui.track)).ToList(); TimelineHelpers.RangeSelect(allItems, selectSorted, lastItemToSelect, SelectionManager.Add, SelectionManager.Remove); }
public override bool Execute(ActionContext context) { return(Execute(context, (item1, item2) => ItemsUtils.TimeGapBetweenItems(item1, item2))); }
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; }
public override bool Execute(WindowState state) { return(Execute(state, (item1, item2) => ItemsUtils.TimeGapBetweenItems(item1, item2, state))); }