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

Rewrite seeking to better handle timing point boundaries

This commit is contained in:
smoogipoo 2018-03-13 16:54:34 +09:00
parent df352c98d6
commit 299de4b866

View File

@ -142,28 +142,70 @@ namespace osu.Game.Rulesets.Edit
protected override bool OnWheel(InputState state)
{
var timingPoint = beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(adjustableClock.CurrentTime);
const int beat_snap_divisor = 4; // Todo: This should not be a constant
double seekAmount = timingPoint.BeatLength / beat_snap_divisor;
int direction = state.Mouse.WheelDelta > 0 ? -1 : 1;
// The direction is added to prevent rounding issues by enforcing that abs(unsnappedTime - currentTime) > beatLength
double unsnappedTime = adjustableClock.CurrentTime + seekAmount * direction + direction;
// Unsnapped time may be between two beats, so we need to snap it to the closest beat
int closestBeat;
if (direction > 0)
closestBeat = (int)Math.Floor(unsnappedTime / seekAmount);
if (state.Mouse.WheelDelta > 0)
SeekBackward(true);
else
closestBeat = (int)Math.Ceiling(unsnappedTime / seekAmount);
double snappedTime = closestBeat * seekAmount;
adjustableClock.Seek(snappedTime);
SeekForward(true);
return true;
}
/// <summary>
/// Seeks the current time one beat-snapped beat-length backwards.
/// </summary>
/// <param name="snapped">Whether to snap to the closest beat.</param>
public void SeekBackward(bool snapped) => seek(-1, snapped);
/// <summary>
/// Seeks the current time one beat-snapped beat-length forwards.
/// </summary>
/// <param name="snapped">Whether to snap to the closest beat.</param>
public void SeekForward(bool snapped) => seek(1, snapped);
private void seek(int direction, bool snapped)
{
// Todo: This should not be a constant, but feels good for now
const int beat_snap_divisor = 4;
var currentTimingPoint = beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(adjustableClock.CurrentTime);
double seekAmount = currentTimingPoint.BeatLength / beat_snap_divisor;
double seekTime = adjustableClock.CurrentTime + seekAmount * direction;
if (!snapped)
{
adjustableClock.Seek(seekTime);
return;
}
var nextTimingPoint = beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > currentTimingPoint.Time);
var firstTimingPoint = beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.First();
if (currentTimingPoint != firstTimingPoint && seekTime < currentTimingPoint.Time)
seekTime = currentTimingPoint.Time - 1; // -1 to be in the prior timing point's boundary
else if (nextTimingPoint != null && seekTime >= nextTimingPoint.Time)
seekTime = nextTimingPoint.Time + 1; // +1 to be in the next timing point's boundary
else
{
// We will be snapping to beats within the current timing point
seekTime -= currentTimingPoint.Time;
// When rounding below, we need to ensure that abs(seekTime - currentTime) > seekAmount
// This is done by adding direction - a small offset, to seekTime
seekTime += direction;
// Determine the index from the current timing point of the closest beat to seekTime, accounting for scrolling direction
int closestBeat;
if (direction > 0)
closestBeat = (int)Math.Floor(seekTime / seekAmount);
else
closestBeat = (int)Math.Ceiling(seekTime / seekAmount);
seekTime = currentTimingPoint.Time + closestBeat * seekAmount;
}
adjustableClock.Seek(seekTime);
}
private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool;
protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true);