2020-04-11 01:22:23 +00:00
|
|
|
// 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;
|
2021-12-23 09:33:17 +00:00
|
|
|
using System.Threading;
|
2020-04-11 01:22:23 +00:00
|
|
|
using System.Threading.Tasks;
|
|
|
|
using osu.Framework.Allocation;
|
|
|
|
using osu.Framework.Audio;
|
|
|
|
using osu.Framework.Audio.Sample;
|
|
|
|
using osu.Framework.Bindables;
|
2022-09-13 04:07:23 +00:00
|
|
|
using osu.Framework.Extensions.ObjectExtensions;
|
2022-07-29 16:29:11 +00:00
|
|
|
using osu.Framework.Graphics.Rendering;
|
2021-06-20 20:07:44 +00:00
|
|
|
using osu.Framework.Graphics.Shaders;
|
2020-04-11 01:22:23 +00:00
|
|
|
using osu.Framework.Graphics.Textures;
|
|
|
|
using osu.Framework.IO.Stores;
|
2020-12-21 04:35:46 +00:00
|
|
|
using osu.Framework.Platform;
|
2020-04-11 01:22:23 +00:00
|
|
|
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>
|
2023-03-28 05:15:19 +00:00
|
|
|
/// <remarks>
|
|
|
|
/// Reads textures from the "Textures" folder in ruleset resources.
|
|
|
|
/// If not available locally, lookups will fallback to the global texture store.
|
|
|
|
/// </remarks>
|
2020-04-11 02:13:04 +00:00
|
|
|
public TextureStore TextureStore { get; }
|
2020-04-11 01:22:23 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The sample store to be used for the ruleset.
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
2023-03-28 05:15:19 +00:00
|
|
|
/// Reads samples from the "Samples" folder in ruleset resources.
|
|
|
|
/// If not available locally, lookups will fallback to the global sample store.
|
2020-04-11 01:22:23 +00:00
|
|
|
/// </remarks>
|
2020-04-11 02:13:04 +00:00
|
|
|
public ISampleStore SampleStore { get; }
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2021-06-20 20:07:44 +00:00
|
|
|
/// <summary>
|
|
|
|
/// The shader manager to be used for the ruleset.
|
|
|
|
/// </summary>
|
2023-03-28 05:15:19 +00:00
|
|
|
/// <remarks>
|
|
|
|
/// Reads shaders from the "Shaders" folder in ruleset resources.
|
|
|
|
/// If not available locally, lookups will fallback to the global shader manager.
|
|
|
|
/// </remarks>
|
2021-06-20 20:07:44 +00:00
|
|
|
public ShaderManager ShaderManager { get; }
|
|
|
|
|
2020-04-11 01:22:23 +00:00
|
|
|
/// <summary>
|
2022-09-13 04:07:23 +00:00
|
|
|
/// The ruleset config manager. May be null if ruleset does not expose a configuration manager.
|
2020-04-11 01:22:23 +00:00
|
|
|
/// </summary>
|
2022-09-13 04:07:23 +00:00
|
|
|
public IRulesetConfigManager? RulesetConfigManager { get; }
|
2020-04-11 01:22:23 +00:00
|
|
|
|
|
|
|
public DrawableRulesetDependencies(Ruleset ruleset, IReadOnlyDependencyContainer parent)
|
|
|
|
: base(parent)
|
|
|
|
{
|
|
|
|
var resources = ruleset.CreateResourceStore();
|
|
|
|
|
2022-09-13 00:45:31 +00:00
|
|
|
var host = parent.Get<GameHost>();
|
2022-07-29 16:29:11 +00:00
|
|
|
|
2022-09-13 00:45:31 +00:00
|
|
|
TextureStore = new TextureStore(host.Renderer, parent.Get<GameHost>().CreateTextureLoaderStore(new NamespacedResourceStore<byte[]>(resources, @"Textures")));
|
|
|
|
CacheAs(TextureStore = new FallbackTextureStore(host.Renderer, TextureStore, parent.Get<TextureStore>()));
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2022-09-13 00:45:31 +00:00
|
|
|
SampleStore = parent.Get<AudioManager>().GetSampleStore(new NamespacedResourceStore<byte[]>(resources, @"Samples"));
|
|
|
|
SampleStore.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY;
|
|
|
|
CacheAs(SampleStore = new FallbackSampleStore(SampleStore, parent.Get<ISampleStore>()));
|
2021-06-20 20:07:44 +00:00
|
|
|
|
2023-03-28 05:53:08 +00:00
|
|
|
CacheAs(ShaderManager = new RulesetShaderManager(host.Renderer, new NamespacedResourceStore<byte[]>(resources, @"Shaders"), parent.Get<ShaderManager>()));
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2021-12-23 18:02:10 +00:00
|
|
|
RulesetConfigManager = parent.Get<IRulesetConfigCache>().GetConfigFor(ruleset);
|
2020-04-11 01:22:23 +00:00
|
|
|
if (RulesetConfigManager != null)
|
|
|
|
Cache(RulesetConfigManager);
|
|
|
|
}
|
|
|
|
|
|
|
|
#region Disposal
|
|
|
|
|
|
|
|
~DrawableRulesetDependencies()
|
|
|
|
{
|
2021-03-02 07:07:51 +00:00
|
|
|
// required to potentially clean up sample store from audio hierarchy.
|
2020-04-11 01:22:23 +00:00
|
|
|
Dispose(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
Dispose(true);
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool isDisposed;
|
|
|
|
|
|
|
|
protected void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
if (isDisposed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
isDisposed = true;
|
|
|
|
|
2023-04-06 08:40:04 +00:00
|
|
|
if (SampleStore.IsNotNull()) SampleStore.Dispose();
|
2022-09-13 04:07:23 +00:00
|
|
|
if (TextureStore.IsNotNull()) TextureStore.Dispose();
|
|
|
|
if (ShaderManager.IsNotNull()) ShaderManager.Dispose();
|
2020-04-11 01:22:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
/// <summary>
|
|
|
|
/// A sample store which adds a fallback source and prevents disposal of the fallback source.
|
|
|
|
/// </summary>
|
|
|
|
private class FallbackSampleStore : ISampleStore
|
2020-04-11 01:22:23 +00:00
|
|
|
{
|
2020-09-24 05:33:43 +00:00
|
|
|
private readonly ISampleStore primary;
|
|
|
|
private readonly ISampleStore fallback;
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public FallbackSampleStore(ISampleStore primary, ISampleStore fallback)
|
|
|
|
{
|
|
|
|
this.primary = primary;
|
|
|
|
this.fallback = fallback;
|
|
|
|
}
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2021-01-19 08:11:40 +00:00
|
|
|
public Sample Get(string name) => primary.Get(name) ?? fallback.Get(name);
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2022-11-13 17:47:28 +00:00
|
|
|
public async Task<Sample> GetAsync(string name, CancellationToken cancellationToken = default)
|
|
|
|
{
|
|
|
|
return await primary.GetAsync(name, cancellationToken).ConfigureAwait(false)
|
|
|
|
?? await fallback.GetAsync(name, cancellationToken).ConfigureAwait(false);
|
|
|
|
}
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public Stream GetStream(string name) => primary.GetStream(name) ?? fallback.GetStream(name);
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public IEnumerable<string> GetAvailableResources() => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2021-02-18 06:42:26 +00:00
|
|
|
public void AddAdjustment(AdjustableProperty type, IBindable<double> adjustBindable) => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2021-02-18 06:42:26 +00:00
|
|
|
public void RemoveAdjustment(AdjustableProperty type, IBindable<double> adjustBindable) => throw new NotSupportedException();
|
2021-02-18 09:52:34 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public void RemoveAllAdjustments(AdjustableProperty type) => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2021-02-22 09:31:27 +00:00
|
|
|
public void BindAdjustments(IAggregateAudioAdjustment component) => throw new NotImplementedException();
|
|
|
|
|
|
|
|
public void UnbindAdjustments(IAggregateAudioAdjustment component) => throw new NotImplementedException();
|
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public BindableNumber<double> Volume => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public BindableNumber<double> Balance => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public BindableNumber<double> Frequency => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public BindableNumber<double> Tempo => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public IBindable<double> AggregateVolume => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public IBindable<double> AggregateBalance => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public IBindable<double> AggregateFrequency => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public IBindable<double> AggregateTempo => throw new NotSupportedException();
|
2020-04-11 01:22:23 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public int PlaybackConcurrency
|
|
|
|
{
|
|
|
|
get => throw new NotSupportedException();
|
|
|
|
set => throw new NotSupportedException();
|
|
|
|
}
|
2020-09-24 05:29:44 +00:00
|
|
|
|
2023-01-28 20:16:22 +00:00
|
|
|
public void AddExtension(string extension) => throw new NotSupportedException();
|
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public void Dispose()
|
|
|
|
{
|
2022-09-13 04:07:23 +00:00
|
|
|
if (primary.IsNotNull()) primary.Dispose();
|
2020-09-24 05:33:43 +00:00
|
|
|
}
|
|
|
|
}
|
2020-09-24 05:29:44 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
/// <summary>
|
|
|
|
/// A texture store which adds a fallback source and prevents disposal of the fallback source.
|
|
|
|
/// </summary>
|
|
|
|
private class FallbackTextureStore : TextureStore
|
2020-09-24 05:29:44 +00:00
|
|
|
{
|
2020-09-24 05:33:43 +00:00
|
|
|
private readonly TextureStore primary;
|
|
|
|
private readonly TextureStore fallback;
|
2020-09-24 05:29:44 +00:00
|
|
|
|
2022-08-02 10:50:57 +00:00
|
|
|
public FallbackTextureStore(IRenderer renderer, TextureStore primary, TextureStore fallback)
|
|
|
|
: base(renderer)
|
2020-09-24 05:33:43 +00:00
|
|
|
{
|
|
|
|
this.primary = primary;
|
|
|
|
this.fallback = fallback;
|
|
|
|
}
|
2020-09-24 05:29:44 +00:00
|
|
|
|
2020-09-24 05:33:43 +00:00
|
|
|
public override Texture Get(string name, WrapMode wrapModeS, WrapMode wrapModeT)
|
|
|
|
=> primary.Get(name, wrapModeS, wrapModeT) ?? fallback.Get(name, wrapModeS, wrapModeT);
|
|
|
|
|
|
|
|
protected override void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
base.Dispose(disposing);
|
2022-09-13 04:07:23 +00:00
|
|
|
if (primary.IsNotNull()) primary.Dispose();
|
2020-09-24 05:33:43 +00:00
|
|
|
}
|
2020-04-11 01:22:23 +00:00
|
|
|
}
|
2021-06-20 20:07:44 +00:00
|
|
|
|
2023-03-28 05:53:08 +00:00
|
|
|
private class RulesetShaderManager : ShaderManager
|
2021-06-20 20:07:44 +00:00
|
|
|
{
|
2023-03-28 05:53:08 +00:00
|
|
|
private readonly ShaderManager parent;
|
2021-06-20 20:07:44 +00:00
|
|
|
|
2023-03-28 05:53:08 +00:00
|
|
|
public RulesetShaderManager(IRenderer renderer, NamespacedResourceStore<byte[]> rulesetResources, ShaderManager parent)
|
|
|
|
: base(renderer, rulesetResources)
|
2021-06-20 20:07:44 +00:00
|
|
|
{
|
2023-03-28 05:53:08 +00:00
|
|
|
this.parent = parent;
|
2021-06-20 20:07:44 +00:00
|
|
|
}
|
|
|
|
|
2023-04-18 02:31:56 +00:00
|
|
|
public override IShader? GetCachedShader(string vertex, string fragment) => base.GetCachedShader(vertex, fragment) ?? parent.GetCachedShader(vertex, fragment);
|
2023-04-03 09:04:33 +00:00
|
|
|
|
2023-04-18 02:31:56 +00:00
|
|
|
public override IShaderPart? GetCachedShaderPart(string name) => base.GetCachedShaderPart(name) ?? parent.GetCachedShaderPart(name);
|
|
|
|
|
|
|
|
public override byte[]? GetRawData(string fileName) => base.GetRawData(fileName) ?? parent.GetRawData(fileName);
|
2021-06-20 20:07:44 +00:00
|
|
|
}
|
2020-04-11 01:22:23 +00:00
|
|
|
}
|
|
|
|
}
|