Merge branch 'master' into per-ruleset-skinnable-tests

This commit is contained in:
Dan Balasescu
2020-04-07 22:59:42 +09:00
committed by GitHub
14 changed files with 116 additions and 39 deletions

View File

@ -52,6 +52,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.406.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2020.407.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Mania.Skinning
private Container directionContainer; private Container directionContainer;
private Sprite noteSprite; private Sprite noteSprite;
private float? minimumColumnWidth;
public LegacyNotePiece() public LegacyNotePiece()
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
@ -29,6 +31,8 @@ namespace osu.Game.Rulesets.Mania.Skinning
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(ISkinSource skin, IScrollingInfo scrollingInfo) private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
{ {
minimumColumnWidth = skin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.MinimumColumnWidth))?.Value;
InternalChild = directionContainer = new Container InternalChild = directionContainer = new Container
{ {
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
@ -47,8 +51,10 @@ namespace osu.Game.Rulesets.Mania.Skinning
if (noteSprite.Texture != null) if (noteSprite.Texture != null)
{ {
var scale = DrawWidth / noteSprite.Texture.DisplayWidth; // The height is scaled to the minimum column width, if provided.
noteSprite.Scale = new Vector2(scale); float minimumWidth = minimumColumnWidth ?? DrawWidth;
noteSprite.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), noteSprite.Texture.DisplayWidth);
} }
} }

View File

