Fix gameplay offset handling on seeks

This commit is contained in:
Dean Herbert 2019-04-03 16:58:20 +09:00
parent b0d6456523
commit 50f8ab3dfb
1 changed files with 23 additions and 14 deletions

View File

@ -36,6 +36,8 @@ public class GameplayClockContainer : Container
/// </summary>
private readonly DecoupleableInterpolatingFramedClock adjustableClock;
private readonly double gameplayStartTime;
public readonly Bindable<double> UserPlaybackRate = new BindableDouble(1)
{
Default = 1,
@ -52,11 +54,14 @@ public class GameplayClockContainer : Container
private Bindable<double> userAudioOffset;
private readonly FramedOffsetClock offsetClock;
private readonly FramedOffsetClock userOffsetClock;
private readonly FramedOffsetClock platformOffsetClock;
public GameplayClockContainer(WorkingBeatmap beatmap, double gameplayStartTime)
{
this.beatmap = beatmap;
this.gameplayStartTime = gameplayStartTime;
RelativeSizeAxes = Axes.Both;
@ -64,30 +69,31 @@ public GameplayClockContainer(WorkingBeatmap beatmap, double gameplayStartTime)
adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
adjustableClock.Seek(Math.Min(0, gameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn));
adjustableClock.ProcessFrame();
// Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited.
// This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
var platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0 };
platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0 };
// the final usable gameplay clock with user-set offsets applied.
offsetClock = new FramedOffsetClock(platformOffsetClock);
userOffsetClock = new FramedOffsetClock(platformOffsetClock);
// the clock to be exposed via DI to children.
GameplayClock = new GameplayClock(offsetClock);
GameplayClock = new GameplayClock(userOffsetClock);
GameplayClock.IsPaused.BindTo(IsPaused);
}
private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset;
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
userAudioOffset = config.GetBindable<double>(OsuSetting.AudioOffset);
userAudioOffset.BindValueChanged(offset => offsetClock.Offset = offset.NewValue, true);
userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true);
UserPlaybackRate.ValueChanged += _ => updateRate();
Seek(Math.Min(0, gameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn));
adjustableClock.ProcessFrame();
}
public void Restart()
@ -104,9 +110,7 @@ public void Restart()
this.Delay(750).Schedule(() =>
{
if (!IsPaused.Value)
{
adjustableClock.Start();
}
Start();
});
});
});
@ -121,7 +125,12 @@ public void Start()
IsPaused.Value = false;
}
public void Seek(double time) => adjustableClock.Seek(time);
public void Seek(double time)
{
// remove the offset component here because most of the time we want the seek to be aligned to gameplay, not the audio track.
// we may want to consider reversing the application of offsets in the future as it may feel more correct.
adjustableClock.Seek(time - totalOffset);
}
public void Stop()
{
@ -138,7 +147,7 @@ public void ResetLocalAdjustments()
protected override void Update()
{
if (!IsPaused.Value)
offsetClock.ProcessFrame();
userOffsetClock.ProcessFrame();
base.Update();
}