diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs index 09fe9b3767..f7d42a2ee6 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.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 System; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -11,6 +12,7 @@ using osu.Game.Graphics.Backgrounds; using osu.Game.Online.API; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; +using osu.Game.Skinning; using osu.Game.Users; namespace osu.Game.Tests.Visual.Background @@ -23,6 +25,9 @@ namespace osu.Game.Tests.Visual.Background private Graphics.Backgrounds.Background getCurrentBackground() => screen.ChildrenOfType().FirstOrDefault(); + [Resolved] + private SkinManager skins { get; set; } + [Resolved] private OsuConfigManager config { get; set; } @@ -35,7 +40,7 @@ namespace osu.Game.Tests.Visual.Background } [Test] - public void TestTogglingStoryboardSwitchesBackgroundType() + public void TestBackgroundTypeSwitch() { setSupporter(true); @@ -44,6 +49,12 @@ namespace osu.Game.Tests.Visual.Background setSourceMode(BackgroundSource.BeatmapWithStoryboard); AddUntilStep("is storyboard background", () => getCurrentBackground() is BeatmapBackgroundWithStoryboard); + + setSourceMode(BackgroundSource.Skin); + AddUntilStep("is default background", () => getCurrentBackground().GetType() == typeof(Graphics.Backgrounds.Background)); + + setCustomSkin(); + AddUntilStep("is skin background", () => getCurrentBackground() is SkinBackground); } [Test] @@ -61,15 +72,19 @@ namespace osu.Game.Tests.Visual.Background AddUntilStep("is beatmap background", () => getCurrentBackground() is BeatmapBackground); } - [Test] - public void TestBeatmapDoesntReloadOnNoChange() + [TestCase(BackgroundSource.Beatmap, typeof(BeatmapBackground))] + [TestCase(BackgroundSource.BeatmapWithStoryboard, typeof(BeatmapBackgroundWithStoryboard))] + [TestCase(BackgroundSource.Skin, typeof(SkinBackground))] + public void TestBackgroundDoesntReloadOnNoChange(BackgroundSource source, Type backgroundType) { - BeatmapBackground last = null; + Graphics.Backgrounds.Background last = null; - setSourceMode(BackgroundSource.Beatmap); + setSourceMode(source); setSupporter(true); + if (source == BackgroundSource.Skin) + setCustomSkin(); - AddUntilStep("wait for beatmap background to be loaded", () => (last = getCurrentBackground() as BeatmapBackground) != null); + AddUntilStep("wait for beatmap background to be loaded", () => (last = getCurrentBackground())?.GetType() == backgroundType); AddAssert("next doesn't load new background", () => screen.Next() == false); // doesn't really need to be checked but might as well. @@ -77,8 +92,25 @@ namespace osu.Game.Tests.Visual.Background AddUntilStep("ensure same background instance", () => last == getCurrentBackground()); } + [Test] + public void TestBackgroundCyclingOnDefaultSkin([Values] bool supporter) + { + Graphics.Backgrounds.Background last = null; + + setSourceMode(BackgroundSource.Skin); + setSupporter(supporter); + setDefaultSkin(); + + AddUntilStep("wait for beatmap background to be loaded", () => (last = getCurrentBackground())?.GetType() == typeof(Graphics.Backgrounds.Background)); + AddAssert("next cycles background", () => screen.Next()); + + // doesn't really need to be checked but might as well. + AddWaitStep("wait a bit", 5); + AddUntilStep("ensure different background instance", () => last != getCurrentBackground()); + } + private void setSourceMode(BackgroundSource source) => - AddStep("set background mode to beatmap", () => config.SetValue(OsuSetting.MenuBackgroundSource, source)); + AddStep($"set background mode to {source}", () => config.SetValue(OsuSetting.MenuBackgroundSource, source)); private void setSupporter(bool isSupporter) => AddStep($"set supporter {isSupporter}", () => ((DummyAPIAccess)API).LocalUser.Value = new User @@ -86,5 +118,16 @@ namespace osu.Game.Tests.Visual.Background IsSupporter = isSupporter, Id = API.LocalUser.Value.Id + 1, }); + + private void setCustomSkin() + { + // feign a skin switch. this doesn't do anything except force CurrentSkin to become a LegacySkin. + AddStep("set custom skin", () => skins.CurrentSkinInfo.Value = new SkinInfo { ID = 5 }); + } + + private void setDefaultSkin() => AddStep("set default skin", () => skins.CurrentSkinInfo.SetDefault()); + + [TearDownSteps] + public void TearDown() => setDefaultSkin(); } } diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index c90b1e0e98..cfc1eb1806 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.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 System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,7 +15,7 @@ namespace osu.Game.Graphics.Backgrounds /// /// A background which offers blurring via a on demand. /// - public class Background : CompositeDrawable + public class Background : CompositeDrawable, IEquatable { private const float blur_scale = 0.5f; @@ -71,5 +72,14 @@ namespace osu.Game.Graphics.Backgrounds bufferedContainer?.BlurTo(newBlurSigma * blur_scale, duration, easing); } + + public virtual bool Equals(Background other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return other.GetType() == GetType() + && other.textureName == textureName; + } } } diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index 058d2ed0f9..e0c15dd52a 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -24,5 +24,14 @@ namespace osu.Game.Graphics.Backgrounds { Sprite.Texture = Beatmap?.Background ?? textures.Get(fallbackTextureName); } + + public override bool Equals(Background other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return other.GetType() == GetType() + && ((BeatmapBackground)other).Beatmap == Beatmap; + } } } diff --git a/osu.Game/Graphics/Backgrounds/SkinBackground.cs b/osu.Game/Graphics/Backgrounds/SkinBackground.cs new file mode 100644 index 0000000000..9266e7b17b --- /dev/null +++ b/osu.Game/Graphics/Backgrounds/SkinBackground.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Skinning; + +namespace osu.Game.Graphics.Backgrounds +{ + internal class SkinBackground : Background + { + private readonly Skin skin; + + public SkinBackground(Skin skin, string fallbackTextureName) + : base(fallbackTextureName) + { + this.skin = skin; + } + + [BackgroundDependencyLoader] + private void load() + { + Sprite.Texture = skin.GetTexture("menu-background") ?? Sprite.Texture; + } + + public override bool Equals(Background other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return other.GetType() == GetType() + && ((SkinBackground)other).skin.SkinInfo.Equals(skin.SkinInfo); + } + } +} diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 6bcfaac907..f0c90cc409 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -112,17 +112,24 @@ namespace osu.Game.Screens.Backgrounds newBackground = new BeatmapBackgroundWithStoryboard(beatmap.Value, getBackgroundTextureName()); newBackground ??= new BeatmapBackground(beatmap.Value, getBackgroundTextureName()); - // this method is called in many cases where the beatmap hasn't changed (ie. on screen transitions). - // if a background is already displayed for the requested beatmap, we don't want to load it again. - if (background?.GetType() == newBackground.GetType() && - (background as BeatmapBackground)?.Beatmap == beatmap.Value) - return background; - break; } + + case BackgroundSource.Skin: + // default skins should use the default background rotation, which won't be the case if a SkinBackground is created for them. + if (skin.Value is DefaultSkin || skin.Value is DefaultLegacySkin) + break; + + newBackground = new SkinBackground(skin.Value, getBackgroundTextureName()); + break; } } + // this method is called in many cases where the background might not necessarily need to change. + // if an equivalent background is currently being shown, we don't want to load it again. + if (newBackground?.Equals(background) == true) + return background; + newBackground ??= new Background(getBackgroundTextureName()); newBackground.Depth = currentDisplay; @@ -140,22 +147,5 @@ namespace osu.Game.Screens.Backgrounds return $@"Menu/menu-background-{currentDisplay % background_count + 1}"; } } - - private class SkinnedBackground : Background - { - private readonly Skin skin; - - public SkinnedBackground(Skin skin, string fallbackTextureName) - : base(fallbackTextureName) - { - this.skin = skin; - } - - [BackgroundDependencyLoader] - private void load() - { - Sprite.Texture = skin.GetTexture("menu-background") ?? Sprite.Texture; - } - } } }