Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions osu.Game.Tests/Visual/Beatmaps/TestSceneFramedBeatmapClock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// 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.

using NUnit.Framework;
using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Rulesets;

namespace osu.Game.Tests.Visual.Beatmaps
{
public partial class TestSceneFramedBeatmapClock : OsuTestScene
{
private RealmAccess? realm;

[BackgroundDependencyLoader]
private void load(RealmAccess realm)
{
this.realm = realm;
}

[Test]
public void TestOffsetUpdatesOnBeatmapChange()
{
// Create two beatmaps with different IDs
var ruleset = realm!.Run(r => r.Find<RulesetInfo>("osu")!.Detach());

var beatmap1 = CreateWorkingBeatmap(CreateBeatmap(ruleset));
beatmap1.BeatmapInfo.UserSettings.Offset = 50;

var beatmap2 = CreateWorkingBeatmap(CreateBeatmap(ruleset));
beatmap2.BeatmapInfo.UserSettings.Offset = 100;

// Ensure they are in Realm
AddStep("Add beatmaps to Realm", () =>
{
realm!.Write(r =>
{
r.Add(beatmap1.BeatmapInfo, true);
r.Add(beatmap2.BeatmapInfo, true);
});
});

TestClockContainer? container = null;

AddStep("Create clock", () =>
{
Child = container = new TestClockContainer(beatmap1);
});

AddAssert("Offset is 50", () => checkOffset(container, 50));

AddStep("Change beatmap", () => container!.Beatmap.Value = beatmap2);

AddAssert("Offset is 100", () => checkOffset(container, 100));

// Test updating offset on current beatmap
AddStep("Update offset on current beatmap", () =>
{
realm!.Write(r =>
{
var b = r.Find<BeatmapInfo>(beatmap2.BeatmapInfo.ID);
if (b != null)
b.UserSettings.Offset = 200;
});
});

AddAssert("Offset is 200", () => checkOffset(container, 200));
}

private bool checkOffset(TestClockContainer? container, double expectedUserOffset)
{
if (container?.FramedClock == null) return false;

double platformOffset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 15 : 0;
return container.FramedClock.TotalAppliedOffset == expectedUserOffset + platformOffset;
}

private partial class TestClockContainer : DependencyProvidingContainer
{
public Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();

Check failure on line 83 in osu.Game.Tests/Visual/Beatmaps/TestSceneFramedBeatmapClock.cs

View workflow job for this annotation

GitHub Actions / Code Quality

Field can be made readonly in osu.Game.Tests\Visual\Beatmaps\TestSceneFramedBeatmapClock.cs on line 83

Check failure on line 83 in osu.Game.Tests/Visual/Beatmaps/TestSceneFramedBeatmapClock.cs

View workflow job for this annotation

GitHub Actions / Code Quality

Field can be made readonly in osu.Game.Tests\Visual\Beatmaps\TestSceneFramedBeatmapClock.cs on line 83
public FramedBeatmapClock? FramedClock { get; private set; }

public TestClockContainer(WorkingBeatmap initialBeatmap)
{
Beatmap.Value = initialBeatmap;
CachedDependencies = new (System.Type, object)[] { (typeof(IBindable<WorkingBeatmap>), Beatmap) };
}

[BackgroundDependencyLoader]
private void load()
{
FramedClock = new FramedBeatmapClock(true, false);
// Ensure rate is 1 so that platform offsets (which are rate-adjusted) are applied correctly.
FramedClock.Rate = 1;
Add(FramedClock);
}
}
}
}
22 changes: 14 additions & 8 deletions osu.Game/Beatmaps/FramedBeatmapClock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,23 @@ protected override void LoadComplete()
userAudioOffset = config.GetBindable<double>(OsuSetting.AudioOffset);
userAudioOffset.BindValueChanged(offset => userGlobalOffsetClock.Offset = offset.NewValue, true);

// TODO: this doesn't update when using ChangeSource() to change beatmap.
beatmapOffsetSubscription = realm.SubscribeToPropertyChanged(
r => r.Find<BeatmapInfo>(beatmap.Value.BeatmapInfo.ID)?.UserSettings,
settings => settings.Offset,
val =>
{
userBeatmapOffsetClock.Offset = val;
});
beatmap.BindValueChanged(b => updateBeatmapOffsetSubscription(b.NewValue), true);
}
}

private void updateBeatmapOffsetSubscription(WorkingBeatmap workingBeatmap)
{
beatmapOffsetSubscription?.Dispose();
beatmapOffsetSubscription = null;

Debug.Assert(userBeatmapOffsetClock != null);

beatmapOffsetSubscription = realm.SubscribeToPropertyChanged(
r => r.Find<BeatmapInfo>(workingBeatmap.BeatmapInfo.ID)?.UserSettings,
settings => settings.Offset,
val => userBeatmapOffsetClock.Offset = val);
}

protected override void Update()
{
base.Update();
Expand Down
Loading