1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 18:47:27 +08:00

Merge branch 'master' into inheritable-allow-track-adjust

This commit is contained in:
Dean Herbert 2021-09-16 16:35:11 +09:00 committed by GitHub
commit da0667365b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 191 additions and 234 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,18 +1,18 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics;
using osu.Game.Skinning; using osu.Game.Skinning;
namespace osu.Game.Rulesets.Mania.Skinning.Legacy namespace osu.Game.Rulesets.Mania.Skinning.Legacy
{ {
public class LegacyHoldNoteHeadPiece : LegacyNotePiece public class LegacyHoldNoteHeadPiece : LegacyNotePiece
{ {
protected override Texture GetTexture(ISkinSource skin) protected override Drawable GetAnimation(ISkinSource skin)
{ {
// TODO: Should fallback to the head from default legacy skin instead of note. // TODO: Should fallback to the head from default legacy skin instead of note.
return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage) return GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); ?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
} }
} }
} }

View File

@ -2,7 +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.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Skinning; using osu.Game.Skinning;
@ -18,12 +18,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
: new ValueChangedEvent<ScrollingDirection>(ScrollingDirection.Up, ScrollingDirection.Up)); : new ValueChangedEvent<ScrollingDirection>(ScrollingDirection.Up, ScrollingDirection.Up));
} }
protected override Texture GetTexture(ISkinSource skin) protected override Drawable GetAnimation(ISkinSource skin)
{ {
// TODO: Should fallback to the head from default legacy skin instead of note. // TODO: Should fallback to the head from default legacy skin instead of note.
return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteTailImage) return GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteTailImage)
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage) ?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); ?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
} }
} }
} }

View File

@ -1,9 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.OpenGL.Textures;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
@ -19,7 +21,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>(); private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
private Container directionContainer; private Container directionContainer;
private Sprite noteSprite;
[CanBeNull]
private Drawable noteAnimation;
private float? minimumColumnWidth; private float? minimumColumnWidth;
@ -39,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Child = noteSprite = new Sprite { Texture = GetTexture(skin) } Child = noteAnimation = GetAnimation(skin) ?? Empty()
}; };
direction.BindTo(scrollingInfo.Direction); direction.BindTo(scrollingInfo.Direction);
@ -50,12 +54,18 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
{ {
base.Update(); base.Update();
if (noteSprite.Texture != null) Texture texture = null;
if (noteAnimation is Sprite sprite)
texture = sprite.Texture;
else if (noteAnimation is TextureAnimation textureAnimation && textureAnimation.FrameCount > 0)
texture = textureAnimation.CurrentFrame;
if (texture != null)
{ {
// The height is scaled to the minimum column width, if provided. // The height is scaled to the minimum column width, if provided.
float minimumWidth = minimumColumnWidth ?? DrawWidth; float minimumWidth = minimumColumnWidth ?? DrawWidth;
noteAnimation.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), texture.DisplayWidth);
noteSprite.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), noteSprite.Texture.DisplayWidth);
} }
} }
@ -73,9 +83,11 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
} }
} }
protected virtual Texture GetTexture(ISkinSource skin) => GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); [CanBeNull]
protected virtual Drawable GetAnimation(ISkinSource skin) => GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
protected Texture GetTextureFromLookup(ISkin skin, LegacyManiaSkinConfigurationLookups lookup) [CanBeNull]
protected Drawable GetAnimationFromLookup(ISkin skin, LegacyManiaSkinConfigurationLookups lookup)
{ {
string suffix = string.Empty; string suffix = string.Empty;
@ -93,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
string noteImage = GetColumnSkinConfig<string>(skin, lookup)?.Value string noteImage = GetColumnSkinConfig<string>(skin, lookup)?.Value
?? $"mania-note{FallbackColumnIndex}{suffix}"; ?? $"mania-note{FallbackColumnIndex}{suffix}";
return skin.GetTexture(noteImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge); return skin.GetAnimation(noteImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge, true, true);
} }
} }
} }

View File

@ -75,7 +75,6 @@ namespace osu.Game.Tests.Visual.Navigation
typeof(FileStore), typeof(FileStore),
typeof(ScoreManager), typeof(ScoreManager),
typeof(BeatmapManager), typeof(BeatmapManager),
typeof(SettingsStore),
typeof(RulesetConfigCache), typeof(RulesetConfigCache),
typeof(OsuColour), typeof(OsuColour),
typeof(IBindable<WorkingBeatmap>), typeof(IBindable<WorkingBeatmap>),

