Store default skins to database

This commit is contained in:
Dean Herbert 2021-11-29 17:15:26 +09:00
parent c629a7a36f
commit f6a3709060
11 changed files with 61 additions and 52 deletions

View File

@ -174,7 +174,7 @@ namespace osu.Game.Rulesets.Catch.Tests
private Drawable setupSkinHierarchy(Drawable child, ISkin skin) private Drawable setupSkinHierarchy(Drawable child, ISkin skin)
{ {
var legacySkinProvider = new SkinProvidingContainer(skins.GetSkin(DefaultLegacySkin.Info)); var legacySkinProvider = new SkinProvidingContainer(skins.GetSkin(DefaultLegacySkin.CreateInfo()));
var testSkinProvider = new SkinProvidingContainer(skin); var testSkinProvider = new SkinProvidingContainer(skin);
var legacySkinTransformer = new SkinProvidingContainer(new CatchLegacySkinTransformer(testSkinProvider)); var legacySkinTransformer = new SkinProvidingContainer(new CatchLegacySkinTransformer(testSkinProvider));

View File

@ -56,13 +56,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
[Test] [Test]
public void TestDefaultSkin() public void TestDefaultSkin()
{ {
AddStep("set default skin", () => skins.CurrentSkinInfo.Value = SkinInfo.Default.ToLive()); AddStep("set default skin", () => skins.CurrentSkinInfo.Value = DefaultSkin.CreateInfo().ToLive());
} }
[Test] [Test]
public void TestLegacySkin() public void TestLegacySkin()
{ {
AddStep("set legacy skin", () => skins.CurrentSkinInfo.Value = DefaultLegacySkin.Info.ToLive()); AddStep("set legacy skin", () => skins.CurrentSkinInfo.Value = DefaultLegacySkin.CreateInfo().ToLive());
} }
} }
} }

View File

