1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 14:53:01 +08:00

Refactor lookup methods to avoid linq and reduce TimingPointAt calls

This commit is contained in:
Dean Herbert 2021-04-28 17:16:05 +09:00
parent c5186b6a69
commit 859898d98f

View File

@ -170,35 +170,47 @@ namespace osu.Game.Beatmaps.ControlPoints
public double GetClosestSnappedTime(double time, int beatDivisor, double? referenceTime = null) public double GetClosestSnappedTime(double time, int beatDivisor, double? referenceTime = null)
{ {
var timingPoint = TimingPointAt(referenceTime ?? time); var timingPoint = TimingPointAt(referenceTime ?? time);
var beatLength = timingPoint.BeatLength / beatDivisor; return getClosestSnappedTime(timingPoint, time, beatDivisor);
var beatLengths = (int)Math.Round((time - timingPoint.Time) / beatLength, MidpointRounding.AwayFromZero);
return timingPoint.Time + beatLengths * beatLength;
} }
/// <summary> /// <summary>
/// Returns the time on any valid beat divisor closest to the given time. /// Returns the time on *ANY* valid beat divisor, favouring the divisor closest to the given time.
/// </summary> /// </summary>
/// <param name="time">The time to find the closest snapped time to.</param> /// <param name="time">The time to find the closest snapped time to.</param>
/// <param name="referenceTime">An optional reference point to use for timing point lookup.</param> public double GetClosestSnappedTime(double time) => GetClosestSnappedTime(time, GetClosestBeatDivisor(time));
public double GetClosestSnappedTime(double time, double? referenceTime = null)
{
return GetClosestSnappedTime(time, GetClosestBeatDivisor(time, referenceTime), referenceTime);
}
/// <summary> /// <summary>
/// Returns the beat snap divisor closest to the given time. If two are equally close, the smallest is returned. /// Returns the beat snap divisor closest to the given time. If two are equally close, the smallest divisor is returned.
/// </summary> /// </summary>
/// <param name="time">The time to find the closest beat snap divisor to.</param> /// <param name="time">The time to find the closest beat snap divisor to.</param>
/// <param name="referenceTime">An optional reference point to use for timing point lookup.</param> /// <param name="referenceTime">An optional reference point to use for timing point lookup.</param>
public int GetClosestBeatDivisor(double time, double? referenceTime = null) public int GetClosestBeatDivisor(double time, double? referenceTime = null)
{ {
double getUnsnap(int divisor) => Math.Abs(time - GetClosestSnappedTime(time, divisor, referenceTime)); TimingControlPoint timingPoint = TimingPointAt(referenceTime ?? time);
int[] divisors = BindableBeatDivisor.VALID_DIVISORS; int closestDivisor = 0;
double smallestUnsnap = divisors.Min(getUnsnap); double closestTime = double.MaxValue;
return divisors.FirstOrDefault(divisor => getUnsnap(divisor) == smallestUnsnap); foreach (int divisor in BindableBeatDivisor.VALID_DIVISORS)
{
double distanceFromSnap = Math.Abs(time - getClosestSnappedTime(timingPoint, time, divisor));
if (distanceFromSnap < closestTime)
{
closestDivisor = divisor;
closestTime = distanceFromSnap;
}
}
return closestDivisor;
}
private static double getClosestSnappedTime(TimingControlPoint timingPoint, double time, int beatDivisor)
{
var beatLength = timingPoint.BeatLength / beatDivisor;
var beatLengths = (int)Math.Round((time - timingPoint.Time) / beatLength, MidpointRounding.AwayFromZero);
return timingPoint.Time + beatLengths * beatLength;
} }
/// <summary> /// <summary>