mirror of
https://github.com/osukey/osukey.git
synced 2025-07-01 16:29:58 +09:00
Centralise and update WorkingBeatmap creation in test cases
This commit is contained in:
@ -3,15 +3,21 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
@ -19,7 +25,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[Cached(typeof(Bindable<WorkingBeatmap>))]
|
||||
[Cached(typeof(IBindable<WorkingBeatmap>))]
|
||||
private readonly OsuTestBeatmap beatmap = new OsuTestBeatmap(new DummyWorkingBeatmap(), null);
|
||||
private OsuTestBeatmap beatmap;
|
||||
|
||||
protected BindableBeatmap Beatmap => beatmap;
|
||||
|
||||
@ -39,7 +45,10 @@ namespace osu.Game.Tests.Visual
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
// This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures
|
||||
beatmap.Default = new DummyWorkingBeatmap(parent.Get<OsuGameBase>());
|
||||
beatmap = new OsuTestBeatmap(new DummyWorkingBeatmap(parent.Get<OsuGameBase>()))
|
||||
{
|
||||
Default = new DummyWorkingBeatmap(parent.Get<OsuGameBase>())
|
||||
};
|
||||
|
||||
return Dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
}
|
||||
@ -49,8 +58,19 @@ namespace osu.Game.Tests.Visual
|
||||
localStorage = new Lazy<Storage>(() => new NativeStorage($"{GetType().Name}-{Guid.NewGuid()}"));
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private AudioManager audio { get; set; }
|
||||
|
||||
protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset);
|
||||
|
||||
protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset = null) =>
|
||||
CreateWorkingBeatmap(CreateBeatmap(ruleset));
|
||||
|
||||
protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) =>
|
||||
new ClockBackedTestWorkingBeatmap(beatmap, Clock, audio);
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audioManager, RulesetStore rulesets)
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
Ruleset.Value = rulesets.AvailableRulesets.First();
|
||||
}
|
||||
@ -59,7 +79,8 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
beatmap?.Value.Track.Stop();
|
||||
if (beatmap?.Value.TrackLoaded == true)
|
||||
beatmap.Value.Track.Stop();
|
||||
|
||||
if (localStorage.IsValueCreated)
|
||||
{
|
||||
@ -76,6 +97,164 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
protected override ITestSceneTestRunner CreateRunner() => new OsuTestSceneTestRunner();
|
||||
|
||||
public class ClockBackedTestWorkingBeatmap : TestWorkingBeatmap
|
||||
{
|
||||
private readonly Track track;
|
||||
|
||||
private readonly TrackVirtualStore store;
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance which creates a <see cref="TestBeatmap"/> for the provided ruleset when requested.
|
||||
/// </summary>
|
||||
/// <param name="ruleset">The target ruleset.</param>
|
||||
/// <param name="referenceClock">A clock which should be used instead of a stopwatch for virtual time progression.</param>
|
||||
/// <param name="audio">Audio manager. Required if a reference clock isn't provided.</param>
|
||||
public ClockBackedTestWorkingBeatmap(RulesetInfo ruleset, IFrameBasedClock referenceClock, AudioManager audio)
|
||||
: this(new TestBeatmap(ruleset), referenceClock, audio)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance which provides the <see cref="IBeatmap"/> when requested.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap</param>
|
||||
/// <param name="referenceClock">An optional clock which should be used instead of a stopwatch for virtual time progression.</param>
|
||||
/// <param name="audio">Audio manager. Required if a reference clock isn't provided.</param>
|
||||
/// <param name="length">The length of the returned virtual track.</param>
|
||||
public ClockBackedTestWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock referenceClock, AudioManager audio, double length = 60000)
|
||||
: base(beatmap)
|
||||
{
|
||||
if (referenceClock != null)
|
||||
{
|
||||
store = new TrackVirtualStore(referenceClock);
|
||||
audio.AddItem(store);
|
||||
track = store.GetVirtual(length);
|
||||
}
|
||||
else
|
||||
track = audio?.Tracks.GetVirtual(length);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
store?.Dispose();
|
||||
}
|
||||
|
||||
protected override Track GetTrack() => track;
|
||||
|
||||
public class TrackVirtualStore : AudioCollectionManager<Track>, ITrackStore
|
||||
{
|
||||
private readonly IFrameBasedClock referenceClock;
|
||||
|
||||
public TrackVirtualStore(IFrameBasedClock referenceClock)
|
||||
{
|
||||
this.referenceClock = referenceClock;
|
||||
}
|
||||
|
||||
public Track Get(string name) => throw new NotImplementedException();
|
||||
|
||||
public Task<Track> GetAsync(string name) => throw new NotImplementedException();
|
||||
|
||||
public Stream GetStream(string name) => throw new NotImplementedException();
|
||||
|
||||
public IEnumerable<string> GetAvailableResources() => throw new NotImplementedException();
|
||||
|
||||
public Track GetVirtual(double length = Double.PositiveInfinity)
|
||||
{
|
||||
var track = new TrackVirtualManual(referenceClock) { Length = length };
|
||||
AddItem(track);
|
||||
return track;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A virtual track which tracks a reference clock.
|
||||
/// </summary>
|
||||
public class TrackVirtualManual : Track
|
||||
{
|
||||
private readonly IFrameBasedClock referenceClock;
|
||||
|
||||
private readonly ManualClock clock = new ManualClock();
|
||||
|
||||
private bool running;
|
||||
|
||||
/// <summary>
|
||||
/// Local offset added to the reference clock to resolve correct time.
|
||||
/// </summary>
|
||||
private double offset;
|
||||
|
||||
public TrackVirtualManual(IFrameBasedClock referenceClock)
|
||||
{
|
||||
this.referenceClock = referenceClock;
|
||||
Length = double.PositiveInfinity;
|
||||
}
|
||||
|
||||
public override bool Seek(double seek)
|
||||
{
|
||||
offset = MathHelper.Clamp(seek, 0, Length);
|
||||
lastReferenceTime = null;
|
||||
|
||||
return offset == seek;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
running = true;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Seek(0);
|
||||
base.Reset();
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
if (running)
|
||||
{
|
||||
running = false;
|
||||
// on stopping, the current value should be transferred out of the clock, as we can no longer rely on
|
||||
// the referenceClock (which will still be counting time).
|
||||
offset = clock.CurrentTime;
|
||||
lastReferenceTime = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsRunning => running;
|
||||
|
||||
private double? lastReferenceTime;
|
||||
|
||||
public override double CurrentTime => clock.CurrentTime;
|
||||
|
||||
protected override void UpdateState()
|
||||
{
|
||||
base.UpdateState();
|
||||
|
||||
if (running)
|
||||
{
|
||||
double refTime = referenceClock.CurrentTime;
|
||||
|
||||
if (!lastReferenceTime.HasValue)
|
||||
{
|
||||
// if the clock just started running, the current value should be transferred to the offset
|
||||
// (to zero the progression of time).
|
||||
offset -= refTime;
|
||||
}
|
||||
|
||||
lastReferenceTime = refTime;
|
||||
}
|
||||
|
||||
clock.CurrentTime = Math.Min((lastReferenceTime ?? 0) + offset, Length);
|
||||
|
||||
if (CurrentTime >= Length)
|
||||
{
|
||||
Stop();
|
||||
RaiseCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OsuTestSceneTestRunner : OsuGameBase, ITestSceneTestRunner
|
||||
{
|
||||
private TestSceneTestRunner.TestRunner runner;
|
||||
@ -93,17 +272,10 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
private class OsuTestBeatmap : BindableBeatmap
|
||||
{
|
||||
public OsuTestBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager)
|
||||
: base(defaultValue, audioManager)
|
||||
public OsuTestBeatmap(WorkingBeatmap defaultValue)
|
||||
: base(defaultValue)
|
||||
{
|
||||
}
|
||||
|
||||
public override BindableBeatmap GetBoundCopy()
|
||||
{
|
||||
var copy = new OsuTestBeatmap(Default, AudioManager);
|
||||
copy.BindTo(this);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user