mirror of
https://github.com/osukey/osukey.git
synced 2025-05-31 10:27:26 +09:00
Fix SPM changing incorrectly with playback rate changes
This commit is contained in:
parent
0cecb2bba3
commit
3f788da06d
@ -2,11 +2,13 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||||
@ -77,6 +79,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
private bool rotationTransferred;
|
private bool rotationTransferred;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private GameplayClock gameplayClock { get; set; }
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
@ -126,7 +131,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
currentRotation += angle;
|
currentRotation += angle;
|
||||||
// rate has to be applied each frame, because it's not guaranteed to be constant throughout playback
|
// rate has to be applied each frame, because it's not guaranteed to be constant throughout playback
|
||||||
// (see: ModTimeRamp)
|
// (see: ModTimeRamp)
|
||||||
RateAdjustedRotation += (float)(Math.Abs(angle) * Clock.Rate);
|
RateAdjustedRotation += (float)(Math.Abs(angle) * gameplayClock.TrueGameplayRate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
@ -59,7 +61,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
{
|
{
|
||||||
if (clock != null)
|
if (clock != null)
|
||||||
{
|
{
|
||||||
stabilityGameplayClock.ParentGameplayClock = parentGameplayClock = clock;
|
parentGameplayClock = stabilityGameplayClock.ParentGameplayClock = clock;
|
||||||
GameplayClock.IsPaused.BindTo(clock.IsPaused);
|
GameplayClock.IsPaused.BindTo(clock.IsPaused);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,7 +193,9 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
private class StabilityGameplayClock : GameplayClock
|
private class StabilityGameplayClock : GameplayClock
|
||||||
{
|
{
|
||||||
public IFrameBasedClock ParentGameplayClock;
|
public GameplayClock ParentGameplayClock;
|
||||||
|
|
||||||
|
public override IEnumerable<Bindable<double>> NonGameplayAdjustments => ParentGameplayClock.NonGameplayAdjustments;
|
||||||
|
|
||||||
public StabilityGameplayClock(FramedClock underlyingClock)
|
public StabilityGameplayClock(FramedClock underlyingClock)
|
||||||
: base(underlyingClock)
|
: base(underlyingClock)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
|
|
||||||
@ -20,6 +22,11 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public readonly BindableBool IsPaused = new BindableBool();
|
public readonly BindableBool IsPaused = new BindableBool();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All adjustments applied to this clock which don't come from gameplay or mods.
|
||||||
|
/// </summary>
|
||||||
|
public virtual IEnumerable<Bindable<double>> NonGameplayAdjustments => Enumerable.Empty<Bindable<double>>();
|
||||||
|
|
||||||
public GameplayClock(IFrameBasedClock underlyingClock)
|
public GameplayClock(IFrameBasedClock underlyingClock)
|
||||||
{
|
{
|
||||||
this.underlyingClock = underlyingClock;
|
this.underlyingClock = underlyingClock;
|
||||||
@ -29,6 +36,23 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public double Rate => underlyingClock.Rate;
|
public double Rate => underlyingClock.Rate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The rate of gameplay when playback is at 100%.
|
||||||
|
/// This excludes any seeking / user adjustments.
|
||||||
|
/// </summary>
|
||||||
|
public double TrueGameplayRate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
double baseRate = Rate;
|
||||||
|
|
||||||
|
foreach (var adjustment in NonGameplayAdjustments)
|
||||||
|
baseRate /= adjustment.Value;
|
||||||
|
|
||||||
|
return baseRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsRunning => underlyingClock.IsRunning;
|
public bool IsRunning => underlyingClock.IsRunning;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -50,8 +51,10 @@ namespace osu.Game.Screens.Play
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The final clock which is exposed to underlying components.
|
/// The final clock which is exposed to underlying components.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Cached]
|
public GameplayClock GameplayClock => localGameplayClock;
|
||||||
public readonly GameplayClock GameplayClock;
|
|
||||||
|
[Cached(typeof(GameplayClock))]
|
||||||
|
private readonly LocalGameplayClock localGameplayClock;
|
||||||
|
|
||||||
private Bindable<double> userAudioOffset;
|
private Bindable<double> userAudioOffset;
|
||||||
|
|
||||||
@ -79,7 +82,7 @@ namespace osu.Game.Screens.Play
|
|||||||
userOffsetClock = new HardwareCorrectionOffsetClock(platformOffsetClock);
|
userOffsetClock = new HardwareCorrectionOffsetClock(platformOffsetClock);
|
||||||
|
|
||||||
// the clock to be exposed via DI to children.
|
// the clock to be exposed via DI to children.
|
||||||
GameplayClock = new GameplayClock(userOffsetClock);
|
localGameplayClock = new LocalGameplayClock(userOffsetClock);
|
||||||
|
|
||||||
GameplayClock.IsPaused.BindTo(IsPaused);
|
GameplayClock.IsPaused.BindTo(IsPaused);
|
||||||
}
|
}
|
||||||
@ -200,11 +203,26 @@ namespace osu.Game.Screens.Play
|
|||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
if (!IsPaused.Value)
|
if (!IsPaused.Value)
|
||||||
|
{
|
||||||
userOffsetClock.ProcessFrame();
|
userOffsetClock.ProcessFrame();
|
||||||
|
}
|
||||||
|
|
||||||
base.Update();
|
base.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double getTrueGameplayRate()
|
||||||
|
{
|
||||||
|
double baseRate = track.Rate;
|
||||||
|
|
||||||
|
if (speedAdjustmentsApplied)
|
||||||
|
{
|
||||||
|
baseRate /= UserPlaybackRate.Value;
|
||||||
|
baseRate /= pauseFreqAdjust.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseRate;
|
||||||
|
}
|
||||||
|
|
||||||
private bool speedAdjustmentsApplied;
|
private bool speedAdjustmentsApplied;
|
||||||
|
|
||||||
private void updateRate()
|
private void updateRate()
|
||||||
@ -215,6 +233,9 @@ namespace osu.Game.Screens.Play
|
|||||||
track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
|
track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
|
||||||
track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate);
|
track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate);
|
||||||
|
|
||||||
|
localGameplayClock.MutableNonGameplayAdjustments.Add(pauseFreqAdjust);
|
||||||
|
localGameplayClock.MutableNonGameplayAdjustments.Add(UserPlaybackRate);
|
||||||
|
|
||||||
speedAdjustmentsApplied = true;
|
speedAdjustmentsApplied = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,9 +252,24 @@ namespace osu.Game.Screens.Play
|
|||||||
track.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
|
track.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
|
||||||
track.RemoveAdjustment(AdjustableProperty.Tempo, UserPlaybackRate);
|
track.RemoveAdjustment(AdjustableProperty.Tempo, UserPlaybackRate);
|
||||||
|
|
||||||
|
localGameplayClock.MutableNonGameplayAdjustments.Remove(pauseFreqAdjust);
|
||||||
|
localGameplayClock.MutableNonGameplayAdjustments.Remove(UserPlaybackRate);
|
||||||
|
|
||||||
speedAdjustmentsApplied = false;
|
speedAdjustmentsApplied = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class LocalGameplayClock : GameplayClock
|
||||||
|
{
|
||||||
|
public readonly List<Bindable<double>> MutableNonGameplayAdjustments = new List<Bindable<double>>();
|
||||||
|
|
||||||
|
public override IEnumerable<Bindable<double>> NonGameplayAdjustments => MutableNonGameplayAdjustments;
|
||||||
|
|
||||||
|
public LocalGameplayClock(FramedOffsetClock underlyingClock)
|
||||||
|
: base(underlyingClock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class HardwareCorrectionOffsetClock : FramedOffsetClock
|
private class HardwareCorrectionOffsetClock : FramedOffsetClock
|
||||||
{
|
{
|
||||||
// we always want to apply the same real-time offset, so it should be adjusted by the difference in playback rate (from realtime) to achieve this.
|
// we always want to apply the same real-time offset, so it should be adjusted by the difference in playback rate (from realtime) to achieve this.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user