View File

@ -1,103 +0,0 @@
// 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.
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Configuration;
using osu.Game.Rulesets;
namespace osu.Game.Configuration
{
public abstract class DatabasedConfigManager<TLookup> : ConfigManager<TLookup>
where TLookup : struct, Enum
{
private readonly SettingsStore settings;
private readonly int? variant;
private List<DatabasedSetting> databasedSettings;
private readonly RulesetInfo ruleset;
private bool legacySettingsExist;
protected DatabasedConfigManager(SettingsStore settings, RulesetInfo ruleset = null, int? variant = null)
{
this.settings = settings;
this.ruleset = ruleset;
this.variant = variant;
Load();
InitialiseDefaults();
}
protected override void PerformLoad()
{
databasedSettings = settings.Query(ruleset?.ID, variant);
legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out _));
}
protected override bool PerformSave()
{
lock (dirtySettings)
{
foreach (var setting in dirtySettings)
settings.Update(setting);
dirtySettings.Clear();
}
return true;
}
private readonly List<DatabasedSetting> dirtySettings = new List<DatabasedSetting>();
protected override void AddBindable<TBindable>(TLookup lookup, Bindable<TBindable> bindable)
{
base.AddBindable(lookup, bindable);
if (legacySettingsExist)
{
var legacySetting = databasedSettings.Find(s => s.Key == ((int)(object)lookup).ToString());
if (legacySetting != null)
{
bindable.Parse(legacySetting.Value);
settings.Delete(legacySetting);
}
}
var setting = databasedSettings.Find(s => s.Key == lookup.ToString());
if (setting != null)
{
bindable.Parse(setting.Value);
}
else
{
settings.Update(setting = new DatabasedSetting
{
Key = lookup.ToString(),
Value = bindable.Value,
RulesetID = ruleset?.ID,
Variant = variant,
});
databasedSettings.Add(setting);
}
bindable.ValueChanged += b =>
{
setting.Value = b.NewValue;
lock (dirtySettings)
{
if (!dirtySettings.Contains(setting))
dirtySettings.Add(setting);
}
};
}
}
}

View File

