osu/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTe...

204 lines
7.4 KiB
C#

// 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.
#nullable disable
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.Audio;
using osu.Framework.Graphics.Rendering;
using osu.Framework.Graphics.Rendering.Dummy;
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
{
[TestFixture]
public sealed class LegacySkinTextureFallbackTest
{
private static object[][] fallbackTestCases =
{
new object[]
{
// textures in store
new[] { "Gameplay/osu/followpoint@2x", "Gameplay/osu/followpoint" },
// requested component
"Gameplay/osu/followpoint",
// returned texture name & scale
"Gameplay/osu/followpoint@2x", 2
},
new object[]
{
new[] { "Gameplay/osu/followpoint@2x" },
"Gameplay/osu/followpoint",
"Gameplay/osu/followpoint@2x", 2
},
new object[]
{
new[] { "Gameplay/osu/followpoint" },
"Gameplay/osu/followpoint",
"Gameplay/osu/followpoint", 1
},
new object[]
{
new[] { "Gameplay/osu/followpoint", "followpoint@2x" },
"Gameplay/osu/followpoint",
"Gameplay/osu/followpoint", 1
},
new object[]
{
// Looking up a filename with extension specified should work.
new[] { "followpoint.png" },
"followpoint.png",
"followpoint.png", 1
},
new object[]
{
// Looking up a filename with extension specified should also work with @2x sprites.
new[] { "followpoint@2x.png" },
"followpoint.png",
"followpoint@2x.png", 2
},
new object[]
{
// Looking up a path with extension specified should work.
new[] { "Gameplay/osu/followpoint.png" },
"Gameplay/osu/followpoint.png",
"Gameplay/osu/followpoint.png", 1
},
new object[]
{
// Looking up a path with extension specified should also work with @2x sprites.
new[] { "Gameplay/osu/followpoint@2x.png" },
"Gameplay/osu/followpoint.png",
"Gameplay/osu/followpoint@2x.png", 2
},
};
[TestCaseSource(nameof(fallbackTestCases))]
public void TestFallbackOrder(string[] filesInStore, string requestedComponent, string expectedTexture, float expectedScale)
{
var textureStore = new TestTextureStore(filesInStore);
var legacySkin = new TestLegacySkin(textureStore);
var texture = legacySkin.GetTexture(requestedComponent);
Assert.IsNotNull(texture);
Assert.AreEqual(textureStore.Textures[expectedTexture].Width, texture.Width);
Assert.AreEqual(expectedScale, texture.ScaleAdjust);
}
[Test]
public void TestReturnNullOnFallbackFailure()
{
var textureStore = new TestTextureStore("sliderb", "hit100");
var legacySkin = new TestLegacySkin(textureStore);
var texture = legacySkin.GetTexture("Gameplay/osu/followpoint");
Assert.IsNull(texture);
}
[Test]
public void TestDisallowHighResolutionSprites()
{
var textureStore = new TestTextureStore("hitcircle", "hitcircle@2x");
var legacySkin = new TestLegacySkin(textureStore) { HighResolutionSprites = false };
var texture = legacySkin.GetTexture("hitcircle");
Assert.IsNotNull(texture);
Assert.That(texture.ScaleAdjust, Is.EqualTo(1));
var twoTimesTexture = legacySkin.GetTexture("hitcircle@2x");
Assert.IsNotNull(twoTimesTexture);
Assert.That(twoTimesTexture.ScaleAdjust, Is.EqualTo(1));
Assert.AreNotEqual(texture, twoTimesTexture);
}
[Test]
public void TestAllowHighResolutionSprites()
{
var textureStore = new TestTextureStore("hitcircle", "hitcircle@2x");
var legacySkin = new TestLegacySkin(textureStore) { HighResolutionSprites = true };
var texture = legacySkin.GetTexture("hitcircle");
Assert.IsNotNull(texture);
Assert.That(texture.ScaleAdjust, Is.EqualTo(2));
var twoTimesTexture = legacySkin.GetTexture("hitcircle@2x");
Assert.IsNotNull(twoTimesTexture);
Assert.That(twoTimesTexture.ScaleAdjust, Is.EqualTo(2));
Assert.AreEqual(texture, twoTimesTexture);
}
private class TestLegacySkin : LegacySkin
{
public bool HighResolutionSprites { get; set; } = true;
protected override bool AllowHighResolutionSprites => HighResolutionSprites;
public TestLegacySkin(IResourceStore<TextureUpload> textureStore)
: base(new SkinInfo(), new TestResourceProvider(textureStore), null, string.Empty)
{
}
private class TestResourceProvider : IStorageResourceProvider
{
private readonly IResourceStore<TextureUpload> textureStore;
public TestResourceProvider(IResourceStore<TextureUpload> textureStore)
{
this.textureStore = textureStore;
}
public IRenderer Renderer => new DummyRenderer();
public AudioManager AudioManager => null;
public IResourceStore<byte[]> Files => null!;
public IResourceStore<byte[]> Resources => null!;
public RealmAccess RealmAccess => null!;
public IResourceStore<TextureUpload> CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => textureStore;
}
}
private class TestTextureStore : IResourceStore<TextureUpload>
{
public readonly Dictionary<string, TextureUpload> Textures;
public TestTextureStore(params string[] fileNames)
{
// 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, _ => new TextureUpload(new Image<Rgba32>(width, width++)));
}
public TextureUpload Get(string name) => Textures.GetValueOrDefault(name);
public Task<TextureUpload> GetAsync(string name, CancellationToken cancellationToken = new CancellationToken()) => Task.FromResult(Get(name));
public Stream GetStream(string name) => throw new NotImplementedException();
public IEnumerable<string> GetAvailableResources() => throw new NotImplementedException();
public void Dispose()
{
}
}
}
}