1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 14:32:55 +08:00

Merge pull request #24142 from peppy/fix-gameplay-samepl-trigger-source-rewind

Fix `GameplaySampleTriggerSource` not handling rewinds correctly
This commit is contained in:
Bartłomiej Dach 2023-07-08 14:12:30 +02:00 committed by GitHub
commit 7af5b6ee5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 50 additions and 14 deletions

View File

@ -4,6 +4,7 @@
using osu.Framework.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
using osuTK;
using osuTK.Graphics;
@ -59,7 +60,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
lastDisplayedCombo = combo;
if (Time.Elapsed < 0)
if ((Clock as IGameplayClock)?.IsRewinding == true)
{
// needs more work to make rewind somehow look good.
// basically we want the previous increment to play... or turning off RemoveCompletedTransforms (not feasible from a performance angle).

View File

@ -10,6 +10,7 @@ using osu.Game.Rulesets.Catch.Objects.Drawables;
using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play;
using osuTK;
namespace osu.Game.Rulesets.Catch.UI
@ -96,7 +97,7 @@ namespace osu.Game.Rulesets.Catch.UI
comboDisplay.X = Catcher.X;
if (Time.Elapsed <= 0)
if ((Clock as IGameplayClock)?.IsRewinding == true)
{
// This is probably a wrong value, but currently the true value is not recorded.
// Setting `true` will prevent generation of false-positive after-images (with more false-negatives).

View File

@ -16,6 +16,7 @@ using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
using osuTK;
@ -298,7 +299,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
return false;
// do not run any of this logic when rewinding, as it inverts order of presses/releases.
if (Time.Elapsed < 0)
if ((Clock as IGameplayClock)?.IsRewinding == true)
return false;
if (CheckHittable?.Invoke(this, Time.Current) == false)
@ -337,7 +338,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
return;
// do not run any of this logic when rewinding, as it inverts order of presses/releases.
if (Time.Elapsed < 0)
if ((Clock as IGameplayClock)?.IsRewinding == true)
return;
Tail.UpdateResult();

View File

@ -14,6 +14,7 @@ using osu.Framework.Input.Events;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Skinning.Default;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
using osuTK;
@ -179,16 +180,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private Vector2? lastPosition;
private bool rewinding;
public void UpdateProgress(double completionProgress)
{
Position = drawableSlider.HitObject.CurvePositionAt(completionProgress);
var diff = lastPosition.HasValue ? lastPosition.Value - Position : Position - drawableSlider.HitObject.CurvePositionAt(completionProgress + 0.01f);
if (Clock.ElapsedFrameTime != 0)
rewinding = Clock.ElapsedFrameTime < 0;
bool rewinding = (Clock as IGameplayClock)?.IsRewinding == true;
// Ensure the value is substantially high enough to allow for Atan2 to get a valid angle.
if (diff.LengthFast < 0.01f)

View File

@ -125,6 +125,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public IEnumerable<double> NonGameplayAdjustments => throw new NotImplementedException();
public IBindable<bool> IsPaused => throw new NotImplementedException();
public bool IsRewinding => false;
}
}
}

View File

@ -107,7 +107,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
base.SetUpSteps();
AddStep("Add trigger source", () => Player.GameplayClockContainer.Add(sampleTriggerSource = new TestGameplaySampleTriggerSource(Player.DrawableRuleset.Playfield.HitObjectContainer)));
AddStep("Add trigger source", () => Player.DrawableRuleset.FrameStableComponents.Add(sampleTriggerSource = new TestGameplaySampleTriggerSource(Player.DrawableRuleset.Playfield.HitObjectContainer)));
}
[Test]
@ -153,6 +153,14 @@ namespace osu.Game.Tests.Visual.Gameplay
waitForAliveObjectIndex(2);
checkValidObjectIndex(2);
// test rewinding
seekBeforeIndex(1);
waitForAliveObjectIndex(1);
checkValidObjectIndex(1);
seekBeforeIndex(1, 400);
checkValidObjectIndex(0);
seekBeforeIndex(3);
waitForAliveObjectIndex(3);
checkValidObjectIndex(3);

View File

@ -64,6 +64,8 @@ namespace osu.Game.Beatmaps
[Resolved]
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
public bool IsRewinding { get; private set; }
public bool IsCoupled
{
get => decoupledClock.IsCoupled;
@ -133,6 +135,9 @@ namespace osu.Game.Beatmaps
}
else
finalClockSource.ProcessFrame();
if (Clock.ElapsedFrameTime != 0)
IsRewinding = Clock.ElapsedFrameTime < 0;
}
public double TotalAppliedOffset

View File

@ -24,6 +24,7 @@ using osu.Game.Rulesets.Objects.Pooling;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
using osuTK.Graphics;
@ -688,7 +689,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
protected bool UpdateResult(bool userTriggered)
{
// It's possible for input to get into a bad state when rewinding gameplay, so results should not be processed
if (Time.Elapsed < 0)
if ((Clock as IGameplayClock)?.IsRewinding == true)
return false;
if (Judged)

View File

@ -171,6 +171,9 @@ namespace osu.Game.Rulesets.UI
// The manual clock time has changed in the above code. The framed clock now needs to be updated
// to ensure that the its time is valid for our children before input is processed
framedClock.ProcessFrame();
if (framedClock.ElapsedFrameTime != 0)
IsRewinding = framedClock.ElapsedFrameTime < 0;
}
/// <summary>
@ -247,6 +250,8 @@ namespace osu.Game.Rulesets.UI
public IBindable<bool> IsPaused { get; } = new BindableBool();
public bool IsRewinding { get; private set; }
public double CurrentTime => framedClock.CurrentTime;
public double Rate => framedClock.Rate;

View File

@ -69,6 +69,14 @@ namespace osu.Game.Rulesets.UI
hitSound.Play();
});
protected override void Update()
{
base.Update();
if (gameplayClock?.IsRewinding == true)
mostValidObject = null;
}
protected HitObject? GetMostValidObject()
{
if (mostValidObject == null || isAlreadyHit(mostValidObject))

View File

@ -53,7 +53,7 @@ namespace osu.Game.Screens.Play
if (gameplayClock.CurrentTime < firstBreakTime)
firstBreakTime = null;
if (gameplayClock.ElapsedFrameTime < 0)
if (gameplayClock.IsRewinding)
return;
if (combo.NewValue == 0 && (combo.OldValue > 20 || (alwaysPlayFirst.Value && firstBreakTime == null)))

View File

@ -19,11 +19,10 @@ namespace osu.Game.Screens.Play
[Cached(typeof(IGameplayClock))]
public partial class GameplayClockContainer : Container, IAdjustableClock, IGameplayClock
{
/// <summary>
/// Whether gameplay is paused.
/// </summary>
public IBindable<bool> IsPaused => isPaused;
public bool IsRewinding => GameplayClock.IsRewinding;
/// <summary>
/// The source clock. Should generally not be used for any timekeeping purposes.
/// </summary>

View File

@ -23,6 +23,14 @@ namespace osu.Game.Screens.Play
/// </summary>
IAdjustableAudioComponent AdjustmentsFromMods { get; }
/// <summary>
/// Whether gameplay is paused.
/// </summary>
IBindable<bool> IsPaused { get; }
/// <summary>
/// Whether the clock is currently rewinding.
/// </summary>
bool IsRewinding { get; }
}
}