1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 20:07:25 +08:00

Merge pull request #21351 from peppy/limit-barline-generation-sanity

Limit how far before the first hitobject that barlines can be generated
This commit is contained in:
Bartłomiej Dach 2022-11-23 17:51:10 +01:00 committed by GitHub
commit 1ad9d66e65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 1 deletions

View File

@ -83,5 +83,41 @@ namespace osu.Game.Rulesets.Taiko.Tests
AddAssert("first barline ommited", () => barlines.All(b => b.StartTime != start_time)); AddAssert("first barline ommited", () => barlines.All(b => b.StartTime != start_time));
AddAssert("second barline generated", () => barlines.Any(b => b.StartTime == start_time + (beat_length * time_signature_numerator))); AddAssert("second barline generated", () => barlines.Any(b => b.StartTime == start_time + (beat_length * time_signature_numerator)));
} }
[Test]
public void TestNegativeStartTimeTimingPoint()
{
const double beat_length = 250;
const int time_signature_numerator = 4;
var beatmap = new Beatmap<TaikoHitObject>
{
HitObjects =
{
new Hit
{
Type = HitType.Centre,
StartTime = 1000
}
},
BeatmapInfo =
{
Difficulty = new BeatmapDifficulty { SliderTickRate = 4 },
Ruleset = new TaikoRuleset().RulesetInfo
},
};
beatmap.ControlPointInfo.Add(-100, new TimingControlPoint
{
BeatLength = beat_length,
TimeSignature = new TimeSignature(time_signature_numerator)
});
var barlines = new BarLineGenerator<BarLine>(beatmap).BarLines;
AddAssert("bar line generated at t=900", () => barlines.Any(line => line.StartTime == 900));
AddAssert("bar line generated at t=1900", () => barlines.Any(line => line.StartTime == 1900));
}
} }
} }

View File

@ -27,7 +27,10 @@ namespace osu.Game.Rulesets.Objects
if (beatmap.HitObjects.Count == 0) if (beatmap.HitObjects.Count == 0)
return; return;
HitObject firstObject = beatmap.HitObjects.First();
HitObject lastObject = beatmap.HitObjects.Last(); HitObject lastObject = beatmap.HitObjects.Last();
double firstHitTime = firstObject.StartTime;
double lastHitTime = 1 + lastObject.GetEndTime(); double lastHitTime = 1 + lastObject.GetEndTime();
var timingPoints = beatmap.ControlPointInfo.TimingPoints; var timingPoints = beatmap.ControlPointInfo.TimingPoints;
@ -41,12 +44,31 @@ namespace osu.Game.Rulesets.Objects
EffectControlPoint currentEffectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTimingPoint.Time); EffectControlPoint currentEffectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTimingPoint.Time);
int currentBeat = 0; int currentBeat = 0;
// Don't generate barlines before the hit object or t=0 (whichever is earliest). Some beatmaps use very unrealistic values here (although none are ranked).
// I'm not sure we ever want barlines to appear before the first hitobject, but let's keep some degree of compatibility for now.
// Of note, this will still differ from stable if the first timing control point is t<0 and is not near the first hitobject.
double generationStartTime = Math.Min(0, firstHitTime);
// Stop on the next timing point, or if there is no next timing point stop slightly past the last object // Stop on the next timing point, or if there is no next timing point stop slightly past the last object
double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time : lastHitTime + currentTimingPoint.BeatLength * currentTimingPoint.TimeSignature.Numerator; double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time : lastHitTime + currentTimingPoint.BeatLength * currentTimingPoint.TimeSignature.Numerator;
double startTime = currentTimingPoint.Time;
double barLength = currentTimingPoint.BeatLength * currentTimingPoint.TimeSignature.Numerator; double barLength = currentTimingPoint.BeatLength * currentTimingPoint.TimeSignature.Numerator;
double startTime;
if (currentTimingPoint.Time > generationStartTime)
{
startTime = currentTimingPoint.Time;
}
else
{
// If the timing point starts before the minimum allowable time for bar lines,
// we still need to compute a start time for generation that is actually properly aligned with the timing point.
int barCount = (int)Math.Ceiling((generationStartTime - currentTimingPoint.Time) / barLength);
startTime = currentTimingPoint.Time + barCount * barLength;
}
if (currentEffectPoint.OmitFirstBarLine) if (currentEffectPoint.OmitFirstBarLine)
{ {
startTime += barLength; startTime += barLength;