@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Tests
AddStep("create slider", () => AddStep("create slider", () =>
{ {
var tintingSkin = skinManager.GetSkin(DefaultLegacySkin.Info); var tintingSkin = skinManager.GetSkin(DefaultLegacySkin.CreateInfo());
tintingSkin.Configuration.ConfigDictionary["AllowSliderBallTint"] = "1"; tintingSkin.Configuration.ConfigDictionary["AllowSliderBallTint"] = "1";
Child = new SkinProvidingContainer(tintingSkin) Child = new SkinProvidingContainer(tintingSkin)

View File

@ -167,7 +167,7 @@ namespace osu.Game.Tests.Gameplay
private class TestSkin : LegacySkin private class TestSkin : LegacySkin
{ {
public TestSkin(string resourceName, IStorageResourceProvider resources) public TestSkin(string resourceName, IStorageResourceProvider resources)
: base(DefaultLegacySkin.Info, new TestResourceStore(resourceName), resources, "skin.ini") : base(DefaultLegacySkin.CreateInfo(), new TestResourceStore(resourceName), resources, "skin.ini")
{ {
} }
} }

View File

@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test] [Test]
public void TestEmptyLegacyBeatmapSkinFallsBack() public void TestEmptyLegacyBeatmapSkinFallsBack()
{ {
CreateSkinTest(SkinInfo.Default, () => new LegacyBeatmapSkin(new BeatmapInfo(), null, null)); CreateSkinTest(DefaultSkin.CreateInfo(), () => new LegacyBeatmapSkin(new BeatmapInfo(), null, null));
AddUntilStep("wait for hud load", () => Player.ChildrenOfType<SkinnableTargetContainer>().All(c => c.ComponentsLoaded)); AddUntilStep("wait for hud load", () => Player.ChildrenOfType<SkinnableTargetContainer>().All(c => c.ComponentsLoaded));
AddAssert("hud from default skin", () => AssertComponentsFromExpectedSource(SkinnableTarget.MainHUDComponents, skinManager.CurrentSkin.Value)); AddAssert("hud from default skin", () => AssertComponentsFromExpectedSource(SkinnableTarget.MainHUDComponents, skinManager.CurrentSkin.Value));
} }

View File

@ -256,10 +256,10 @@ namespace osu.Game
if (skinInfo == null) if (skinInfo == null)
{ {
if (guid == SkinInfo.CLASSIC_SKIN) if (guid == SkinInfo.CLASSIC_SKIN)
skinInfo = DefaultLegacySkin.Info.ToLive(); skinInfo = DefaultLegacySkin.CreateInfo().ToLive();
} }
SkinManager.CurrentSkinInfo.Value = skinInfo ?? SkinInfo.Default.ToLive(); SkinManager.CurrentSkinInfo.Value = skinInfo ?? DefaultSkin.CreateInfo().ToLive();
}; };
configSkin.TriggerChange(); configSkin.TriggerChange();
@ -660,7 +660,7 @@ namespace osu.Game
// make config aware of how to lookup skins for on-screen display purposes. // make config aware of how to lookup skins for on-screen display purposes.
// if this becomes a more common thing, tracked settings should be reconsidered to allow local DI. // if this becomes a more common thing, tracked settings should be reconsidered to allow local DI.
LocalConfig.LookupSkinName = id => SkinManager.GetAllUsableSkins().FirstOrDefault(s => s.ID == id)?.ToString() ?? "Unknown"; LocalConfig.LookupSkinName = id => SkinManager.Query(s => s.ID == id)?.ToString() ?? "Unknown";
LocalConfig.LookupKeyBindings = l => LocalConfig.LookupKeyBindings = l =>
{ {

View File

@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections
Icon = FontAwesome.Solid.PaintBrush Icon = FontAwesome.Solid.PaintBrush
}; };
private readonly Bindable<ILive<SkinInfo>> dropdownBindable = new Bindable<ILive<SkinInfo>> { Default = SkinInfo.Default.ToLive() }; private readonly Bindable<ILive<SkinInfo>> dropdownBindable = new Bindable<ILive<SkinInfo>> { Default = DefaultSkin.CreateInfo().ToLive() };
private readonly Bindable<string> configBindable = new Bindable<string>(); private readonly Bindable<string> configBindable = new Bindable<string>();
private static readonly ILive<SkinInfo> random_skin_info = new SkinInfo private static readonly ILive<SkinInfo> random_skin_info = new SkinInfo
@ -81,7 +81,8 @@ namespace osu.Game.Overlays.Settings.Sections
realmSkins = realmFactory.Context.All<SkinInfo>() realmSkins = realmFactory.Context.All<SkinInfo>()
.Where(s => !s.DeletePending) .Where(s => !s.DeletePending)
.OrderBy(s => s.Name, StringComparer.OrdinalIgnoreCase); .OrderBy(s => s.Protected)
.ThenBy(s => s.Name, StringComparer.OrdinalIgnoreCase);
realmSubscription = realmSkins realmSubscription = realmSkins
.SubscribeForNotifications((sender, changes, error) => .SubscribeForNotifications((sender, changes, error) =>
@ -141,11 +142,11 @@ namespace osu.Game.Overlays.Settings.Sections
private void updateItems() private void updateItems()
{ {
int protectedCount = realmSkins.Count(s => s.Protected);
skinItems = realmSkins.ToLive(); skinItems = realmSkins.ToLive();
skinItems.Insert(0, SkinInfo.Default.ToLive()); skinItems.Insert(protectedCount, random_skin_info);
skinItems.Insert(1, DefaultLegacySkin.Info.ToLive());
skinItems.Insert(2, random_skin_info);
skinDropdown.Items = skinItems; skinDropdown.Items = skinItems;
} }

View File

@ -12,8 +12,17 @@ namespace osu.Game.Skinning
{ {
public class DefaultLegacySkin : LegacySkin public class DefaultLegacySkin : LegacySkin
{ {
public static SkinInfo CreateInfo() => new SkinInfo
{
ID = Skinning.SkinInfo.CLASSIC_SKIN, // this is temporary until database storage is decided upon.
Name = "osu!classic",
Creator = "team osu!",
Protected = true,
InstantiationInfo = typeof(DefaultLegacySkin).GetInvariantInstantiationInfo()
};
public DefaultLegacySkin(IStorageResourceProvider resources) public DefaultLegacySkin(IStorageResourceProvider resources)
: this(Info, resources) : this(CreateInfo(), resources)
{ {
} }
@ -39,13 +48,5 @@ namespace osu.Game.Skinning
Configuration.LegacyVersion = 2.7m; Configuration.LegacyVersion = 2.7m;
} }
public static SkinInfo Info { get; } = new SkinInfo
{
ID = osu.Game.Skinning.SkinInfo.CLASSIC_SKIN, // this is temporary until database storage is decided upon.
Name = "osu!classic",
Creator = "team osu!",
InstantiationInfo = typeof(DefaultLegacySkin).GetInvariantInstantiationInfo()
};
} }
} }

View File

@ -23,10 +23,19 @@ namespace osu.Game.Skinning
{ {
public class DefaultSkin : Skin public class DefaultSkin : Skin
{ {
public static SkinInfo CreateInfo() => new SkinInfo
{
ID = osu.Game.Skinning.SkinInfo.DEFAULT_SKIN,
Name = "osu! (triangles)",
Creator = "team osu!",
Protected = true,
InstantiationInfo = typeof(DefaultSkin).GetInvariantInstantiationInfo()
};
private readonly IStorageResourceProvider resources; private readonly IStorageResourceProvider resources;
public DefaultSkin(IStorageResourceProvider resources) public DefaultSkin(IStorageResourceProvider resources)
: this(osu.Game.Skinning.SkinInfo.Default, resources) : this(CreateInfo(), resources)
{ {
} }

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.Models; using osu.Game.Models;
using Realms; using Realms;
@ -32,6 +31,8 @@ namespace osu.Game.Skinning
public string Hash { get; set; } = string.Empty; public string Hash { get; set; } = string.Empty;
public bool Protected { get; set; }
public string InstantiationInfo { get; set; } = string.Empty; public string InstantiationInfo { get; set; } = string.Empty;
public virtual Skin CreateInstance(IStorageResourceProvider resources) public virtual Skin CreateInstance(IStorageResourceProvider resources)
@ -48,14 +49,6 @@ namespace osu.Game.Skinning
public bool DeletePending { get; set; } public bool DeletePending { get; set; }
public static SkinInfo Default { get; } = new SkinInfo
{
ID = DEFAULT_SKIN,
Name = "osu! (triangles)",
Creator = "team osu!",
InstantiationInfo = typeof(DefaultSkin).GetInvariantInstantiationInfo()
};
public bool Equals(SkinInfo? other) public bool Equals(SkinInfo? other)
{ {
if (ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;

View File

@ -45,7 +45,11 @@ namespace osu.Game.Skinning
private readonly IResourceStore<byte[]> resources; private readonly IResourceStore<byte[]> resources;
public readonly Bindable<Skin> CurrentSkin = new Bindable<Skin>(); public readonly Bindable<Skin> CurrentSkin = new Bindable<Skin>();
public readonly Bindable<ILive<SkinInfo>> CurrentSkinInfo = new Bindable<ILive<SkinInfo>>(SkinInfo.Default.ToLive()) { Default = SkinInfo.Default.ToLive() };
public readonly Bindable<ILive<SkinInfo>> CurrentSkinInfo = new Bindable<ILive<SkinInfo>>(Skinning.DefaultSkin.CreateInfo().ToLive())
{
Default = Skinning.DefaultSkin.CreateInfo().ToLive()
};
private readonly SkinModelManager skinModelManager; private readonly SkinModelManager skinModelManager;
private readonly RealmContextFactory contextFactory; private readonly RealmContextFactory contextFactory;
@ -74,8 +78,24 @@ namespace osu.Game.Skinning
skinModelManager = new SkinModelManager(storage, contextFactory, host, this); skinModelManager = new SkinModelManager(storage, contextFactory, host, this);
DefaultLegacySkin = new DefaultLegacySkin(this); var defaultSkins = new[]
DefaultSkin = new DefaultSkin(this); {
DefaultLegacySkin = new DefaultLegacySkin(this),
DefaultSkin = new DefaultSkin(this),
};
// Ensure the default entries are present.
using (var context = contextFactory.CreateContext())
using (var transaction = context.BeginWrite())
{
foreach (var skin in defaultSkins)
{
if (context.Find<SkinInfo>(skin.SkinInfo.ID) == null)
context.Add(skin.SkinInfo.Value);
}
transaction.Commit();
}
CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = skin.NewValue.PerformRead(GetSkin); CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = skin.NewValue.PerformRead(GetSkin);
@ -89,21 +109,6 @@ namespace osu.Game.Skinning
}; };
} }
/// <summary>
/// Returns a list of all usable <see cref="SkinInfo"/>s. Includes the non-databased default skins.
/// </summary>
/// <returns>A newly allocated list of available <see cref="SkinInfo"/>.</returns>
public List<ILive<SkinInfo>> GetAllUsableSkins()
{
using (var context = contextFactory.CreateContext())
{
var userSkins = context.All<SkinInfo>().Where(s => !s.DeletePending).ToLive();
userSkins.Insert(0, DefaultSkin.SkinInfo);
userSkins.Insert(1, DefaultLegacySkin.SkinInfo);
return userSkins;
}
}
public void SelectRandomSkin() public void SelectRandomSkin()
{ {
using (var context = contextFactory.CreateContext()) using (var context = contextFactory.CreateContext())
@ -113,7 +118,7 @@ namespace osu.Game.Skinning
if (randomChoices.Length == 0) if (randomChoices.Length == 0)
{ {
CurrentSkinInfo.Value = SkinInfo.Default.ToLive(); CurrentSkinInfo.Value = Skinning.DefaultSkin.CreateInfo().ToLive();
return; return;
} }