@ -64,6 +64,7 @@ namespace osu.Game.Rulesets.Mania.UI
{ {
// Mania doesn't care about global velocity // Mania doesn't care about global velocity
p.Velocity = 1; p.Velocity = 1;
p.BaseBeatLength *= Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier;
// For non-mania beatmap, speed changes should only happen through timing points // For non-mania beatmap, speed changes should only happen through timing points
if (!isForCurrentRuleset) if (!isForCurrentRuleset)

View File

@ -106,7 +106,7 @@ namespace osu.Game.Tests.Skins
var decoder = new LegacySkinDecoder(); var decoder = new LegacySkinDecoder();
using (var resStream = TestResources.OpenResource("skin-empty.ini")) using (var resStream = TestResources.OpenResource("skin-empty.ini"))
using (var stream = new LineBufferedReader(resStream)) using (var stream = new LineBufferedReader(resStream))
Assert.IsNull(decoder.Decode(stream).LegacyVersion); Assert.That(decoder.Decode(stream).LegacyVersion, Is.EqualTo(1.0m));
} }
} }
} }

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -12,7 +13,10 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.IO;
using osu.Game.Rulesets.Osu;
using osu.Game.Skinning; using osu.Game.Skinning;
using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
using osuTK.Graphics; using osuTK.Graphics;
@ -22,15 +26,15 @@ namespace osu.Game.Tests.Skins
[HeadlessTest] [HeadlessTest]
public class TestSceneSkinConfigurationLookup : OsuTestScene public class TestSceneSkinConfigurationLookup : OsuTestScene
{ {
private SkinSource source1; private UserSkinSource userSource;
private SkinSource source2; private BeatmapSkinSource beatmapSource;
private SkinRequester requester; private SkinRequester requester;
[SetUp] [SetUp]
public void SetUp() => Schedule(() => public void SetUp() => Schedule(() =>
{ {
Add(new SkinProvidingContainer(source1 = new SkinSource()) Add(new SkinProvidingContainer(userSource = new UserSkinSource())
.WithChild(new SkinProvidingContainer(source2 = new SkinSource()) .WithChild(new SkinProvidingContainer(beatmapSource = new BeatmapSkinSource())
.WithChild(requester = new SkinRequester()))); .WithChild(requester = new SkinRequester())));
}); });
@ -39,31 +43,31 @@ namespace osu.Game.Tests.Skins
{ {
AddStep("Add config values", () => AddStep("Add config values", () =>
{ {
source1.Configuration.ConfigDictionary["Lookup"] = "source1"; userSource.Configuration.ConfigDictionary["Lookup"] = "user skin";
source2.Configuration.ConfigDictionary["Lookup"] = "source2"; beatmapSource.Configuration.ConfigDictionary["Lookup"] = "beatmap skin";
}); });
AddAssert("Check lookup finds source2", () => requester.GetConfig<string, string>("Lookup")?.Value == "source2"); AddAssert("Check lookup finds beatmap skin", () => requester.GetConfig<string, string>("Lookup")?.Value == "beatmap skin");
} }
[Test] [Test]
public void TestFloatLookup() public void TestFloatLookup()
{ {
AddStep("Add config values", () => source1.Configuration.ConfigDictionary["FloatTest"] = "1.1"); AddStep("Add config values", () => userSource.Configuration.ConfigDictionary["FloatTest"] = "1.1");
AddAssert("Check float parse lookup", () => requester.GetConfig<string, float>("FloatTest")?.Value == 1.1f); AddAssert("Check float parse lookup", () => requester.GetConfig<string, float>("FloatTest")?.Value == 1.1f);
} }
[Test] [Test]
public void TestBoolLookup() public void TestBoolLookup()
{ {
AddStep("Add config values", () => source1.Configuration.ConfigDictionary["BoolTest"] = "1"); AddStep("Add config values", () => userSource.Configuration.ConfigDictionary["BoolTest"] = "1");
AddAssert("Check bool parse lookup", () => requester.GetConfig<string, bool>("BoolTest")?.Value == true); AddAssert("Check bool parse lookup", () => requester.GetConfig<string, bool>("BoolTest")?.Value == true);
} }
[Test] [Test]
public void TestEnumLookup() public void TestEnumLookup()
{ {
AddStep("Add config values", () => source1.Configuration.ConfigDictionary["Test"] = "Test2"); AddStep("Add config values", () => userSource.Configuration.ConfigDictionary["Test"] = "Test2");
AddAssert("Check enum parse lookup", () => requester.GetConfig<LookupType, ValueType>(LookupType.Test)?.Value == ValueType.Test2); AddAssert("Check enum parse lookup", () => requester.GetConfig<LookupType, ValueType>(LookupType.Test)?.Value == ValueType.Test2);
} }
@ -76,7 +80,7 @@ namespace osu.Game.Tests.Skins
[Test] [Test]
public void TestLookupNull() public void TestLookupNull()
{ {
AddStep("Add config values", () => source1.Configuration.ConfigDictionary["Lookup"] = null); AddStep("Add config values", () => userSource.Configuration.ConfigDictionary["Lookup"] = null);
AddAssert("Check lookup null", () => AddAssert("Check lookup null", () =>
{ {
@ -88,7 +92,7 @@ namespace osu.Game.Tests.Skins
[Test] [Test]
public void TestColourLookup() public void TestColourLookup()
{ {
AddStep("Add config colour", () => source1.Configuration.CustomColours["Lookup"] = Color4.Red); AddStep("Add config colour", () => userSource.Configuration.CustomColours["Lookup"] = Color4.Red);
AddAssert("Check colour lookup", () => requester.GetConfig<SkinCustomColourLookup, Color4>(new SkinCustomColourLookup("Lookup"))?.Value == Color4.Red); AddAssert("Check colour lookup", () => requester.GetConfig<SkinCustomColourLookup, Color4>(new SkinCustomColourLookup("Lookup"))?.Value == Color4.Red);
} }
@ -101,7 +105,7 @@ namespace osu.Game.Tests.Skins
[Test] [Test]
public void TestWrongColourType() public void TestWrongColourType()
{ {
AddStep("Add config colour", () => source1.Configuration.CustomColours["Lookup"] = Color4.Red); AddStep("Add config colour", () => userSource.Configuration.CustomColours["Lookup"] = Color4.Red);
AddAssert("perform incorrect lookup", () => AddAssert("perform incorrect lookup", () =>
{ {
@ -127,26 +131,51 @@ namespace osu.Game.Tests.Skins
[Test] [Test]
public void TestEmptyComboColoursNoFallback() public void TestEmptyComboColoursNoFallback()
{ {
AddStep("Add custom combo colours to source1", () => source1.Configuration.AddComboColours( AddStep("Add custom combo colours to user skin", () => userSource.Configuration.AddComboColours(
new Color4(100, 150, 200, 255), new Color4(100, 150, 200, 255),
new Color4(55, 110, 166, 255), new Color4(55, 110, 166, 255),
new Color4(75, 125, 175, 255) new Color4(75, 125, 175, 255)
)); ));
AddStep("Disallow default colours fallback in source2", () => source2.Configuration.AllowDefaultComboColoursFallback = false); AddStep("Disallow default colours fallback in beatmap skin", () => beatmapSource.Configuration.AllowDefaultComboColoursFallback = false);
AddAssert("Check retrieved combo colours from source1", () => AddAssert("Check retrieved combo colours from user skin", () =>
requester.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value?.SequenceEqual(source1.Configuration.ComboColours) ?? false); requester.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value?.SequenceEqual(userSource.Configuration.ComboColours) ?? false);
} }
[Test] [Test]
public void TestLegacyVersionLookup() public void TestNullBeatmapVersionFallsBackToUserSkin()
{ {
AddStep("Set source1 version 2.3", () => source1.Configuration.LegacyVersion = 2.3m); AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m);
AddStep("Set source2 version null", () => source2.Configuration.LegacyVersion = null); AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null);
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m); AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m);
} }
[Test]
public void TestSetBeatmapVersionNoFallback()
{
AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = 2.3m);
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = 1.7m);
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 1.7m);
}
[Test]
public void TestNullBeatmapAndUserVersionFallsBackToLatest()
{
AddStep("Set user skin version 2.3", () => userSource.Configuration.LegacyVersion = null);
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null);
AddAssert("Check legacy version lookup",
() => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == LegacySkinConfiguration.LATEST_VERSION);
}
[Test]
public void TestIniWithNoVersionFallsBackTo1()
{
AddStep("Parse skin with no version", () => userSource.Configuration = new LegacySkinDecoder().Decode(new LineBufferedReader(new MemoryStream())));
AddStep("Set beatmap skin version null", () => beatmapSource.Configuration.LegacyVersion = null);
AddAssert("Check legacy version lookup", () => requester.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value == 1.0m);
}
public enum LookupType public enum LookupType
{ {
Test Test
@ -159,14 +188,22 @@ namespace osu.Game.Tests.Skins
Test3 Test3
} }
public class SkinSource : LegacySkin public class UserSkinSource : LegacySkin
{ {
public SkinSource() public UserSkinSource()
: base(new SkinInfo(), null, null, string.Empty) : base(new SkinInfo(), null, null, string.Empty)
{ {
} }
} }
public class BeatmapSkinSource : LegacyBeatmapSkin
{
public BeatmapSkinSource()
: base(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, null, null)
{
}
}
public class SkinRequester : Drawable, ISkin public class SkinRequester : Drawable, ISkin
{ {
private ISkinSource skin; private ISkinSource skin;

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.IO.Stores; using osu.Framework.IO.Stores;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -18,6 +19,20 @@ namespace osu.Game.Skinning
Configuration.AllowDefaultComboColoursFallback = false; Configuration.AllowDefaultComboColoursFallback = false;
} }
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
{
switch (lookup)
{
case LegacySkinConfiguration.LegacySetting s when s == LegacySkinConfiguration.LegacySetting.Version:
if (Configuration.LegacyVersion is decimal version)
return SkinUtils.As<TValue>(new Bindable<decimal>(version));
return null;
}
return base.GetConfig<TLookup, TValue>(lookup);
}
private static SkinInfo createSkinInfo(BeatmapInfo beatmap) => private static SkinInfo createSkinInfo(BeatmapInfo beatmap) =>
new SkinInfo { Name = beatmap.ToString(), Creator = beatmap.Metadata.Author.ToString() }; new SkinInfo { Name = beatmap.ToString(), Creator = beatmap.Metadata.Author.ToString() };
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Formats;
using osuTK.Graphics; using osuTK.Graphics;
@ -45,5 +46,13 @@ namespace osu.Game.Skinning
ColumnLineWidth.AsSpan().Fill(2); ColumnLineWidth.AsSpan().Fill(2);
ColumnWidth.AsSpan().Fill(DEFAULT_COLUMN_SIZE); ColumnWidth.AsSpan().Fill(DEFAULT_COLUMN_SIZE);
} }
private float? minimumColumnWidth;
public float MinimumColumnWidth
{
get => minimumColumnWidth ?? ColumnWidth.Min();
set => minimumColumnWidth = value;
}
} }
} }