@ -7,7 +7,7 @@ using osu.Game.Database;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
[Table("Settings")] [Table("Settings")]
public class DatabasedSetting : IHasPrimaryKey public class DatabasedSetting : IHasPrimaryKey // can be removed 20220315.
{ {
public int ID { get; set; } public int ID { get; set; }

View File

@ -0,0 +1,32 @@
// 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.
using System;
using osu.Game.Database;
using Realms;
#nullable enable
namespace osu.Game.Configuration
{
[MapTo(@"RulesetSetting")]
public class RealmRulesetSetting : RealmObject, IHasGuidPrimaryKey
{
[PrimaryKey]
public Guid ID { get; set; } = Guid.NewGuid();
[Indexed]
public int RulesetID { get; set; }
[Indexed]
public int Variant { get; set; }
[Required]
public string Key { get; set; } = string.Empty;
[Required]
public string Value { get; set; } = string.Empty;
public override string ToString() => $"{Key} => {Value}";
}
}

View File

@ -1,46 +1,20 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Game.Database; using osu.Game.Database;
namespace osu.Game.Configuration namespace osu.Game.Configuration
{ {
public class SettingsStore : DatabaseBackedStore public class SettingsStore
{ {
public event Action SettingChanged; // this class mostly exists as a wrapper to avoid breaking the ruleset API (see usage in RulesetConfigManager).
// it may cease to exist going forward, depending on how the structure of the config data layer changes.
public SettingsStore(DatabaseContextFactory contextFactory) public readonly RealmContextFactory Realm;
: base(contextFactory)
public SettingsStore(RealmContextFactory realmFactory)
{ {
} Realm = realmFactory;
/// <summary>
/// Retrieve <see cref="DatabasedSetting"/>s for a specified ruleset/variant content.
/// </summary>
/// <param name="rulesetId">The ruleset's internal ID.</param>
/// <param name="variant">An optional variant.</param>
public List<DatabasedSetting> Query(int? rulesetId = null, int? variant = null) =>
ContextFactory.Get().DatabasedSetting.Where(b => b.RulesetID == rulesetId && b.Variant == variant).ToList();
public void Update(DatabasedSetting setting)
{
using (ContextFactory.GetForWrite())
{
var newValue = setting.Value;
Refresh(ref setting);
setting.Value = newValue;
}
SettingChanged?.Invoke();
}
public void Delete(DatabasedSetting setting)
{
using (var usage = ContextFactory.GetForWrite())
usage.Context.Remove(setting);
} }
} }
} }

View File

@ -12,7 +12,6 @@ using osu.Game.Configuration;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Scoring; using osu.Game.Scoring;
using DatabasedKeyBinding = osu.Game.Input.Bindings.DatabasedKeyBinding;
using LogLevel = Microsoft.Extensions.Logging.LogLevel; using LogLevel = Microsoft.Extensions.Logging.LogLevel;
using osu.Game.Skinning; using osu.Game.Skinning;
@ -24,14 +23,13 @@ namespace osu.Game.Database
public DbSet<BeatmapDifficulty> BeatmapDifficulty { get; set; } public DbSet<BeatmapDifficulty> BeatmapDifficulty { get; set; }
public DbSet<BeatmapMetadata> BeatmapMetadata { get; set; } public DbSet<BeatmapMetadata> BeatmapMetadata { get; set; }
public DbSet<BeatmapSetInfo> BeatmapSetInfo { get; set; } public DbSet<BeatmapSetInfo> BeatmapSetInfo { get; set; }
public DbSet<DatabasedSetting> DatabasedSetting { get; set; }
public DbSet<FileInfo> FileInfo { get; set; } public DbSet<FileInfo> FileInfo { get; set; }
public DbSet<RulesetInfo> RulesetInfo { get; set; } public DbSet<RulesetInfo> RulesetInfo { get; set; }
public DbSet<SkinInfo> SkinInfo { get; set; } public DbSet<SkinInfo> SkinInfo { get; set; }
public DbSet<ScoreInfo> ScoreInfo { get; set; } public DbSet<ScoreInfo> ScoreInfo { get; set; }
// migrated to realm // migrated to realm
public DbSet<DatabasedKeyBinding> DatabasedKeyBinding { get; set; } public DbSet<DatabasedSetting> DatabasedSetting { get; set; }
private readonly string connectionString; private readonly string connectionString;
@ -138,11 +136,6 @@ namespace osu.Game.Database
modelBuilder.Entity<SkinInfo>().HasIndex(b => b.Hash).IsUnique(); modelBuilder.Entity<SkinInfo>().HasIndex(b => b.Hash).IsUnique();
modelBuilder.Entity<SkinInfo>().HasIndex(b => b.DeletePending); modelBuilder.Entity<SkinInfo>().HasIndex(b => b.DeletePending);
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => new { b.RulesetID, b.Variant });
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => b.IntAction);
modelBuilder.Entity<DatabasedKeyBinding>().Ignore(b => b.KeyCombination);
modelBuilder.Entity<DatabasedKeyBinding>().Ignore(b => b.Action);
modelBuilder.Entity<DatabasedSetting>().HasIndex(b => new { b.RulesetID, b.Variant }); modelBuilder.Entity<DatabasedSetting>().HasIndex(b => new { b.RulesetID, b.Variant });
modelBuilder.Entity<FileInfo>().HasIndex(b => b.Hash).IsUnique(); modelBuilder.Entity<FileInfo>().HasIndex(b => b.Hash).IsUnique();

View File

@ -1,39 +0,0 @@
// 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.
using System.ComponentModel.DataAnnotations.Schema;
using osu.Framework.Input.Bindings;
using osu.Game.Database;
namespace osu.Game.Input.Bindings
{
[Table("KeyBinding")]
public class DatabasedKeyBinding : IKeyBinding, IHasPrimaryKey
{
public int ID { get; set; }
public int? RulesetID { get; set; }
public int? Variant { get; set; }
[Column("Keys")]
public string KeysString { get; set; }
[Column("Action")]
public int IntAction { get; set; }
[NotMapped]
public KeyCombination KeyCombination
{
get => KeysString;
set => KeysString = value.ToString();
}
[NotMapped]
public object Action
{
get => IntAction;
set => IntAction = (int)value;
}
}
}

View File

