mirror of
https://github.com/ppy/osu
synced 2025-02-07 13:51:59 +00:00
Merge pull request #8709 from frenzibyte/cache-ruleset-dependencies-for-tests
Cache ruleset dependencies for test scenes that require it
This commit is contained in:
commit
83f26bcb81
@ -87,11 +87,11 @@ namespace osu.Game.Tests.Gameplay
|
||||
this.resourceName = resourceName;
|
||||
}
|
||||
|
||||
public byte[] Get(string name) => name == resourceName ? TestResources.GetStore().Get("Resources/test-sample.mp3") : null;
|
||||
public byte[] Get(string name) => name == resourceName ? TestResources.GetStore().Get("Resources/Samples/test-sample.mp3") : null;
|
||||
|
||||
public Task<byte[]> GetAsync(string name) => name == resourceName ? TestResources.GetStore().GetAsync("Resources/test-sample.mp3") : null;
|
||||
public Task<byte[]> GetAsync(string name) => name == resourceName ? TestResources.GetStore().GetAsync("Resources/Samples/test-sample.mp3") : null;
|
||||
|
||||
public Stream GetStream(string name) => name == resourceName ? TestResources.GetStore().GetStream("Resources/test-sample.mp3") : null;
|
||||
public Stream GetStream(string name) => name == resourceName ? TestResources.GetStore().GetStream("Resources/Samples/test-sample.mp3") : null;
|
||||
|
||||
public IEnumerable<string> GetAvailableResources() => new[] { resourceName };
|
||||
|
||||
|
BIN
osu.Game.Tests/Resources/Textures/test-image.png
Normal file
BIN
osu.Game.Tests/Resources/Textures/test-image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
95
osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs
Normal file
95
osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs
Normal file
@ -0,0 +1,95 @@
|
||||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Configuration.Tracking;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Tests.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// A test scene ensuring the dependencies for the
|
||||
/// provided ruleset below are cached at the base implementation.
|
||||
/// </summary>
|
||||
[HeadlessTest]
|
||||
public class TestSceneRulesetDependencies : OsuTestScene
|
||||
{
|
||||
protected override Ruleset CreateRuleset() => new TestRuleset();
|
||||
|
||||
[Test]
|
||||
public void TestRetrieveTexture()
|
||||
{
|
||||
AddAssert("ruleset texture retrieved", () =>
|
||||
Dependencies.Get<TextureStore>().Get(@"test-image") != null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRetrieveSample()
|
||||
{
|
||||
AddAssert("ruleset sample retrieved", () =>
|
||||
Dependencies.Get<ISampleStore>().Get(@"test-sample") != null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestResolveConfigManager()
|
||||
{
|
||||
AddAssert("ruleset config resolved", () =>
|
||||
Dependencies.Get<TestRulesetConfigManager>() != null);
|
||||
}
|
||||
|
||||
private class TestRuleset : Ruleset
|
||||
{
|
||||
public override string Description => string.Empty;
|
||||
public override string ShortName => string.Empty;
|
||||
|
||||
public TestRuleset()
|
||||
{
|
||||
// temporary ID to let RulesetConfigCache pass our
|
||||
// config manager to the ruleset dependencies.
|
||||
RulesetInfo.ID = -1;
|
||||
}
|
||||
|
||||
public override IResourceStore<byte[]> CreateResourceStore() => new NamespacedResourceStore<byte[]>(TestResources.GetStore(), @"Resources");
|
||||
public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new TestRulesetConfigManager();
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type) => Array.Empty<Mod>();
|
||||
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => null;
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null;
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => null;
|
||||
}
|
||||
|
||||
private class TestRulesetConfigManager : IRulesetConfigManager
|
||||
{
|
||||
public void Load()
|
||||
{
|
||||
}
|
||||
|
||||
public bool Save() => true;
|
||||
|
||||
public TrackedSettings CreateTrackedSettings() => new TrackedSettings();
|
||||
|
||||
public void LoadInto(TrackedSettings settings)
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,20 +11,13 @@ using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Input.Handlers;
|
||||
@ -63,10 +56,6 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
private readonly Lazy<Playfield> playfield;
|
||||
|
||||
private TextureStore textureStore;
|
||||
|
||||
private ISampleStore localSampleStore;
|
||||
|
||||
/// <summary>
|
||||
/// The playfield.
|
||||
/// </summary>
|
||||
@ -113,6 +102,8 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
private OnScreenDisplay onScreenDisplay;
|
||||
|
||||
private DrawableRulesetDependencies dependencies;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a ruleset visualisation for the provided ruleset and beatmap.
|
||||
/// </summary>
|
||||
@ -147,30 +138,13 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
dependencies = new DrawableRulesetDependencies(Ruleset, base.CreateChildDependencies(parent));
|
||||
|
||||
var resources = Ruleset.CreateResourceStore();
|
||||
|
||||
if (resources != null)
|
||||
{
|
||||
textureStore = new TextureStore(new TextureLoaderStore(new NamespacedResourceStore<byte[]>(resources, "Textures")));
|
||||
textureStore.AddStore(dependencies.Get<TextureStore>());
|
||||
dependencies.Cache(textureStore);
|
||||
|
||||
localSampleStore = dependencies.Get<AudioManager>().GetSampleStore(new NamespacedResourceStore<byte[]>(resources, "Samples"));
|
||||
localSampleStore.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY;
|
||||
dependencies.CacheAs<ISampleStore>(new FallbackSampleStore(localSampleStore, dependencies.Get<ISampleStore>()));
|
||||
}
|
||||
Config = dependencies.RulesetConfigManager;
|
||||
|
||||
onScreenDisplay = dependencies.Get<OnScreenDisplay>();
|
||||
|
||||
Config = dependencies.Get<RulesetConfigCache>().GetConfigFor(Ruleset);
|
||||
|
||||
if (Config != null)
|
||||
{
|
||||
dependencies.Cache(Config);
|
||||
onScreenDisplay?.BeginTracking(this, Config);
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
@ -362,13 +336,14 @@ namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
localSampleStore?.Dispose();
|
||||
|
||||
if (Config != null)
|
||||
{
|
||||
onScreenDisplay?.StopTracking(this, Config);
|
||||
Config = null;
|
||||
}
|
||||
|
||||
// Dispose the components created by this dependency container.
|
||||
dependencies?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -524,62 +499,4 @@ namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A sample store which adds a fallback source.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a temporary implementation to workaround ISampleStore limitations.
|
||||
/// </remarks>
|
||||
public class FallbackSampleStore : ISampleStore
|
||||
{
|
||||
private readonly ISampleStore primary;
|
||||
private readonly ISampleStore secondary;
|
||||
|
||||
public FallbackSampleStore(ISampleStore primary, ISampleStore secondary)
|
||||
{
|
||||
this.primary = primary;
|
||||
this.secondary = secondary;
|
||||
}
|
||||
|
||||
public SampleChannel Get(string name) => primary.Get(name) ?? secondary.Get(name);
|
||||
|
||||
public Task<SampleChannel> GetAsync(string name) => primary.GetAsync(name) ?? secondary.GetAsync(name);
|
||||
|
||||
public Stream GetStream(string name) => primary.GetStream(name) ?? secondary.GetStream(name);
|
||||
|
||||
public IEnumerable<string> GetAvailableResources() => throw new NotSupportedException();
|
||||
|
||||
public void AddAdjustment(AdjustableProperty type, BindableNumber<double> adjustBindable) => throw new NotSupportedException();
|
||||
|
||||
public void RemoveAdjustment(AdjustableProperty type, BindableNumber<double> adjustBindable) => throw new NotSupportedException();
|
||||
|
||||
public BindableNumber<double> Volume => throw new NotSupportedException();
|
||||
|
||||
public BindableNumber<double> Balance => throw new NotSupportedException();
|
||||
|
||||
public BindableNumber<double> Frequency => throw new NotSupportedException();
|
||||
|
||||
public BindableNumber<double> Tempo => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> GetAggregate(AdjustableProperty type) => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> AggregateVolume => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> AggregateBalance => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> AggregateFrequency => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> AggregateTempo => throw new NotSupportedException();
|
||||
|
||||
public int PlaybackConcurrency
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
148
osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs
Normal file
148
osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs
Normal file
@ -0,0 +1,148 @@
|
||||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
|
||||
namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
public class DrawableRulesetDependencies : DependencyContainer, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The texture store to be used for the ruleset.
|
||||
/// </summary>
|
||||
public TextureStore TextureStore { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The sample store to be used for the ruleset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the local sample store pointing to the ruleset sample resources,
|
||||
/// the cached sample store (<see cref="FallbackSampleStore"/>) retrieves from
|
||||
/// this store and falls back to the parent store if this store doesn't have the requested sample.
|
||||
/// </remarks>
|
||||
public ISampleStore SampleStore { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The ruleset config manager.
|
||||
/// </summary>
|
||||
public IRulesetConfigManager RulesetConfigManager { get; private set; }
|
||||
|
||||
public DrawableRulesetDependencies(Ruleset ruleset, IReadOnlyDependencyContainer parent)
|
||||
: base(parent)
|
||||
{
|
||||
var resources = ruleset.CreateResourceStore();
|
||||
|
||||
if (resources != null)
|
||||
{
|
||||
TextureStore = new TextureStore(new TextureLoaderStore(new NamespacedResourceStore<byte[]>(resources, @"Textures")));
|
||||
TextureStore.AddStore(parent.Get<TextureStore>());
|
||||
Cache(TextureStore);
|
||||
|
||||
SampleStore = parent.Get<AudioManager>().GetSampleStore(new NamespacedResourceStore<byte[]>(resources, @"Samples"));
|
||||
SampleStore.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY;
|
||||
CacheAs<ISampleStore>(new FallbackSampleStore(SampleStore, parent.Get<ISampleStore>()));
|
||||
}
|
||||
|
||||
RulesetConfigManager = parent.Get<RulesetConfigCache>().GetConfigFor(ruleset);
|
||||
if (RulesetConfigManager != null)
|
||||
Cache(RulesetConfigManager);
|
||||
}
|
||||
|
||||
#region Disposal
|
||||
|
||||
~DrawableRulesetDependencies()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private bool isDisposed;
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (isDisposed)
|
||||
return;
|
||||
|
||||
isDisposed = true;
|
||||
|
||||
SampleStore?.Dispose();
|
||||
RulesetConfigManager = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A sample store which adds a fallback source.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a temporary implementation to workaround ISampleStore limitations.
|
||||
/// </remarks>
|
||||
public class FallbackSampleStore : ISampleStore
|
||||
{
|
||||
private readonly ISampleStore primary;
|
||||
private readonly ISampleStore secondary;
|
||||
|
||||
public FallbackSampleStore(ISampleStore primary, ISampleStore secondary)
|
||||
{
|
||||
this.primary = primary;
|
||||
this.secondary = secondary;
|
||||
}
|
||||
|
||||
public SampleChannel Get(string name) => primary.Get(name) ?? secondary.Get(name);
|
||||
|
||||
public Task<SampleChannel> GetAsync(string name) => primary.GetAsync(name) ?? secondary.GetAsync(name);
|
||||
|
||||
public Stream GetStream(string name) => primary.GetStream(name) ?? secondary.GetStream(name);
|
||||
|
||||
public IEnumerable<string> GetAvailableResources() => throw new NotSupportedException();
|
||||
|
||||
public void AddAdjustment(AdjustableProperty type, BindableNumber<double> adjustBindable) => throw new NotSupportedException();
|
||||
|
||||
public void RemoveAdjustment(AdjustableProperty type, BindableNumber<double> adjustBindable) => throw new NotSupportedException();
|
||||
|
||||
public BindableNumber<double> Volume => throw new NotSupportedException();
|
||||
|
||||
public BindableNumber<double> Balance => throw new NotSupportedException();
|
||||
|
||||
public BindableNumber<double> Frequency => throw new NotSupportedException();
|
||||
|
||||
public BindableNumber<double> Tempo => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> GetAggregate(AdjustableProperty type) => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> AggregateVolume => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> AggregateBalance => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> AggregateFrequency => throw new NotSupportedException();
|
||||
|
||||
public IBindable<double> AggregateTempo => throw new NotSupportedException();
|
||||
|
||||
public int PlaybackConcurrency
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Storyboards;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
@ -38,6 +39,8 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
protected new OsuScreenDependencies Dependencies { get; private set; }
|
||||
|
||||
private DrawableRulesetDependencies rulesetDependencies;
|
||||
|
||||
private Lazy<Storage> localStorage;
|
||||
protected Storage LocalStorage => localStorage.Value;
|
||||
|
||||
@ -66,7 +69,13 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
Dependencies = new OsuScreenDependencies(false, base.CreateChildDependencies(parent));
|
||||
var baseDependencies = base.CreateChildDependencies(parent);
|
||||
|
||||
var providedRuleset = CreateRuleset();
|
||||
if (providedRuleset != null)
|
||||
baseDependencies = rulesetDependencies = new DrawableRulesetDependencies(providedRuleset, baseDependencies);
|
||||
|
||||
Dependencies = new OsuScreenDependencies(false, baseDependencies);
|
||||
|
||||
Beatmap = Dependencies.Beatmap;
|
||||
Beatmap.SetDefault();
|
||||
@ -153,6 +162,8 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
rulesetDependencies?.Dispose();
|
||||
|
||||
if (Beatmap?.Value.TrackLoaded == true)
|
||||
Beatmap.Value.Track.Stop();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user