Merge pull request #8815 from smoogipoo/fix-controlpoint-decode

Fix control point overriding working incorrectly
This commit is contained in:
Dean Herbert 2020-04-21 16:18:50 +09:00 committed by GitHub
commit aa153290a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 15 deletions

View File

@ -241,6 +241,11 @@ namespace osu.Game.Tests.Beatmaps.Formats
{ {
var controlPoints = decoder.Decode(stream).ControlPointInfo; var controlPoints = decoder.Decode(stream).ControlPointInfo;
Assert.That(controlPoints.TimingPoints.Count, Is.EqualTo(4));
Assert.That(controlPoints.DifficultyPoints.Count, Is.EqualTo(3));
Assert.That(controlPoints.EffectPoints.Count, Is.EqualTo(3));
Assert.That(controlPoints.SamplePoints.Count, Is.EqualTo(3));
Assert.That(controlPoints.DifficultyPointAt(500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); Assert.That(controlPoints.DifficultyPointAt(500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1));
Assert.That(controlPoints.DifficultyPointAt(1500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); Assert.That(controlPoints.DifficultyPointAt(1500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1));
Assert.That(controlPoints.DifficultyPointAt(2500).SpeedMultiplier, Is.EqualTo(0.75).Within(0.1)); Assert.That(controlPoints.DifficultyPointAt(2500).SpeedMultiplier, Is.EqualTo(0.75).Within(0.1));

View File

@ -386,17 +386,10 @@ namespace osu.Game.Beatmaps.Formats
SampleVolume = sampleVolume, SampleVolume = sampleVolume,
CustomSampleBank = customSampleBank, CustomSampleBank = customSampleBank,
}, timingChange); }, timingChange);
// To handle the scenario where a non-timing line shares the same time value as a subsequent timing line but
// appears earlier in the file, we buffer non-timing control points and rewrite them *after* control points from the timing line
// with the same time value (allowing them to overwrite as necessary).
//
// The expected outcome is that we prefer the non-timing line's adjustments over the timing line's adjustments when time is equal.
if (timingChange)
flushPendingPoints();
} }
private readonly List<ControlPoint> pendingControlPoints = new List<ControlPoint>(); private readonly List<ControlPoint> pendingControlPoints = new List<ControlPoint>();
private readonly HashSet<Type> pendingControlPointTypes = new HashSet<Type>();
private double pendingControlPointsTime; private double pendingControlPointsTime;
private void addControlPoint(double time, ControlPoint point, bool timingChange) private void addControlPoint(double time, ControlPoint point, bool timingChange)
@ -405,21 +398,28 @@ namespace osu.Game.Beatmaps.Formats
flushPendingPoints(); flushPendingPoints();
if (timingChange) if (timingChange)
{ pendingControlPoints.Insert(0, point);
beatmap.ControlPointInfo.Add(time, point); else
return; pendingControlPoints.Add(point);
}
pendingControlPoints.Add(point);
pendingControlPointsTime = time; pendingControlPointsTime = time;
} }
private void flushPendingPoints() private void flushPendingPoints()
{ {
foreach (var p in pendingControlPoints) // Changes from non-timing-points are added to the end of the list (see addControlPoint()) and should override any changes from timing-points (added to the start of the list).
beatmap.ControlPointInfo.Add(pendingControlPointsTime, p); for (int i = pendingControlPoints.Count - 1; i >= 0; i--)
{
var type = pendingControlPoints[i].GetType();
if (pendingControlPointTypes.Contains(type))
continue;
pendingControlPointTypes.Add(type);
beatmap.ControlPointInfo.Add(pendingControlPointsTime, pendingControlPoints[i]);
}
pendingControlPoints.Clear(); pendingControlPoints.Clear();
pendingControlPointTypes.Clear();
} }
private void handleHitObject(string line) private void handleHitObject(string line)