View File

@ -36,6 +36,7 @@ namespace osu.Game.Skinning
HoldNoteBodyImage, HoldNoteBodyImage,
ExplosionImage, ExplosionImage,
ExplosionScale, ExplosionScale,
ColumnLineColour ColumnLineColour,
MinimumColumnWidth
} }
} }

View File

@ -106,6 +106,10 @@ namespace osu.Game.Skinning
case "LightingNWidth": case "LightingNWidth":
parseArrayValue(pair.Value, currentConfig.ExplosionWidth); parseArrayValue(pair.Value, currentConfig.ExplosionWidth);
break; break;
case "WidthForNoteHeightScale":
currentConfig.MinimumColumnWidth = float.Parse(pair.Value, CultureInfo.InvariantCulture) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR;
break;
} }
} }

View File

@ -71,7 +71,7 @@ namespace osu.Game.Skinning
} }
} }
else else
Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION }; Configuration = new LegacySkinConfiguration();
} }
if (storage != null) if (storage != null)
@ -122,10 +122,7 @@ namespace osu.Game.Skinning
switch (legacy) switch (legacy)
{ {
case LegacySkinConfiguration.LegacySetting.Version: case LegacySkinConfiguration.LegacySetting.Version:
if (Configuration.LegacyVersion is decimal version) return SkinUtils.As<TValue>(new Bindable<decimal>(Configuration.LegacyVersion ?? LegacySkinConfiguration.LATEST_VERSION));
return SkinUtils.As<TValue>(new Bindable<decimal>(version));
break;
} }
break; break;
@ -207,6 +204,9 @@ namespace osu.Game.Skinning
case LegacyManiaSkinConfigurationLookups.ColumnLineColour: case LegacyManiaSkinConfigurationLookups.ColumnLineColour:
return SkinUtils.As<TValue>(getCustomColour(existing, "ColourColumnLine")); return SkinUtils.As<TValue>(getCustomColour(existing, "ColourColumnLine"));
case LegacyManiaSkinConfigurationLookups.MinimumColumnWidth:
return SkinUtils.As<TValue>(new Bindable<float>(existing.MinimumColumnWidth));
} }
return null; return null;

