From 09ec49e6fa68e714730043d9ec723bc352456017 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Mar 2022 18:30:54 +0900 Subject: [PATCH 01/21] Rename realm-backed resource store in preparation for non-legacy usage --- osu.Game/Skinning/DefaultLegacySkin.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- ...sedSkinResourceStore.cs => RealmBackedResourceStore.cs} | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) rename osu.Game/Skinning/{LegacyDatabasedSkinResourceStore.cs => RealmBackedResourceStore.cs} (83%) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index c7033d37dc..3a8464879a 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -34,7 +34,7 @@ namespace osu.Game.Skinning resources, // A default legacy skin may still have a skin.ini if it is modified by the user. // We must specify the stream directly as we are redirecting storage to the osu-resources location for other files. - new LegacyDatabasedSkinResourceStore(skin, resources.Files).GetStream("skin.ini") + new RealmBackedResourceStore(skin, resources.Files).GetStream("skin.ini") ) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 359d9e5624..9d71fff92f 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -51,7 +51,7 @@ namespace osu.Game.Skinning [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] public LegacySkin(SkinInfo skin, IStorageResourceProvider resources) - : this(skin, new LegacyDatabasedSkinResourceStore(skin, resources.Files), resources, "skin.ini") + : this(skin, new RealmBackedResourceStore(skin, resources.Files), resources, "skin.ini") { } diff --git a/osu.Game/Skinning/LegacyDatabasedSkinResourceStore.cs b/osu.Game/Skinning/RealmBackedResourceStore.cs similarity index 83% rename from osu.Game/Skinning/LegacyDatabasedSkinResourceStore.cs rename to osu.Game/Skinning/RealmBackedResourceStore.cs index cd90fea9bb..93ffbe4f44 100644 --- a/osu.Game/Skinning/LegacyDatabasedSkinResourceStore.cs +++ b/osu.Game/Skinning/RealmBackedResourceStore.cs @@ -4,21 +4,22 @@ using System.Collections.Generic; using osu.Framework.Extensions; using osu.Framework.IO.Stores; +using osu.Game.Database; using osu.Game.Extensions; namespace osu.Game.Skinning { - public class LegacyDatabasedSkinResourceStore : ResourceStore + public class RealmBackedResourceStore : ResourceStore { private readonly Dictionary fileToStoragePathMapping = new Dictionary(); - public LegacyDatabasedSkinResourceStore(SkinInfo source, IResourceStore underlyingStore) + public RealmBackedResourceStore(IHasRealmFiles source, IResourceStore underlyingStore) : base(underlyingStore) { initialiseFileCache(source); } - private void initialiseFileCache(SkinInfo source) + private void initialiseFileCache(IHasRealmFiles source) { fileToStoragePathMapping.Clear(); foreach (var f in source.Files) From 5c4a74378dec7f2b64f5de49abde8779c6793486 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Mar 2022 18:36:42 +0900 Subject: [PATCH 02/21] Remove `Textures` and `Samples` initialisation to `Skin` --- osu.Game/Skinning/LegacySkin.cs | 25 --------- osu.Game/Skinning/Skin.cs | 99 ++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 71 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 9d71fff92f..5533615568 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -27,12 +27,6 @@ namespace osu.Game.Skinning { public class LegacySkin : Skin { - [CanBeNull] - protected TextureStore Textures; - - [CanBeNull] - protected ISampleStore Samples; - /// /// Whether texture for the keys exists. /// Used to determine if the mania ruleset is skinned. @@ -77,18 +71,6 @@ namespace osu.Game.Skinning protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] Stream configurationStream) : base(skin, resources, configurationStream) { - if (storage != null) - { - var samples = resources?.AudioManager?.GetSampleStore(storage); - if (samples != null) - samples.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; - - Samples = samples; - Textures = new TextureStore(resources?.CreateTextureLoaderStore(storage)); - - (storage as ResourceStore)?.AddExtension("ogg"); - } - // todo: this shouldn't really be duplicated here (from ManiaLegacySkinTransformer). we need to come up with a better solution. hasKeyTexture = new Lazy(() => this.GetAnimation( lookupForMania(new LegacyManiaSkinConfigurationLookup(4, LegacyManiaSkinConfigurationLookups.KeyImage, 0))?.Value ?? "mania-key1", true, @@ -551,12 +533,5 @@ namespace osu.Game.Skinning // Fall back to using the last piece for components coming from lazer (e.g. "Gameplay/osu/approachcircle" -> "approachcircle"). yield return componentName.Split('/').Last(); } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - Textures?.Dispose(); - Samples?.Dispose(); - } } } diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 931bdfed48..d1ea7aa300 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -16,7 +16,6 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Database; -using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Screens.Play.HUD; @@ -24,8 +23,19 @@ namespace osu.Game.Skinning { public abstract class Skin : IDisposable, ISkin { + /// + /// A texture store which can be used to perform user file loops for this skin. + /// + [CanBeNull] + protected TextureStore Textures { get; set; } + + /// + /// A sample store which can be used to perform user file loops for this skin. + /// + [CanBeNull] + protected ISampleStore Samples { get; set; } + public readonly Live SkinInfo; - private readonly IStorageResourceProvider resources; public SkinConfiguration Configuration { get; set; } @@ -41,16 +51,30 @@ namespace osu.Game.Skinning public abstract IBindable GetConfig(TLookup lookup); + private readonly RealmBackedResourceStore skinStorage; + protected Skin(SkinInfo skin, IStorageResourceProvider resources, [CanBeNull] Stream configurationStream = null) { - SkinInfo = resources?.RealmAccess != null - ? skin.ToLive(resources.RealmAccess) - // This path should only be used in some tests. - : skin.ToLiveUnmanaged(); + if (resources.RealmAccess != null) + { + SkinInfo = skin.ToLive(resources.RealmAccess); + skinStorage = new RealmBackedResourceStore(skin, resources.Files); - this.resources = resources; + var samples = resources?.AudioManager?.GetSampleStore(skinStorage); + if (samples != null) + samples.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; - configurationStream ??= getConfigurationStream(); + Samples = samples; + Textures = new TextureStore(resources?.CreateTextureLoaderStore(skinStorage)); + + skinStorage.AddExtension("ogg"); + } + else + { + SkinInfo = skin.ToLiveUnmanaged(); + } + + configurationStream ??= skinStorage?.GetStream(@"skin.ini"); if (configurationStream != null) // stream will be closed after use by LineBufferedReader. @@ -59,40 +83,30 @@ namespace osu.Game.Skinning Configuration = new SkinConfiguration(); // skininfo files may be null for default skin. - SkinInfo.PerformRead(s => + foreach (SkinnableTarget skinnableTarget in Enum.GetValues(typeof(SkinnableTarget))) { - // we may want to move this to some kind of async operation in the future. - foreach (SkinnableTarget skinnableTarget in Enum.GetValues(typeof(SkinnableTarget))) + string filename = $"{skinnableTarget}.json"; + + byte[] bytes = skinStorage?.Get(filename); + + if (bytes == null) + continue; + + try { - string filename = $"{skinnableTarget}.json"; + string jsonContent = Encoding.UTF8.GetString(bytes); + var deserializedContent = JsonConvert.DeserializeObject>(jsonContent); - // skininfo files may be null for default skin. - var fileInfo = s.Files.FirstOrDefault(f => f.Filename == filename); - - if (fileInfo == null) + if (deserializedContent == null) continue; - byte[] bytes = resources?.Files.Get(fileInfo.File.GetStoragePath()); - - if (bytes == null) - continue; - - try - { - string jsonContent = Encoding.UTF8.GetString(bytes); - var deserializedContent = JsonConvert.DeserializeObject>(jsonContent); - - if (deserializedContent == null) - continue; - - DrawableComponentInfo[skinnableTarget] = deserializedContent.ToArray(); - } - catch (Exception ex) - { - Logger.Error(ex, "Failed to load skin configuration."); - } + DrawableComponentInfo[skinnableTarget] = deserializedContent.ToArray(); } - }); + catch (Exception ex) + { + Logger.Error(ex, "Failed to load skin configuration."); + } + } } protected virtual void ParseConfigurationStream(Stream stream) @@ -101,16 +115,6 @@ namespace osu.Game.Skinning Configuration = new LegacySkinDecoder().Decode(reader); } - private Stream getConfigurationStream() - { - string path = SkinInfo.PerformRead(s => s.Files.SingleOrDefault(f => f.Filename.Equals(@"skin.ini", StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath()); - - if (string.IsNullOrEmpty(path)) - return null; - - return resources?.Files.GetStream(path); - } - /// /// Remove all stored customisations for the provided target. /// @@ -168,6 +172,9 @@ namespace osu.Game.Skinning return; isDisposed = true; + + Textures?.Dispose(); + Samples?.Dispose(); } #endregion From b4d89b4e313863e6dec8ce85a4948ef4d9321b63 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Mar 2022 18:42:45 +0900 Subject: [PATCH 03/21] Replace duplicate `LegacySkinResourceStore` class with `RealmBackedResourceStore` --- osu.Game/Skinning/LegacyBeatmapSkin.cs | 2 +- osu.Game/Skinning/LegacySkinResourceStore.cs | 39 -------------------- 2 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 osu.Game/Skinning/LegacySkinResourceStore.cs diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index f80a980351..2ddf79ed5a 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -21,7 +21,7 @@ namespace osu.Game.Skinning protected override bool UseCustomSampleBanks => true; public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, IResourceStore storage, IStorageResourceProvider resources) - : base(createSkinInfo(beatmapInfo), new LegacySkinResourceStore(beatmapInfo.BeatmapSet, storage), resources, beatmapInfo.Path) + : base(createSkinInfo(beatmapInfo), new RealmBackedResourceStore(beatmapInfo.BeatmapSet, storage), resources, beatmapInfo.Path) { // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) Configuration.AllowDefaultComboColoursFallback = false; diff --git a/osu.Game/Skinning/LegacySkinResourceStore.cs b/osu.Game/Skinning/LegacySkinResourceStore.cs deleted file mode 100644 index 2487a469c8..0000000000 --- a/osu.Game/Skinning/LegacySkinResourceStore.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) ppy Pty Ltd . 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.Linq; -using osu.Framework.Extensions; -using osu.Framework.IO.Stores; -using osu.Game.Database; -using osu.Game.Extensions; - -namespace osu.Game.Skinning -{ - public class LegacySkinResourceStore : ResourceStore - { - private readonly IHasNamedFiles source; - - public LegacySkinResourceStore(IHasNamedFiles source, IResourceStore underlyingStore) - : base(underlyingStore) - { - this.source = source; - } - - protected override IEnumerable GetFilenames(string name) - { - foreach (string filename in base.GetFilenames(name)) - { - string path = getPathForFile(filename.ToStandardisedPath()); - if (path != null) - yield return path; - } - } - - private string getPathForFile(string filename) => - source.Files.FirstOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath(); - - public override IEnumerable GetAvailableResources() => source.Files.Select(f => f.Filename); - } -} From 35d2f973a39b533ed1cb7392d31d1d8299e9b0c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Mar 2022 19:07:05 +0900 Subject: [PATCH 04/21] Prefer provided resource store over realm backed to keep tests working --- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Skinning/Skin.cs | 39 +++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 5533615568..84844c4502 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -69,7 +69,7 @@ namespace osu.Game.Skinning /// Access to raw game resources. /// An optional stream containing the contents of a skin.ini file. protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] Stream configurationStream) - : base(skin, resources, configurationStream) + : base(skin, resources, storage, configurationStream) { // todo: this shouldn't really be duplicated here (from ManiaLegacySkinTransformer). we need to come up with a better solution. hasKeyTexture = new Lazy(() => this.GetAnimation( diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index d1ea7aa300..a47da70cd6 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -13,6 +13,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Database; @@ -51,30 +52,36 @@ namespace osu.Game.Skinning public abstract IBindable GetConfig(TLookup lookup); - private readonly RealmBackedResourceStore skinStorage; - - protected Skin(SkinInfo skin, IStorageResourceProvider resources, [CanBeNull] Stream configurationStream = null) + protected Skin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null, [CanBeNull] Stream configurationStream = null) { - if (resources.RealmAccess != null) + if (resources != null) { - SkinInfo = skin.ToLive(resources.RealmAccess); - skinStorage = new RealmBackedResourceStore(skin, resources.Files); + if (resources.RealmAccess != null) + { + SkinInfo = skin.ToLive(resources.RealmAccess); - var samples = resources?.AudioManager?.GetSampleStore(skinStorage); + if (storage == null) + { + var realmStorage = new RealmBackedResourceStore(skin, resources.Files); + realmStorage.AddExtension("ogg"); + + storage = realmStorage; + } + } + else + { + SkinInfo = skin.ToLiveUnmanaged(); + } + + var samples = resources.AudioManager?.GetSampleStore(storage); if (samples != null) samples.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; Samples = samples; - Textures = new TextureStore(resources?.CreateTextureLoaderStore(skinStorage)); - - skinStorage.AddExtension("ogg"); - } - else - { - SkinInfo = skin.ToLiveUnmanaged(); + Textures = new TextureStore(resources.CreateTextureLoaderStore(storage)); } - configurationStream ??= skinStorage?.GetStream(@"skin.ini"); + configurationStream ??= storage?.GetStream(@"skin.ini"); if (configurationStream != null) // stream will be closed after use by LineBufferedReader. @@ -87,7 +94,7 @@ namespace osu.Game.Skinning { string filename = $"{skinnableTarget}.json"; - byte[] bytes = skinStorage?.Get(filename); + byte[] bytes = storage?.Get(filename); if (bytes == null) continue; From a7f63fb034d5174dc7e51e46fdfce88a06a4a89c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Mar 2022 19:23:22 +0900 Subject: [PATCH 05/21] Make providing a custom `ResourceStore` to `LegacyBeatmapSkin` optional (for tests only) --- osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs | 2 +- osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs | 2 +- .../Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 2 +- osu.Game/Skinning/LegacyBeatmapSkin.cs | 5 +++-- osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs | 2 +- osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs | 2 +- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs index 71544e94f3..0c1981b35d 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs @@ -77,7 +77,7 @@ namespace osu.Game.Tests.Skins public class BeatmapSkinSource : LegacyBeatmapSkin { public BeatmapSkinSource() - : base(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, null, null) + : base(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, null) { } diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 870d6d8f57..d3cacaa88c 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -202,7 +202,7 @@ namespace osu.Game.Tests.Skins public class BeatmapSkinSource : LegacyBeatmapSkin { public BeatmapSkinSource() - : base(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, null, null) + : base(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, null) { } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs index eb1695b3df..53364b6d89 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestEmptyLegacyBeatmapSkinFallsBack() { - CreateSkinTest(DefaultSkin.CreateInfo(), () => new LegacyBeatmapSkin(new BeatmapInfo(), null, null)); + CreateSkinTest(DefaultSkin.CreateInfo(), () => new LegacyBeatmapSkin(new BeatmapInfo(), null)); AddUntilStep("wait for hud load", () => Player.ChildrenOfType().All(c => c.ComponentsLoaded)); AddAssert("hud from default skin", () => AssertComponentsFromExpectedSource(SkinnableTarget.MainHUDComponents, skinManager.CurrentSkin.Value)); } diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index d3f356bb24..7d28208157 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -225,7 +225,7 @@ namespace osu.Game.Beatmaps { try { - return new LegacyBeatmapSkin(BeatmapInfo, resources.Files, resources); + return new LegacyBeatmapSkin(BeatmapInfo, resources); } catch (Exception e) { diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 2ddf79ed5a..9b3548912c 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -20,8 +21,8 @@ namespace osu.Game.Skinning protected override bool AllowManiaSkin => false; protected override bool UseCustomSampleBanks => true; - public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, IResourceStore storage, IStorageResourceProvider resources) - : base(createSkinInfo(beatmapInfo), new RealmBackedResourceStore(beatmapInfo.BeatmapSet, storage), resources, beatmapInfo.Path) + public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null) + : base(createSkinInfo(beatmapInfo), storage ?? new RealmBackedResourceStore(beatmapInfo.BeatmapSet, resources.Files), resources, beatmapInfo.Path) { // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) Configuration.AllowDefaultComboColoursFallback = false; diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index 2a3e51b4f5..c13504c3de 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Beatmaps this.resources = resources; } - protected internal override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resourceStore, resources); + protected internal override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resources, resourceStore); } } } diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index 5c522058d9..fee650ded0 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Beatmaps public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.DarkGoldenrod; public TestBeatmapSkin(BeatmapInfo beatmapInfo, bool hasColours) - : base(beatmapInfo, new ResourceStore(), null) + : base(beatmapInfo, null, new ResourceStore()) { if (hasColours) { From e1236e07add705b02c145518169152e7c4e2fcd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 13:36:33 +0900 Subject: [PATCH 06/21] Fix extensions not being specified in time for realm file caching --- osu.Game/Skinning/LegacyBeatmapSkin.cs | 5 +++-- osu.Game/Skinning/RealmBackedResourceStore.cs | 9 +++++++- osu.Game/Skinning/Skin.cs | 21 ++++++++----------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 9b3548912c..d2428b0ccf 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -21,8 +21,9 @@ namespace osu.Game.Skinning protected override bool AllowManiaSkin => false; protected override bool UseCustomSampleBanks => true; - public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null) - : base(createSkinInfo(beatmapInfo), storage ?? new RealmBackedResourceStore(beatmapInfo.BeatmapSet, resources.Files), resources, beatmapInfo.Path) + public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null) + : base(createSkinInfo(beatmapInfo), storage ?? (resources != null ? new RealmBackedResourceStore(beatmapInfo.BeatmapSet, resources.Files, new[] { @"ogg" }) : null), resources, + beatmapInfo.Path) { // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) Configuration.AllowDefaultComboColoursFallback = false; diff --git a/osu.Game/Skinning/RealmBackedResourceStore.cs b/osu.Game/Skinning/RealmBackedResourceStore.cs index 93ffbe4f44..fc9036727f 100644 --- a/osu.Game/Skinning/RealmBackedResourceStore.cs +++ b/osu.Game/Skinning/RealmBackedResourceStore.cs @@ -13,9 +13,16 @@ namespace osu.Game.Skinning { private readonly Dictionary fileToStoragePathMapping = new Dictionary(); - public RealmBackedResourceStore(IHasRealmFiles source, IResourceStore underlyingStore) + public RealmBackedResourceStore(IHasRealmFiles source, IResourceStore underlyingStore, string[] extensions = null) : base(underlyingStore) { + // Must be initialised before the file cache. + if (extensions != null) + { + foreach (string extension in extensions) + AddExtension(extension); + } + initialiseFileCache(source); } diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index a47da70cd6..654c4e75f7 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -60,25 +60,22 @@ namespace osu.Game.Skinning { SkinInfo = skin.ToLive(resources.RealmAccess); - if (storage == null) - { - var realmStorage = new RealmBackedResourceStore(skin, resources.Files); - realmStorage.AddExtension("ogg"); - - storage = realmStorage; - } + storage ??= new RealmBackedResourceStore(skin, resources.Files, new[] { @"ogg" }); } else { SkinInfo = skin.ToLiveUnmanaged(); } - var samples = resources.AudioManager?.GetSampleStore(storage); - if (samples != null) - samples.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; + if (storage != null) + { + var samples = resources.AudioManager?.GetSampleStore(storage); + if (samples != null) + samples.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; - Samples = samples; - Textures = new TextureStore(resources.CreateTextureLoaderStore(storage)); + Samples = samples; + Textures = new TextureStore(resources.CreateTextureLoaderStore(storage)); + } } configurationStream ??= storage?.GetStream(@"skin.ini"); From 32e2cfb8ee710feabc140f1920c6b4e4c7150062 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 13:38:32 +0900 Subject: [PATCH 07/21] Leave realm resource store construction to base class --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 84844c4502..238cda1151 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -45,7 +45,7 @@ namespace osu.Game.Skinning [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] public LegacySkin(SkinInfo skin, IStorageResourceProvider resources) - : this(skin, new RealmBackedResourceStore(skin, resources.Files), resources, "skin.ini") + : this(skin, null, resources, "skin.ini") { } From 3c38b142281e2bb90023be88b96ce0ac38a8b745 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 13:14:56 +0900 Subject: [PATCH 08/21] Documentation improvements --- osu.Game/Skinning/LegacyBeatmapSkin.cs | 23 +++++++++++++++++++++-- osu.Game/Skinning/LegacySkin.cs | 5 +++-- osu.Game/Skinning/Skin.cs | 7 +++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index d2428b0ccf..7b8b659473 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -9,6 +9,7 @@ using osu.Framework.IO.Stores; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; +using osu.Game.Database; using osu.Game.IO; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Objects.Types; @@ -21,14 +22,28 @@ namespace osu.Game.Skinning protected override bool AllowManiaSkin => false; protected override bool UseCustomSampleBanks => true; + /// + /// Construct a new legacy beatmap skin instance. + /// + /// The model for this beatmap. + /// Access to raw game resources. + /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null) - : base(createSkinInfo(beatmapInfo), storage ?? (resources != null ? new RealmBackedResourceStore(beatmapInfo.BeatmapSet, resources.Files, new[] { @"ogg" }) : null), resources, + : base(createSkinInfo(beatmapInfo), storage ?? createRealmBackedStore(beatmapInfo, resources), resources, beatmapInfo.Path) { // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) Configuration.AllowDefaultComboColoursFallback = false; } + private static IResourceStore createRealmBackedStore(BeatmapInfo beatmapInfo, [CanBeNull] IStorageResourceProvider resources) + { + if (resources == null) + return null; + + return new RealmBackedResourceStore(beatmapInfo.BeatmapSet, resources.Files, new[] { @"ogg" }); + } + public override Drawable GetDrawableComponent(ISkinComponent component) { if (component is SkinnableTargetComponent targetComponent) @@ -79,6 +94,10 @@ namespace osu.Game.Skinning } private static SkinInfo createSkinInfo(BeatmapInfo beatmapInfo) => - new SkinInfo { Name = beatmapInfo.ToString(), Creator = beatmapInfo.Metadata.Author.Username ?? string.Empty }; + new SkinInfo + { + Name = beatmapInfo.ToString(), + Creator = beatmapInfo.Metadata.Author.Username ?? string.Empty + }; } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 238cda1151..1559b9af53 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Game.Audio; using osu.Game.Beatmaps.Formats; +using osu.Game.Database; using osu.Game.IO; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; @@ -53,7 +54,7 @@ namespace osu.Game.Skinning /// Construct a new legacy skin instance. /// /// The model for this skin. - /// A storage for looking up files within this skin using user-facing filenames. + /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. /// Access to raw game resources. /// The user-facing filename of the configuration file to be parsed. Can accept an .osu or skin.ini file. protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, string configurationFilename) @@ -65,7 +66,7 @@ namespace osu.Game.Skinning /// Construct a new legacy skin instance. /// /// The model for this skin. - /// A storage for looking up files within this skin using user-facing filenames. + /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. /// Access to raw game resources. /// An optional stream containing the contents of a skin.ini file. protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] Stream configurationStream) diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 654c4e75f7..84041deb1a 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -52,6 +52,13 @@ namespace osu.Game.Skinning public abstract IBindable GetConfig(TLookup lookup); + /// + /// Construct a new skin. + /// + /// The skin's metadata. Usually a live realm object. + /// Access to game-wide resources. + /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. + /// An optional stream which will be used to read the skin configuration. If null, the configuration will be retrieved from the storage using "skin.ini". protected Skin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null, [CanBeNull] Stream configurationStream = null) { if (resources != null) From 00aea9bef02f559210bef8ef898a07191c03f96e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 13:46:19 +0900 Subject: [PATCH 09/21] Only use legacy resources lookup for protected (aka default) skin --- osu.Game/Skinning/DefaultLegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 3a8464879a..7d7d2db7f3 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -30,7 +30,7 @@ namespace osu.Game.Skinning public DefaultLegacySkin(SkinInfo skin, IStorageResourceProvider resources) : base( skin, - new NamespacedResourceStore(resources.Resources, "Skins/Legacy"), + skin.Protected ? new NamespacedResourceStore(resources.Resources, "Skins/Legacy") : null, resources, // A default legacy skin may still have a skin.ini if it is modified by the user. // We must specify the stream directly as we are redirecting storage to the osu-resources location for other files. From a5acd38fd5b68a9e137a1852aa3683b94a60bd12 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 14:14:55 +0900 Subject: [PATCH 10/21] Fix `HitObjectSampleTest` adding null files to realm models --- osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index c13504c3de..630fbda688 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -96,12 +96,14 @@ namespace osu.Game.Tests.Beatmaps AddStep("setup skins", () => { userSkinInfo.Files.Clear(); - userSkinInfo.Files.Add(new RealmNamedFileUsage(new RealmFile { Hash = userFile }, userFile)); + if (!string.IsNullOrEmpty(userFile)) + userSkinInfo.Files.Add(new RealmNamedFileUsage(new RealmFile { Hash = userFile }, userFile)); Debug.Assert(beatmapInfo.BeatmapSet != null); beatmapInfo.BeatmapSet.Files.Clear(); - beatmapInfo.BeatmapSet.Files.Add(new RealmNamedFileUsage(new RealmFile { Hash = beatmapFile }, beatmapFile)); + if (!string.IsNullOrEmpty(beatmapFile)) + beatmapInfo.BeatmapSet.Files.Add(new RealmNamedFileUsage(new RealmFile { Hash = beatmapFile }, beatmapFile)); // Need to refresh the cached skin source to refresh the skin resource store. dependencies.SkinSource = new SkinProvidingContainer(Skin = new LegacySkin(userSkinInfo, this)); From e56d13d8be0ac9774aecf477cb43c24987295dd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 14:21:35 +0900 Subject: [PATCH 11/21] Fix realm backed store not being initialised for some tests --- osu.Game/Skinning/Skin.cs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 84041deb1a..4c2b58bbc2 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -63,26 +63,18 @@ namespace osu.Game.Skinning { if (resources != null) { - if (resources.RealmAccess != null) - { - SkinInfo = skin.ToLive(resources.RealmAccess); + SkinInfo = resources.RealmAccess != null + ? skin.ToLive(resources.RealmAccess) + : skin.ToLiveUnmanaged(); - storage ??= new RealmBackedResourceStore(skin, resources.Files, new[] { @"ogg" }); - } - else - { - SkinInfo = skin.ToLiveUnmanaged(); - } + storage ??= new RealmBackedResourceStore(skin, resources.Files, new[] { @"ogg" }); - if (storage != null) - { - var samples = resources.AudioManager?.GetSampleStore(storage); - if (samples != null) - samples.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; + var samples = resources.AudioManager?.GetSampleStore(storage); + if (samples != null) + samples.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; - Samples = samples; - Textures = new TextureStore(resources.CreateTextureLoaderStore(storage)); - } + Samples = samples; + Textures = new TextureStore(resources.CreateTextureLoaderStore(storage)); } configurationStream ??= storage?.GetStream(@"skin.ini"); From b48aa1d8fa934eaedb0c03f65e630d3217c94826 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 14:23:07 +0900 Subject: [PATCH 12/21] Ensure `HitObjectSampleTest`'s `TestWorkingBeatmap` provides the marking resource store correctly --- .../Tests/Beatmaps/HitObjectSampleTest.cs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index 630fbda688..4667a385b3 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -193,22 +193,32 @@ namespace osu.Game.Tests.Beatmaps } } - private class TestWorkingBeatmap : ClockBackedTestWorkingBeatmap + private class TestWorkingBeatmap : ClockBackedTestWorkingBeatmap, IStorageResourceProvider { private readonly BeatmapInfo skinBeatmapInfo; - private readonly IResourceStore resourceStore; private readonly IStorageResourceProvider resources; - public TestWorkingBeatmap(BeatmapInfo skinBeatmapInfo, IResourceStore resourceStore, IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, IStorageResourceProvider resources) + public TestWorkingBeatmap(BeatmapInfo skinBeatmapInfo, IResourceStore accessMarkingResourceStore, IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, + IStorageResourceProvider resources) : base(beatmap, storyboard, referenceClock, resources.AudioManager) { this.skinBeatmapInfo = skinBeatmapInfo; - this.resourceStore = resourceStore; + Files = accessMarkingResourceStore; this.resources = resources; } - protected internal override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resources, resourceStore); + protected internal override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, this); + + public AudioManager AudioManager => resources.AudioManager; + + public IResourceStore Files { get; } + + public IResourceStore Resources => resources.Resources; + + public RealmAccess RealmAccess => resources.RealmAccess; + + public IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore) => resources.CreateTextureLoaderStore(underlyingStore); } } } From 6c405f1dee7242d5fc7dbdff300658d4693e3221 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 14:31:24 +0900 Subject: [PATCH 13/21] Remove `storage` override from `LegacyBeatmapSkin` --- osu.Game/Skinning/LegacyBeatmapSkin.cs | 10 ++++------ osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 7b8b659473..6dc68b23d3 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -9,7 +9,6 @@ using osu.Framework.IO.Stores; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; -using osu.Game.Database; using osu.Game.IO; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Objects.Types; @@ -27,10 +26,8 @@ namespace osu.Game.Skinning /// /// The model for this beatmap. /// Access to raw game resources. - /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. - public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null) - : base(createSkinInfo(beatmapInfo), storage ?? createRealmBackedStore(beatmapInfo, resources), resources, - beatmapInfo.Path) + public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, [CanBeNull] IStorageResourceProvider resources) + : base(createSkinInfo(beatmapInfo), createRealmBackedStore(beatmapInfo, resources), resources, beatmapInfo.Path) { // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) Configuration.AllowDefaultComboColoursFallback = false; @@ -39,7 +36,8 @@ namespace osu.Game.Skinning private static IResourceStore createRealmBackedStore(BeatmapInfo beatmapInfo, [CanBeNull] IStorageResourceProvider resources) { if (resources == null) - return null; + // should only ever be used in tests. + return new ResourceStore(); return new RealmBackedResourceStore(beatmapInfo.BeatmapSet, resources.Files, new[] { @"ogg" }); } diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index fee650ded0..b2b348d869 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Beatmaps public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.DarkGoldenrod; public TestBeatmapSkin(BeatmapInfo beatmapInfo, bool hasColours) - : base(beatmapInfo, null, new ResourceStore()) + : base(beatmapInfo, null) { if (hasColours) { From 9d3c6ade6237c347bef8ad060ea755f2f2cf9d15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 14:38:40 +0900 Subject: [PATCH 14/21] Remove unnecessary skin reading hack in `DefaultLegacySkin` --- osu.Game/Skinning/DefaultLegacySkin.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 7d7d2db7f3..e7d0ed793f 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -30,11 +30,10 @@ namespace osu.Game.Skinning public DefaultLegacySkin(SkinInfo skin, IStorageResourceProvider resources) : base( skin, + // In the case of the actual default legacy skin (ie. the fallback one, which a user hasn't applied any modifications to) we want to use the game provided resources. skin.Protected ? new NamespacedResourceStore(resources.Resources, "Skins/Legacy") : null, resources, - // A default legacy skin may still have a skin.ini if it is modified by the user. - // We must specify the stream directly as we are redirecting storage to the osu-resources location for other files. - new RealmBackedResourceStore(skin, resources.Files).GetStream("skin.ini") + "skin.ini" ) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); From d0ea1739b4767427c6ccd1b8de425a5fa4059be3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 14:53:00 +0900 Subject: [PATCH 15/21] Remove skin configuration stream logic as it is no longer required --- osu.Game/Skinning/LegacySkin.cs | 14 +------------- osu.Game/Skinning/Skin.cs | 6 +++--- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 1559b9af53..6752851ca6 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -58,19 +58,7 @@ namespace osu.Game.Skinning /// Access to raw game resources. /// The user-facing filename of the configuration file to be parsed. Can accept an .osu or skin.ini file. protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, string configurationFilename) - : this(skin, storage, resources, string.IsNullOrEmpty(configurationFilename) ? null : storage?.GetStream(configurationFilename)) - { - } - - /// - /// Construct a new legacy skin instance. - /// - /// The model for this skin. - /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. - /// Access to raw game resources. - /// An optional stream containing the contents of a skin.ini file. - protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] Stream configurationStream) - : base(skin, resources, storage, configurationStream) + : base(skin, resources, storage, configurationFilename) { // todo: this shouldn't really be duplicated here (from ManiaLegacySkinTransformer). we need to come up with a better solution. hasKeyTexture = new Lazy(() => this.GetAnimation( diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 4c2b58bbc2..72bbca4903 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -58,8 +58,8 @@ namespace osu.Game.Skinning /// The skin's metadata. Usually a live realm object. /// Access to game-wide resources. /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. - /// An optional stream which will be used to read the skin configuration. If null, the configuration will be retrieved from the storage using "skin.ini". - protected Skin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null, [CanBeNull] Stream configurationStream = null) + /// An optional filename to read the skin configuration from. If not provided, the configuration will be retrieved from the storage using "skin.ini". + protected Skin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null, [CanBeNull] string configurationFilename = "skin.ini") { if (resources != null) { @@ -77,7 +77,7 @@ namespace osu.Game.Skinning Textures = new TextureStore(resources.CreateTextureLoaderStore(storage)); } - configurationStream ??= storage?.GetStream(@"skin.ini"); + var configurationStream = storage?.GetStream(configurationFilename); if (configurationStream != null) // stream will be closed after use by LineBufferedReader. From 7a1909bf970acd9f5a2ebcce6387a644b0ec3002 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 15:02:01 +0900 Subject: [PATCH 16/21] Change parameter order of `LegacySkin` to put `IStorageResourceProvider` first The optional resource store should not be before the (basically) required resource provider. --- .../CatchSkinColourDecodingTest.cs | 2 +- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs | 2 +- osu.Game/Skinning/DefaultLegacySkin.cs | 2 +- osu.Game/Skinning/LegacyBeatmapSkin.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 6 +++--- osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs | 2 +- osu.Game/Tests/Visual/SkinnableTestScene.cs | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs index e70def7f8b..ea3c0f3f4a 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Tests { public TestLegacySkin(SkinInfo skin, IResourceStore storage) // Bypass LegacySkinResourceStore to avoid returning null for retrieving files due to bad skin info (SkinInfo.Files = null). - : base(skin, storage, null, "skin.ini") + : base(skin, null, storage, "skin.ini") { } } diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index d19b3c71f1..0d436c1ef7 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -175,7 +175,7 @@ namespace osu.Game.Tests.Beatmaps.Formats private class TestLegacySkin : LegacySkin { public TestLegacySkin(IResourceStore storage, string fileName) - : base(new SkinInfo { Name = "Test Skin", Creator = "Craftplacer" }, storage, null, fileName) + : base(new SkinInfo { Name = "Test Skin", Creator = "Craftplacer" }, null, storage, fileName) { } } diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index 6457a23a1b..cfb158cc5a 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -148,7 +148,7 @@ namespace osu.Game.Tests.Gameplay private class TestSkin : LegacySkin { public TestSkin(string resourceName, IStorageResourceProvider resources) - : base(DefaultLegacySkin.CreateInfo(), new TestResourceStore(resourceName), resources, "skin.ini") + : base(DefaultLegacySkin.CreateInfo(), resources, new TestResourceStore(resourceName), "skin.ini") { } } diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index e7d0ed793f..be1b7b8f25 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -30,9 +30,9 @@ namespace osu.Game.Skinning public DefaultLegacySkin(SkinInfo skin, IStorageResourceProvider resources) : base( skin, + resources, // In the case of the actual default legacy skin (ie. the fallback one, which a user hasn't applied any modifications to) we want to use the game provided resources. skin.Protected ? new NamespacedResourceStore(resources.Resources, "Skins/Legacy") : null, - resources, "skin.ini" ) { diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 6dc68b23d3..e3685c986b 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -27,7 +27,7 @@ namespace osu.Game.Skinning /// The model for this beatmap. /// Access to raw game resources. public LegacyBeatmapSkin(BeatmapInfo beatmapInfo, [CanBeNull] IStorageResourceProvider resources) - : base(createSkinInfo(beatmapInfo), createRealmBackedStore(beatmapInfo, resources), resources, beatmapInfo.Path) + : base(createSkinInfo(beatmapInfo), resources, createRealmBackedStore(beatmapInfo, resources), beatmapInfo.Path) { // Disallow default colours fallback on beatmap skins to allow using parent skin combo colours. (via SkinProvidingContainer) Configuration.AllowDefaultComboColoursFallback = false; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 6752851ca6..fa581f98e0 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -46,7 +46,7 @@ namespace osu.Game.Skinning [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] public LegacySkin(SkinInfo skin, IStorageResourceProvider resources) - : this(skin, null, resources, "skin.ini") + : this(skin, resources, null, "skin.ini") { } @@ -54,10 +54,10 @@ namespace osu.Game.Skinning /// Construct a new legacy skin instance. /// /// The model for this skin. - /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. /// Access to raw game resources. + /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. /// The user-facing filename of the configuration file to be parsed. Can accept an .osu or skin.ini file. - protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore storage, [CanBeNull] IStorageResourceProvider resources, string configurationFilename) + protected LegacySkin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage, string configurationFilename) : base(skin, resources, storage, configurationFilename) { // todo: this shouldn't really be duplicated here (from ManiaLegacySkinTransformer). we need to come up with a better solution. diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index b2b348d869..531c38b655 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -141,7 +141,7 @@ namespace osu.Game.Tests.Beatmaps public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.LightCyan; public TestSkin(bool hasCustomColours) - : base(new SkinInfo(), new ResourceStore(), null, string.Empty) + : base(new SkinInfo(), null, new ResourceStore(), string.Empty) { if (hasCustomColours) { diff --git a/osu.Game/Tests/Visual/SkinnableTestScene.cs b/osu.Game/Tests/Visual/SkinnableTestScene.cs index 1107089a46..c8fc988ffd 100644 --- a/osu.Game/Tests/Visual/SkinnableTestScene.cs +++ b/osu.Game/Tests/Visual/SkinnableTestScene.cs @@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual private readonly bool extrapolateAnimations; public TestLegacySkin(SkinInfo skin, IResourceStore storage, IStorageResourceProvider resources, bool extrapolateAnimations) - : base(skin, storage, resources, "skin.ini") + : base(skin, resources, storage, "skin.ini") { this.extrapolateAnimations = extrapolateAnimations; } From 078288a616319eed8e5a9a3d653a22d92ae3c88a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 15:05:01 +0900 Subject: [PATCH 17/21] Make "skin.ini" the default skin filename and remove redundant parameters --- osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs | 2 +- osu.Game/Skinning/DefaultLegacySkin.cs | 3 +-- osu.Game/Skinning/LegacySkin.cs | 4 ++-- osu.Game/Skinning/Skin.cs | 2 +- osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs | 3 +-- osu.Game/Tests/Visual/SkinnableTestScene.cs | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs index ea3c0f3f4a..bb3a724b91 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Tests { public TestLegacySkin(SkinInfo skin, IResourceStore storage) // Bypass LegacySkinResourceStore to avoid returning null for retrieving files due to bad skin info (SkinInfo.Files = null). - : base(skin, null, storage, "skin.ini") + : base(skin, null, storage) { } } diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index cfb158cc5a..76ec35d87d 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -148,7 +148,7 @@ namespace osu.Game.Tests.Gameplay private class TestSkin : LegacySkin { public TestSkin(string resourceName, IStorageResourceProvider resources) - : base(DefaultLegacySkin.CreateInfo(), resources, new TestResourceStore(resourceName), "skin.ini") + : base(DefaultLegacySkin.CreateInfo(), resources, new TestResourceStore(resourceName)) { } } diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index be1b7b8f25..f7b415e886 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -32,8 +32,7 @@ namespace osu.Game.Skinning skin, resources, // In the case of the actual default legacy skin (ie. the fallback one, which a user hasn't applied any modifications to) we want to use the game provided resources. - skin.Protected ? new NamespacedResourceStore(resources.Resources, "Skins/Legacy") : null, - "skin.ini" + skin.Protected ? new NamespacedResourceStore(resources.Resources, "Skins/Legacy") : null ) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index fa581f98e0..1c2ca797c6 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -46,7 +46,7 @@ namespace osu.Game.Skinning [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] public LegacySkin(SkinInfo skin, IStorageResourceProvider resources) - : this(skin, resources, null, "skin.ini") + : this(skin, resources, null) { } @@ -57,7 +57,7 @@ namespace osu.Game.Skinning /// Access to raw game resources. /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. /// The user-facing filename of the configuration file to be parsed. Can accept an .osu or skin.ini file. - protected LegacySkin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage, string configurationFilename) + protected LegacySkin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage, string configurationFilename = @"skin.ini") : base(skin, resources, storage, configurationFilename) { // todo: this shouldn't really be duplicated here (from ManiaLegacySkinTransformer). we need to come up with a better solution. diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 72bbca4903..e28c35937d 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -59,7 +59,7 @@ namespace osu.Game.Skinning /// Access to game-wide resources. /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. /// An optional filename to read the skin configuration from. If not provided, the configuration will be retrieved from the storage using "skin.ini". - protected Skin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null, [CanBeNull] string configurationFilename = "skin.ini") + protected Skin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null, [CanBeNull] string configurationFilename = @"skin.ini") { if (resources != null) { diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index 531c38b655..597c5e9a2b 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -7,7 +7,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; -using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Skinning; @@ -141,7 +140,7 @@ namespace osu.Game.Tests.Beatmaps public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.LightCyan; public TestSkin(bool hasCustomColours) - : base(new SkinInfo(), null, new ResourceStore(), string.Empty) + : base(new SkinInfo(), null, null) { if (hasCustomColours) { diff --git a/osu.Game/Tests/Visual/SkinnableTestScene.cs b/osu.Game/Tests/Visual/SkinnableTestScene.cs index c8fc988ffd..b4da91a97a 100644 --- a/osu.Game/Tests/Visual/SkinnableTestScene.cs +++ b/osu.Game/Tests/Visual/SkinnableTestScene.cs @@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual private readonly bool extrapolateAnimations; public TestLegacySkin(SkinInfo skin, IResourceStore storage, IStorageResourceProvider resources, bool extrapolateAnimations) - : base(skin, resources, storage, "skin.ini") + : base(skin, resources, storage) { this.extrapolateAnimations = extrapolateAnimations; } From 05c7e09d79fa1f667c8bdfe7472eaa3a7677fa2f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Mar 2022 23:57:14 +0900 Subject: [PATCH 18/21] Make `Textures` and `Samples` read-only --- .../Skinning/LegacySkinTextureFallbackTest.cs | 54 +++++++++++++++---- osu.Game/Skinning/Skin.cs | 4 +- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs b/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs index 69e66942ab..7516e7500b 100644 --- a/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs +++ b/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs @@ -1,12 +1,21 @@ // Copyright (c) ppy Pty Ltd . 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.Linq; +using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; -using osu.Framework.Graphics.OpenGL.Textures; +using osu.Framework.Audio; using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; +using osu.Game.Database; +using osu.Game.IO; using osu.Game.Skinning; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; namespace osu.Game.Tests.NonVisual.Skinning { @@ -71,7 +80,7 @@ namespace osu.Game.Tests.NonVisual.Skinning var texture = legacySkin.GetTexture(requestedComponent); Assert.IsNotNull(texture); - Assert.AreEqual(textureStore.Textures[expectedTexture], texture); + Assert.AreEqual(textureStore.Textures[expectedTexture].Width, texture.Width); Assert.AreEqual(expectedScale, texture.ScaleAdjust); } @@ -88,23 +97,50 @@ namespace osu.Game.Tests.NonVisual.Skinning private class TestLegacySkin : LegacySkin { - public TestLegacySkin(TextureStore textureStore) - : base(new SkinInfo(), null, null, string.Empty) + public TestLegacySkin(IResourceStore textureStore) + : base(new SkinInfo(), new TestResourceProvider(textureStore), null, string.Empty) { - Textures = textureStore; + } + + private class TestResourceProvider : IStorageResourceProvider + { + private readonly IResourceStore textureStore; + + public TestResourceProvider(IResourceStore textureStore) + { + this.textureStore = textureStore; + } + + public AudioManager AudioManager => null; + public IResourceStore Files => null; + public IResourceStore Resources => null; + public RealmAccess RealmAccess => null; + public IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore) => textureStore; } } - private class TestTextureStore : TextureStore + private class TestTextureStore : IResourceStore { - public readonly Dictionary Textures; + public readonly Dictionary Textures; public TestTextureStore(params string[] fileNames) { - Textures = fileNames.ToDictionary(fileName => fileName, fileName => new Texture(1, 1)); + // use an incrementing width to allow assertion matching on correct textures as they turn from uploads into actual textures. + int width = 1; + Textures = fileNames.ToDictionary(fileName => fileName, fileName => new TextureUpload(new Image(width, width++))); } - public override Texture Get(string name, WrapMode wrapModeS, WrapMode wrapModeT) => Textures.GetValueOrDefault(name); + public TextureUpload Get(string name) => Textures.GetValueOrDefault(name); + + public Task GetAsync(string name, CancellationToken cancellationToken = new CancellationToken()) => Task.FromResult(Get(name)); + + public Stream GetStream(string name) => throw new NotImplementedException(); + + public IEnumerable GetAvailableResources() => throw new NotImplementedException(); + + public void Dispose() + { + } } } } diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index e28c35937d..b6f46a0d81 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -28,13 +28,13 @@ namespace osu.Game.Skinning /// A texture store which can be used to perform user file loops for this skin. /// [CanBeNull] - protected TextureStore Textures { get; set; } + protected TextureStore Textures { get; } /// /// A sample store which can be used to perform user file loops for this skin. /// [CanBeNull] - protected ISampleStore Samples { get; set; } + protected ISampleStore Samples { get; } public readonly Live SkinInfo; From a4d17a915f96c505e518dd261f9b4d1d5d967b7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Mar 2022 12:36:16 +0900 Subject: [PATCH 19/21] Fix incorrect HUD component fallback Legacy skins should now always show the legacy hud components. The conditional here is no longer valid as fallback lookups happen at a *skin*-fallback level rather than internal *source*-fallback. Put another way, `LegacyDefaultSkin` (with user customisations) should still display the classic HUD components even if a font is not provided, as that font will be available via the skin lookup hierarchy. The TODO removed in this commit has been already resolved so this code is no longer required. --- osu.Game/Skinning/LegacySkin.cs | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 1c2ca797c6..244774fd4c 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -356,26 +356,15 @@ namespace osu.Game.Skinning } }) { - Children = this.HasFont(LegacyFont.Score) - ? new Drawable[] - { - new LegacyComboCounter(), - new LegacyScoreCounter(), - new LegacyAccuracyCounter(), - new LegacyHealthDisplay(), - new SongProgress(), - new BarHitErrorMeter(), - } - : new Drawable[] - { - // TODO: these should fallback to using osu!classic skin textures, rather than doing this. - new DefaultComboCounter(), - new DefaultScoreCounter(), - new DefaultAccuracyCounter(), - new DefaultHealthDisplay(), - new SongProgress(), - new BarHitErrorMeter(), - } + Children = new Drawable[] + { + new LegacyComboCounter(), + new LegacyScoreCounter(), + new LegacyAccuracyCounter(), + new LegacyHealthDisplay(), + new SongProgress(), + new BarHitErrorMeter(), + } }; return skinnableTargetWrapper; From 0cd29a73b929b007c02619d96fa6b71f0834aa24 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Mar 2022 12:39:47 +0900 Subject: [PATCH 20/21] Fix typo in xmldocs --- osu.Game/Skinning/Skin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index b6f46a0d81..e1fcf196f3 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -25,13 +25,13 @@ namespace osu.Game.Skinning public abstract class Skin : IDisposable, ISkin { /// - /// A texture store which can be used to perform user file loops for this skin. + /// A texture store which can be used to perform user file lookups for this skin. /// [CanBeNull] protected TextureStore Textures { get; } /// - /// A sample store which can be used to perform user file loops for this skin. + /// A sample store which can be used to perform user file lookups for this skin. /// [CanBeNull] protected ISampleStore Samples { get; } From e243a7c55d349788f85c34a1b573b88547ace35b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Mar 2022 12:45:11 +0900 Subject: [PATCH 21/21] Reword `storage` param xmldoc to use stronger and better defined langauge --- osu.Game/Skinning/Skin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index e1fcf196f3..e00dd950a7 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -57,7 +57,7 @@ namespace osu.Game.Skinning /// /// The skin's metadata. Usually a live realm object. /// Access to game-wide resources. - /// An optional store which will be used for looking up skin resources. If null, one will be created from realm pattern. + /// An optional store which will *replace* all file lookups that are usually sourced from . /// An optional filename to read the skin configuration from. If not provided, the configuration will be retrieved from the storage using "skin.ini". protected Skin(SkinInfo skin, [CanBeNull] IStorageResourceProvider resources, [CanBeNull] IResourceStore storage = null, [CanBeNull] string configurationFilename = @"skin.ini") {