@ -140,8 +140,6 @@ namespace osu.Game
private FileStore fileStore; private FileStore fileStore;
private SettingsStore settingsStore;
private RulesetConfigCache rulesetConfigCache; private RulesetConfigCache rulesetConfigCache;
private SpectatorClient spectatorClient; private SpectatorClient spectatorClient;
@ -279,8 +277,7 @@ namespace osu.Game
migrateDataToRealm(); migrateDataToRealm();
dependencies.Cache(settingsStore = new SettingsStore(contextFactory)); dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(realmFactory, RulesetStore));
dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(settingsStore));
var powerStatus = CreateBatteryInfo(); var powerStatus = CreateBatteryInfo();
if (powerStatus != null) if (powerStatus != null)
@ -453,24 +450,27 @@ namespace osu.Game
using (var db = contextFactory.GetForWrite()) using (var db = contextFactory.GetForWrite())
using (var usage = realmFactory.GetForWrite()) using (var usage = realmFactory.GetForWrite())
{ {
var existingBindings = db.Context.DatabasedKeyBinding; // migrate ruleset settings. can be removed 20220315.
var existingSettings = db.Context.DatabasedSetting;
// only migrate data if the realm database is empty. // only migrate data if the realm database is empty.
if (!usage.Realm.All<RealmKeyBinding>().Any()) if (!usage.Realm.All<RealmRulesetSetting>().Any())
{ {
foreach (var dkb in existingBindings) foreach (var dkb in existingSettings)
{ {
usage.Realm.Add(new RealmKeyBinding if (dkb.RulesetID == null) continue;
usage.Realm.Add(new RealmRulesetSetting
{ {
KeyCombinationString = dkb.KeyCombination.ToString(), Key = dkb.Key,
ActionInt = (int)dkb.Action, Value = dkb.StringValue,
RulesetID = dkb.RulesetID, RulesetID = dkb.RulesetID.Value,
Variant = dkb.Variant Variant = dkb.Variant ?? 0,
}); });
} }
} }
db.Context.RemoveRange(existingBindings); db.Context.RemoveRange(existingSettings);
usage.Commit(); usage.Commit();
} }

View File

@ -2,16 +2,86 @@
// 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; using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Configuration;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Database;
namespace osu.Game.Rulesets.Configuration namespace osu.Game.Rulesets.Configuration
{ {
public abstract class RulesetConfigManager<TLookup> : DatabasedConfigManager<TLookup>, IRulesetConfigManager public abstract class RulesetConfigManager<TLookup> : ConfigManager<TLookup>, IRulesetConfigManager
where TLookup : struct, Enum where TLookup : struct, Enum
{ {
protected RulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) private readonly RealmContextFactory realmFactory;
: base(settings, ruleset, variant)
private readonly int variant;
private List<RealmRulesetSetting> databasedSettings = new List<RealmRulesetSetting>();
private readonly int rulesetId;
protected RulesetConfigManager(SettingsStore store, RulesetInfo ruleset, int? variant = null)
{ {
realmFactory = store?.Realm;
if (realmFactory != null && !ruleset.ID.HasValue)
throw new InvalidOperationException("Attempted to add databased settings for a non-databased ruleset");
rulesetId = ruleset.ID ?? -1;
this.variant = variant ?? 0;
Load();
InitialiseDefaults();
}
protected override void PerformLoad()
{
if (realmFactory != null)
{
// As long as RulesetConfigCache exists, there is no need to subscribe to realm events.
databasedSettings = realmFactory.Context.All<RealmRulesetSetting>().Where(b => b.RulesetID == rulesetId && b.Variant == variant).ToList();
}
}
protected override bool PerformSave()
{
// do nothing, realm saves immediately
return true;
}
protected override void AddBindable<TBindable>(TLookup lookup, Bindable<TBindable> bindable)
{
base.AddBindable(lookup, bindable);
var setting = databasedSettings.Find(s => s.Key == lookup.ToString());
if (setting != null)
{
bindable.Parse(setting.Value);
}
else
{
setting = new RealmRulesetSetting
{
Key = lookup.ToString(),
Value = bindable.Value.ToString(),
RulesetID = rulesetId,
Variant = variant,
};
realmFactory?.Context.Write(() => realmFactory.Context.Add(setting));
databasedSettings.Add(setting);
}
bindable.ValueChanged += b =>
{
realmFactory?.Context.Write(() => setting.Value = b.NewValue.ToString());
};
} }
} }
} }

View File