View File

@ -52,5 +52,12 @@ namespace osu.Game.Skinning
base.ParseLine(skin, section, line); base.ParseLine(skin, section, line);
} }
protected override LegacySkinConfiguration CreateTemplateObject()
{
var config = base.CreateTemplateObject();
config.LegacyVersion = 1.0m;
return config;
}
} }
} }

View File

@ -27,9 +27,6 @@ namespace osu.Game.Tests.Visual
private Skin specialSkin; private Skin specialSkin;
private Skin oldSkin; private Skin oldSkin;
// Keep a static reference to ensure we don't use a dynamically recompiled DLL as a source (resources will be missing).
private static DllResourceStore dllStore;
protected SkinnableTestScene() protected SkinnableTestScene()
: base(2, 3) : base(2, 3)
{ {
@ -41,7 +38,7 @@ namespace osu.Game.Tests.Visual
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio, SkinManager skinManager) private void load(AudioManager audio, SkinManager skinManager)
{ {
dllStore ??= new DllResourceStore(GetType().Assembly); var dllStore = new DllResourceStore(DynamicCompilationOriginal.GetType().Assembly);
metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), audio, true); metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), audio, true);
defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info); defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info);

View File

@ -22,7 +22,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2020.406.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.407.1" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
<PackageReference Include="Sentry" Version="2.1.1" /> <PackageReference Include="Sentry" Version="2.1.1" />
<PackageReference Include="SharpCompress" Version="0.25.0" /> <PackageReference Include="SharpCompress" Version="0.25.0" />

View File

@ -70,7 +70,7 @@
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.406.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2020.407.1" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.403.0" />
</ItemGroup> </ItemGroup>
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. --> <!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
@ -79,7 +79,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2020.406.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.407.1" />
<PackageReference Include="SharpCompress" Version="0.25.0" /> <PackageReference Include="SharpCompress" Version="0.25.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />