Skip to content

Commit

Permalink
Merge pull request #17093 from peppy/offset-ui-improvements
Browse files Browse the repository at this point in the history
Show beatmap offset adjustments in a more visual way
  • Loading branch information
peppy committed Mar 5, 2022
2 parents 6264dd2 + 0e8ad4b commit 4de66bb
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 87 deletions.
Expand Up @@ -62,11 +62,11 @@ public void TestCalibrationFromZero()
};
});

AddAssert("Has calibration button", () => offsetControl.ChildrenOfType<SettingsButton>().Any());
AddUntilStep("Has calibration button", () => offsetControl.ChildrenOfType<SettingsButton>().Any());
AddStep("Press button", () => offsetControl.ChildrenOfType<SettingsButton>().Single().TriggerClick());
AddAssert("Offset is adjusted", () => offsetControl.Current.Value == -average_error);

AddAssert("Button is disabled", () => !offsetControl.ChildrenOfType<SettingsButton>().Single().Enabled.Value);
AddUntilStep("Button is disabled", () => !offsetControl.ChildrenOfType<SettingsButton>().Single().Enabled.Value);
AddStep("Remove reference score", () => offsetControl.ReferenceScore.Value = null);
AddAssert("No calibration button", () => !offsetControl.ChildrenOfType<SettingsButton>().Any());
}
Expand All @@ -90,11 +90,11 @@ public void TestCalibrationFromNonZero()
};
});

AddAssert("Has calibration button", () => offsetControl.ChildrenOfType<SettingsButton>().Any());
AddUntilStep("Has calibration button", () => offsetControl.ChildrenOfType<SettingsButton>().Any());
AddStep("Press button", () => offsetControl.ChildrenOfType<SettingsButton>().Single().TriggerClick());
AddAssert("Offset is adjusted", () => offsetControl.Current.Value == initial_offset - average_error);

AddAssert("Button is disabled", () => !offsetControl.ChildrenOfType<SettingsButton>().Single().Enabled.Value);
AddUntilStep("Button is disabled", () => !offsetControl.ChildrenOfType<SettingsButton>().Single().Enabled.Value);
AddStep("Remove reference score", () => offsetControl.ReferenceScore.Value = null);
AddAssert("No calibration button", () => !offsetControl.ChildrenOfType<SettingsButton>().Any());
}
Expand Down
Expand Up @@ -8,6 +8,7 @@
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Ranking.Statistics;
Expand All @@ -17,10 +18,15 @@ namespace osu.Game.Tests.Visual.Ranking
{
public class TestSceneHitEventTimingDistributionGraph : OsuTestScene
{
private HitEventTimingDistributionGraph graph;

private static readonly HitObject placeholder_object = new HitCircle();

[Test]
public void TestManyDistributedEvents()
{
createTest(CreateDistributedHitEvents());
AddStep("add adjustment", () => graph.UpdateOffset(10));
}

[Test]
Expand All @@ -32,13 +38,13 @@ public void TestManyDistributedEventsOffset()
[Test]
public void TestAroundCentre()
{
createTest(Enumerable.Range(-150, 300).Select(i => new HitEvent(i / 50f, HitResult.Perfect, new HitCircle(), new HitCircle(), null)).ToList());
createTest(Enumerable.Range(-150, 300).Select(i => new HitEvent(i / 50f, HitResult.Perfect, placeholder_object, placeholder_object, null)).ToList());
}

[Test]
public void TestZeroTimeOffset()
{
createTest(Enumerable.Range(0, 100).Select(_ => new HitEvent(0, HitResult.Perfect, new HitCircle(), new HitCircle(), null)).ToList());
createTest(Enumerable.Range(0, 100).Select(_ => new HitEvent(0, HitResult.Perfect, placeholder_object, placeholder_object, null)).ToList());
}

[Test]
Expand All @@ -53,9 +59,9 @@ public void TestMissesDontShow()
createTest(Enumerable.Range(0, 100).Select(i =>
{
if (i % 2 == 0)
return new HitEvent(0, HitResult.Perfect, new HitCircle(), new HitCircle(), null);
return new HitEvent(0, HitResult.Perfect, placeholder_object, placeholder_object, null);
return new HitEvent(30, HitResult.Miss, new HitCircle(), new HitCircle(), null);
return new HitEvent(30, HitResult.Miss, placeholder_object, placeholder_object, null);
}).ToList());
}

Expand All @@ -68,7 +74,7 @@ public void TestMissesDontShow()
RelativeSizeAxes = Axes.Both,
Colour = Color4Extensions.FromHex("#333")
},
new HitEventTimingDistributionGraph(events)
graph = new HitEventTimingDistributionGraph(events)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Expand All @@ -83,10 +89,10 @@ public static List<HitEvent> CreateDistributedHitEvents(double centre = 0, doubl

for (int i = 0; i < range * 2; i++)
{
int count = (int)(Math.Pow(range - Math.Abs(i - range), 2));
int count = (int)(Math.Pow(range - Math.Abs(i - range), 2)) / 10;

for (int j = 0; j < count; j++)
hitEvents.Add(new HitEvent(centre + i - range, HitResult.Perfect, new HitCircle(), new HitCircle(), null));
hitEvents.Add(new HitEvent(centre + i - range, HitResult.Perfect, placeholder_object, placeholder_object, null));
}

return hitEvents;
Expand Down
6 changes: 6 additions & 0 deletions osu.Game/Configuration/OsuConfigManager.cs
Expand Up @@ -270,7 +270,13 @@ public enum OsuSetting
MouseDisableButtons,
MouseDisableWheel,
ConfineMouseMode,

/// <summary>
/// Globally applied audio offset.
/// This is added to the audio track's current time. Higher values will cause gameplay to occur earlier, relative to the audio track.
/// </summary>
AudioOffset,

VolumeInactive,
MenuMusic,
MenuVoice,
Expand Down
17 changes: 13 additions & 4 deletions osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs
Expand Up @@ -54,6 +54,7 @@ public class BeatmapOffsetControl : CompositeDrawable

private double lastPlayAverage;
private double lastPlayBeatmapOffset;
private HitEventTimingDistributionGraph? lastPlayGraph;

private SettingsButton? useAverageButton;

Expand Down Expand Up @@ -107,8 +108,8 @@ private LocalisableString getEarlyLateText(double value)
Debug.Assert(value != 0);

return value > 0
? BeatmapOffsetControlStrings.HitObjectsAppearLater
: BeatmapOffsetControlStrings.HitObjectsAppearEarlier;
? BeatmapOffsetControlStrings.HitObjectsAppearEarlier
: BeatmapOffsetControlStrings.HitObjectsAppearLater;
}
}
}
Expand Down Expand Up @@ -147,6 +148,12 @@ private void currentChanged(ValueChangedEvent<double> offset)

void updateOffset()
{
// the last play graph is relative to the offset at the point of the last play, so we need to factor that out.
double adjustmentSinceLastPlay = lastPlayBeatmapOffset - Current.Value;

// Negative is applied here because the play graph is considering a hit offset, not track (as we currently use for clocks).
lastPlayGraph?.UpdateOffset(-adjustmentSinceLastPlay);

// ensure the previous write has completed. ignoring performance concerns, if we don't do this, the async writes could be out of sequence.
if (realmWriteTask?.IsCompleted == false)
{
Expand All @@ -155,7 +162,9 @@ void updateOffset()
}

if (useAverageButton != null)
useAverageButton.Enabled.Value = !Precision.AlmostEquals(Current.Value, lastPlayBeatmapOffset - lastPlayAverage, Current.Precision / 2);
{
useAverageButton.Enabled.Value = !Precision.AlmostEquals(lastPlayAverage, adjustmentSinceLastPlay, Current.Precision / 2);
}

realmWriteTask = realm.WriteAsync(r =>
{
Expand Down Expand Up @@ -216,7 +225,7 @@ private void scoreChanged(ValueChangedEvent<ScoreInfo> score)

referenceScoreContainer.AddRange(new Drawable[]
{
new HitEventTimingDistributionGraph(hitEvents)
lastPlayGraph = new HitEventTimingDistributionGraph(hitEvents)
{
RelativeSizeAxes = Axes.X,
Height = 50,
Expand Down

0 comments on commit 4de66bb

Please sign in to comment.