// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Skinning; using osu.Game.Rulesets.Catch.UI; using osu.Game.Skinning; using osu.Game.Tests.Visual; using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests { public class TestSceneHyperDashColouring : OsuTestScene { [Resolved] private SkinManager skins { get; set; } [Test] public void TestHyperDashCatcherColour() { CatcherArea catcherArea = null; AddStep("setup catcher", () => { Child = setupSkinHierarchy(catcherArea = new CatcherArea { RelativePositionAxes = Axes.None, Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(4f), }, false, false, false); }); AddStep("start hyper-dashing", () => { catcherArea.MovableCatcher.SetHyperDashState(2); catcherArea.MovableCatcher.FinishTransforms(); }); AddAssert("catcher has default hyper-dash colour", () => catcherArea.MovableCatcher.Colour == Color4.OrangeRed); AddAssert("catcher trails have default hyper-dash colour", () => catcherArea.OfType>().Any(c => c.Colour == Catcher.DefaultHyperDashColour)); AddStep("finish hyper-dashing", () => { catcherArea.MovableCatcher.SetHyperDashState(1); catcherArea.MovableCatcher.FinishTransforms(); }); AddAssert("hyper-dash colour cleared from catcher", () => catcherArea.MovableCatcher.Colour == Color4.White); } [Test] public void TestCustomHyperDashCatcherColour() { CatcherArea catcherArea = null; AddStep("setup catcher", () => { Child = setupSkinHierarchy(catcherArea = new CatcherArea { RelativePositionAxes = Axes.None, Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(4f), }, true, false, false); }); AddStep("start hyper-dashing", () => { catcherArea.MovableCatcher.SetHyperDashState(2); catcherArea.MovableCatcher.FinishTransforms(); }); AddAssert("catcher use hyper-dash colour from skin", () => catcherArea.MovableCatcher.Colour == TestSkin.CustomHyperDashColour); AddAssert("catcher trails use hyper-dash colour from skin", () => catcherArea.OfType>().Any(c => c.Colour == TestSkin.CustomHyperDashColour)); AddStep("clear hyper-dash", () => { catcherArea.MovableCatcher.SetHyperDashState(1); catcherArea.MovableCatcher.FinishTransforms(); }); AddAssert("hyper-dash colour cleared from catcher", () => catcherArea.MovableCatcher.Colour == Color4.White); } [Test] public void TestHyperDashCatcherEndGlowColour() { CatcherArea catcherArea = null; AddStep("setup catcher", () => { Child = setupSkinHierarchy(catcherArea = new CatcherArea { RelativePositionAxes = Axes.None, Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(4f), }, false, false, false); }); AddStep("start hyper-dashing", () => catcherArea.MovableCatcher.SetHyperDashState(2)); AddAssert("end-glow catcher sprite has default hyper-dash colour", () => catcherArea.OfType>().Any(c => c.Colour == Catcher.DefaultHyperDashColour)); } [TestCase(true)] [TestCase(false)] public void TestCustomHyperDashCatcherEndGlowColour(bool customHyperDashCatcherColour) { CatcherArea catcherArea = null; AddStep("setup catcher", () => { Child = setupSkinHierarchy(catcherArea = new CatcherArea { RelativePositionAxes = Axes.None, Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(4f), }, customHyperDashCatcherColour, true, false); }); AddStep("start hyper-dashing", () => catcherArea.MovableCatcher.SetHyperDashState(2)); AddAssert("end-glow catcher sprite use its hyper-dash colour from skin", () => catcherArea.OfType>().Any(c => c.Colour == TestSkin.CustomHyperDashAfterColour)); } [Test] public void TestCustomHyperDashCatcherEndGlowColourFallback() { CatcherArea catcherArea = null; AddStep("setup catcher", () => { Child = setupSkinHierarchy(catcherArea = new CatcherArea { RelativePositionAxes = Axes.None, Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(4f), }, true, false, false); }); AddStep("start hyper-dashing", () => catcherArea.MovableCatcher.SetHyperDashState(2)); AddAssert("end-glow catcher sprite colour falls back to catcher colour from skin", () => catcherArea.OfType>().Any(c => c.Colour == TestSkin.CustomHyperDashColour)); } [TestCase(false)] [TestCase(true)] public void TestHyperDashFruitColour(bool legacyFruit) { DrawableFruit drawableFruit = null; AddStep("setup hyper-dash fruit", () => { var fruit = new Fruit { HyperDashTarget = new Banana() }; fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); Child = setupSkinHierarchy(drawableFruit = new DrawableFruit(fruit) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(4f), }, false, false, false, legacyFruit); }); AddAssert("hyper-dash fruit has default colour", () => legacyFruit ? checkLegacyFruitHyperDashColour(drawableFruit, Catcher.DefaultHyperDashColour) : checkFruitHyperDashColour(drawableFruit, Catcher.DefaultHyperDashColour)); } [TestCase(false, true)] [TestCase(false, false)] [TestCase(true, true)] [TestCase(true, false)] public void TestCustomHyperDashFruitColour(bool legacyFruit, bool customCatcherHyperDashColour) { DrawableFruit drawableFruit = null; AddStep("setup hyper-dash fruit", () => { var fruit = new Fruit { HyperDashTarget = new Banana() }; fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); Child = setupSkinHierarchy(drawableFruit = new DrawableFruit(fruit) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(4f), }, customCatcherHyperDashColour, false, true, legacyFruit); }); AddAssert("hyper-dash fruit use fruit colour from skin", () => legacyFruit ? checkLegacyFruitHyperDashColour(drawableFruit, TestSkin.CustomHyperDashFruitColour) : checkFruitHyperDashColour(drawableFruit, TestSkin.CustomHyperDashFruitColour)); } [TestCase(false)] [TestCase(true)] public void TestCustomHyperDashFruitColourFallback(bool legacyFruit) { DrawableFruit drawableFruit = null; AddStep("setup hyper-dash fruit", () => { var fruit = new Fruit { HyperDashTarget = new Banana() }; fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); Child = setupSkinHierarchy( drawableFruit = new DrawableFruit(fruit) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Scale = new Vector2(4f), }, true, false, false, legacyFruit); }); AddAssert("hyper-dash fruit colour falls back to catcher colour from skin", () => legacyFruit ? checkLegacyFruitHyperDashColour(drawableFruit, TestSkin.CustomHyperDashColour) : checkFruitHyperDashColour(drawableFruit, TestSkin.CustomHyperDashColour)); } private Drawable setupSkinHierarchy(Drawable child, bool customCatcherColour, bool customAfterColour, bool customFruitColour, bool legacySkin = true) { var testSkinProvider = new SkinProvidingContainer(new TestSkin(customCatcherColour, customAfterColour, customFruitColour)); if (legacySkin) { var legacySkinProvider = new SkinProvidingContainer(skins.GetSkin(DefaultLegacySkin.Info)); var legacySkinTransformer = new SkinProvidingContainer(new CatchLegacySkinTransformer(testSkinProvider)); return legacySkinProvider .WithChild(testSkinProvider .WithChild(legacySkinTransformer .WithChild(child))); } return testSkinProvider.WithChild(child); } private bool checkFruitHyperDashColour(DrawableFruit fruit, Color4 expectedColour) => fruit.ChildrenOfType().First().Drawable.ChildrenOfType().Single(c => c.BorderColour == expectedColour).Any(d => d.Colour == expectedColour); private bool checkLegacyFruitHyperDashColour(DrawableFruit fruit, Color4 expectedColour) => fruit.ChildrenOfType().First().Drawable.ChildrenOfType().Any(c => c.Colour == expectedColour); private class TestSkin : ISkin { public static Color4 CustomHyperDashColour { get; } = Color4.Goldenrod; public static Color4 CustomHyperDashFruitColour { get; } = Color4.Cyan; public static Color4 CustomHyperDashAfterColour { get; } = Color4.Lime; private readonly bool customCatcherColour; private readonly bool customAfterColour; private readonly bool customFruitColour; public TestSkin(bool customCatcherColour, bool customAfterColour, bool customFruitColour) { this.customCatcherColour = customCatcherColour; this.customAfterColour = customAfterColour; this.customFruitColour = customFruitColour; } public Drawable GetDrawableComponent(ISkinComponent component) => null; public Texture GetTexture(string componentName) => null; public SampleChannel GetSample(ISampleInfo sampleInfo) => null; public IBindable GetConfig(TLookup lookup) { if (lookup is CatchSkinColour config) { if (config == CatchSkinColour.HyperDash && customCatcherColour) return SkinUtils.As(new Bindable(CustomHyperDashColour)); if (config == CatchSkinColour.HyperDashFruit && customFruitColour) return SkinUtils.As(new Bindable(CustomHyperDashFruitColour)); if (config == CatchSkinColour.HyperDashAfterImage && customAfterColour) return SkinUtils.As(new Bindable(CustomHyperDashAfterColour)); } return null; } } } }