private static SortedList <TimingPoint> ConvertToSortedList(List <TimingPoint> presetTimingPoints) { var timingPoints = new SortedList <TimingPoint>(presetTimingPoints.Count, CompareTimingPoints); var absoluteTimingPoints = Convert <TimingPoint, AbsoluteTimingPoint>(presetTimingPoints); if (absoluteTimingPoints.Count == 0) { throw new InvalidOperationException("No absolute timing points were used"); } absoluteTimingPoints[0].SetAsInitialTimingPoint(); var relativeTimingPoints = Convert <TimingPoint, RelativeTimingPoint>(presetTimingPoints); relativeTimingPoints.Sort((a, b) => MeasuredTimePosition.CompareByAbsolutePosition(a.TimePosition, b.TimePosition)); // Add absolute timing points and calculate their relative time positions AbsoluteTimingPoint previousAbsolute = null; foreach (var a in absoluteTimingPoints) { if (previousAbsolute != null) { a.CalculateRelativeTimePosition(previousAbsolute); } timingPoints.Add(previousAbsolute = a); } // Add relative timing points, calculate their absolute time positions and adjust the absolute timing points' relative time positions foreach (var r in relativeTimingPoints) { int index = timingPoints.IndexBefore(r); r.CalculateAbsoluteTimePosition(timingPoints[index]); if (index + 1 < timingPoints.Count) { // The next timing point is certainly an absolute timing point since no relative timing points have been added beyond that one yet var nextAbsolute = timingPoints[index + 1] as AbsoluteTimingPoint; // Calculate the measure adjustment for the first absolute timing point to apply it to all the rest int currentMeasure = nextAbsolute.RelativeTimePosition.Measure; nextAbsolute.CalculateRelativeTimePosition(r); int newMeasure = nextAbsolute.RelativeTimePosition.Measure; int measureAdjustment = newMeasure - currentMeasure; if (measureAdjustment != 0) { for (int i = index + 2; i < timingPoints.Count; i++) { (timingPoints[i] as AbsoluteTimingPoint).AdjustMeasure(measureAdjustment); } } } timingPoints.Add(r); } return(timingPoints); }
/// <summary>Gets all the events of this track list and generates a track list that contains the smallest number of tracks where the events are not overlapping in any track.</summary> /// <param name="timingPoints">The timing points based on which to compact the tracks.</param> public GuidelineEditorPresetTrackList CompactTracks(TimingPointList timingPoints) { var result = new GuidelineEditorPresetTrackList(); var unifiedTracks = UnifyTracks(); foreach (var e in unifiedTracks) { bool found = false; for (int i = 0; i < result.Count && !found; i++) { if (found = MeasuredTimePosition.CompareByAbsolutePosition(result.tracks[i].GetEnd(timingPoints), e.TimePosition) < 0) { result.tracks[i].Add(e); } } if (!found) { result.Add(new GuidelineEditorPresetTrack(e)); } } return(result); }
/// <summary>Compares two <seealso cref="TimingPoint"/>s based on their relative time positions.</summary> /// <param name="left">The left <seealso cref="TimingPoint"/> whose relative time position will be compared.</param> /// <param name="right">The right <seealso cref="TimingPoint"/> whose relative time position will be compared.</param> public static int RelativeComparison(TimingPoint left, TimingPoint right) => MeasuredTimePosition.CompareByAbsolutePosition(left.GetRelativeTimePosition(), right.GetRelativeTimePosition());