@ -2,9 +2,10 @@
// 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; using System;
using System.Collections.Concurrent; using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Configuration;
namespace osu.Game.Rulesets namespace osu.Game.Rulesets
@ -15,12 +16,31 @@ namespace osu.Game.Rulesets
/// </summary> /// </summary>
public class RulesetConfigCache : Component public class RulesetConfigCache : Component
{ {
private readonly ConcurrentDictionary<int, IRulesetConfigManager> configCache = new ConcurrentDictionary<int, IRulesetConfigManager>(); private readonly RealmContextFactory realmFactory;
private readonly SettingsStore settingsStore; private readonly RulesetStore rulesets;
public RulesetConfigCache(SettingsStore settingsStore) private readonly Dictionary<int, IRulesetConfigManager> configCache = new Dictionary<int, IRulesetConfigManager>();
public RulesetConfigCache(RealmContextFactory realmFactory, RulesetStore rulesets)
{ {
this.settingsStore = settingsStore; this.realmFactory = realmFactory;
this.rulesets = rulesets;
}
protected override void LoadComplete()
{
base.LoadComplete();
var settingsStore = new SettingsStore(realmFactory);
// let's keep things simple for now and just retrieve all the required configs at startup..
foreach (var ruleset in rulesets.AvailableRulesets)
{
if (ruleset.ID == null)
continue;
configCache[ruleset.ID.Value] = ruleset.CreateInstance().CreateConfig(settingsStore);
}
} }
/// <summary> /// <summary>
@ -34,7 +54,12 @@ namespace osu.Game.Rulesets
if (ruleset.RulesetInfo.ID == null) if (ruleset.RulesetInfo.ID == null)
return null; return null;
return configCache.GetOrAdd(ruleset.RulesetInfo.ID.Value, _ => ruleset.CreateConfig(settingsStore)); if (!configCache.TryGetValue(ruleset.RulesetInfo.ID.Value, out var config))
// any ruleset request which wasn't initialised on startup should not be stored to realm.
// this should only be used by tests.
return ruleset.CreateConfig(null);
return config;
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -17,10 +18,12 @@ namespace osu.Game.Skinning
{ {
public static class LegacySkinExtensions public static class LegacySkinExtensions
{ {
[CanBeNull]
public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-", public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-",
bool startAtCurrentTime = true, double? frameLength = null) bool startAtCurrentTime = true, double? frameLength = null)
=> source.GetAnimation(componentName, default, default, animatable, looping, applyConfigFrameRate, animationSeparator, startAtCurrentTime, frameLength); => source.GetAnimation(componentName, default, default, animatable, looping, applyConfigFrameRate, animationSeparator, startAtCurrentTime, frameLength);
[CanBeNull]
public static Drawable GetAnimation(this ISkin source, string componentName, WrapMode wrapModeS, WrapMode wrapModeT, bool animatable, bool looping, bool applyConfigFrameRate = false, public static Drawable GetAnimation(this ISkin source, string componentName, WrapMode wrapModeS, WrapMode wrapModeT, bool animatable, bool looping, bool applyConfigFrameRate = false,
string animationSeparator = "-", string animationSeparator = "-",
bool startAtCurrentTime = true, double? frameLength = null) bool startAtCurrentTime = true, double? frameLength = null)

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.ObjectExtensions;
using osu.Game.Configuration;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Extensions; using osu.Game.Extensions;
using osu.Game.IO; using osu.Game.IO;
@ -39,8 +38,6 @@ namespace osu.Game.Skinning
public List<SkinFileInfo> Files { get; set; } = new List<SkinFileInfo>(); public List<SkinFileInfo> Files { get; set; } = new List<SkinFileInfo>();
public List<DatabasedSetting> Settings { get; set; }
public bool DeletePending { get; set; } public bool DeletePending { get; set; }
public static SkinInfo Default { get; } = new SkinInfo public static SkinInfo Default { get; } = new SkinInfo

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Linq;
using Microsoft.EntityFrameworkCore;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Database; using osu.Game.Database;
@ -14,9 +12,5 @@ namespace osu.Game.Skinning
: base(contextFactory, storage) : base(contextFactory, storage)
{ {
} }
protected override IQueryable<SkinInfo> AddIncludesForDeletion(IQueryable<SkinInfo> query) =>
base.AddIncludesForDeletion(query)
.Include(s => s.Settings); // don't include FileInfo. these are handled by the FileStore itself.
} }
} }

View File

@ -35,7 +35,7 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Realm" Version="10.3.0" /> <PackageReference Include="Realm" Version="10.5.0" />
<PackageReference Include="ppy.osu.Framework" Version="2021.907.0" /> <PackageReference Include="ppy.osu.Framework" Version="2021.907.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.913.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2021.913.0" />
<PackageReference Include="Sentry" Version="3.9.0" /> <PackageReference Include="Sentry" Version="3.9.0" />