// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.Lists; using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Beatmaps.Legacy { public class LegacyControlPointInfo : ControlPointInfo { /// <summary> /// All sound points. /// </summary> [JsonProperty] public IReadOnlyList<SampleControlPoint> SamplePoints => samplePoints; private readonly SortedList<SampleControlPoint> samplePoints = new SortedList<SampleControlPoint>(Comparer<SampleControlPoint>.Default); /// <summary> /// Finds the sound control point that is active at <paramref name="time"/>. /// </summary> /// <param name="time">The time to find the sound control point at.</param> /// <returns>The sound control point.</returns> public SampleControlPoint SamplePointAt(double time) => BinarySearchWithFallback(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : SampleControlPoint.DEFAULT); /// <summary> /// All difficulty points. /// </summary> [JsonProperty] public IReadOnlyList<DifficultyControlPoint> DifficultyPoints => difficultyPoints; private readonly SortedList<DifficultyControlPoint> difficultyPoints = new SortedList<DifficultyControlPoint>(Comparer<DifficultyControlPoint>.Default); /// <summary> /// Finds the difficulty control point that is active at <paramref name="time"/>. /// </summary> /// <param name="time">The time to find the difficulty control point at.</param> /// <returns>The difficulty control point.</returns> public DifficultyControlPoint DifficultyPointAt(double time) => BinarySearchWithFallback(DifficultyPoints, time, DifficultyControlPoint.DEFAULT); public override void Clear() { base.Clear(); samplePoints.Clear(); difficultyPoints.Clear(); } protected override bool CheckAlreadyExisting(double time, ControlPoint newPoint) { switch (newPoint) { case SampleControlPoint: // intentionally don't use SamplePointAt (we always need to consider the first sample point). var existing = BinarySearch(SamplePoints, time); return newPoint.IsRedundant(existing); case DifficultyControlPoint: return newPoint.IsRedundant(DifficultyPointAt(time)); default: return base.CheckAlreadyExisting(time, newPoint); } } protected override void GroupItemAdded(ControlPoint controlPoint) { switch (controlPoint) { case SampleControlPoint typed: samplePoints.Add(typed); return; case DifficultyControlPoint typed: difficultyPoints.Add(typed); return; default: base.GroupItemAdded(controlPoint); break; } } protected override void GroupItemRemoved(ControlPoint controlPoint) { switch (controlPoint) { case SampleControlPoint typed: samplePoints.Remove(typed); break; case DifficultyControlPoint typed: difficultyPoints.Remove(typed); break; } base.GroupItemRemoved(controlPoint); } } }