Merge branch 'master' into inheritable-allow-track-adjust
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.9 KiB |
@ -1,18 +1,18 @@
|
||||
// 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 osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
{
|
||||
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.
|
||||
return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
|
||||
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||
return GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
|
||||
?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
@ -18,12 +18,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
: 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.
|
||||
return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteTailImage)
|
||||
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
|
||||
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||
return GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteTailImage)
|
||||
?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
|
||||
?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
// 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 JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
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 Container directionContainer;
|
||||
private Sprite noteSprite;
|
||||
|
||||
[CanBeNull]
|
||||
private Drawable noteAnimation;
|
||||
|
||||
private float? minimumColumnWidth;
|
||||
|
||||
@ -39,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
Origin = Anchor.BottomCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = noteSprite = new Sprite { Texture = GetTexture(skin) }
|
||||
Child = noteAnimation = GetAnimation(skin) ?? Empty()
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
@ -50,12 +54,18 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
{
|
||||
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.
|
||||
float minimumWidth = minimumColumnWidth ?? DrawWidth;
|
||||
|
||||
noteSprite.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), noteSprite.Texture.DisplayWidth);
|
||||
noteAnimation.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), 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;
|
||||
|
||||
@ -93,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
string noteImage = GetColumnSkinConfig<string>(skin, lookup)?.Value
|
||||
?? $"mania-note{FallbackColumnIndex}{suffix}";
|
||||
|
||||
return skin.GetTexture(noteImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge);
|
||||
return skin.GetAnimation(noteImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,6 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
typeof(FileStore),
|
||||
typeof(ScoreManager),
|
||||
typeof(BeatmapManager),
|
||||
typeof(SettingsStore),
|
||||
typeof(RulesetConfigCache),
|
||||
typeof(OsuColour),
|
||||
typeof(IBindable<WorkingBeatmap>),
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using osu.Game.Database;
|
||||
namespace osu.Game.Configuration
|
||||
{
|
||||
[Table("Settings")]
|
||||
public class DatabasedSetting : IHasPrimaryKey
|
||||
public class DatabasedSetting : IHasPrimaryKey // can be removed 20220315.
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
|
32
osu.Game/Configuration/RealmRulesetSetting.cs
Normal 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}";
|
||||
}
|
||||
}
|
@ -1,46 +1,20 @@
|
||||
// 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.Game.Database;
|
||||
|
||||
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)
|
||||
: base(contextFactory)
|
||||
public readonly RealmContextFactory Realm;
|
||||
|
||||
public SettingsStore(RealmContextFactory 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);
|
||||
Realm = realmFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ using osu.Game.Configuration;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
using DatabasedKeyBinding = osu.Game.Input.Bindings.DatabasedKeyBinding;
|
||||
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
@ -24,14 +23,13 @@ namespace osu.Game.Database
|
||||
public DbSet<BeatmapDifficulty> BeatmapDifficulty { get; set; }
|
||||
public DbSet<BeatmapMetadata> BeatmapMetadata { get; set; }
|
||||
public DbSet<BeatmapSetInfo> BeatmapSetInfo { get; set; }
|
||||
public DbSet<DatabasedSetting> DatabasedSetting { get; set; }
|
||||
public DbSet<FileInfo> FileInfo { get; set; }
|
||||
public DbSet<RulesetInfo> RulesetInfo { get; set; }
|
||||
public DbSet<SkinInfo> SkinInfo { get; set; }
|
||||
public DbSet<ScoreInfo> ScoreInfo { get; set; }
|
||||
|
||||
// migrated to realm
|
||||
public DbSet<DatabasedKeyBinding> DatabasedKeyBinding { get; set; }
|
||||
public DbSet<DatabasedSetting> DatabasedSetting { get; set; }
|
||||
|
||||
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.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<FileInfo>().HasIndex(b => b.Hash).IsUnique();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -140,8 +140,6 @@ namespace osu.Game
|
||||
|
||||
private FileStore fileStore;
|
||||
|
||||
private SettingsStore settingsStore;
|
||||
|
||||
private RulesetConfigCache rulesetConfigCache;
|
||||
|
||||
private SpectatorClient spectatorClient;
|
||||
@ -279,8 +277,7 @@ namespace osu.Game
|
||||
|
||||
migrateDataToRealm();
|
||||
|
||||
dependencies.Cache(settingsStore = new SettingsStore(contextFactory));
|
||||
dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(settingsStore));
|
||||
dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(realmFactory, RulesetStore));
|
||||
|
||||
var powerStatus = CreateBatteryInfo();
|
||||
if (powerStatus != null)
|
||||
@ -453,24 +450,27 @@ namespace osu.Game
|
||||
using (var db = contextFactory.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.
|
||||
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(),
|
||||
ActionInt = (int)dkb.Action,
|
||||
RulesetID = dkb.RulesetID,
|
||||
Variant = dkb.Variant
|
||||
Key = dkb.Key,
|
||||
Value = dkb.StringValue,
|
||||
RulesetID = dkb.RulesetID.Value,
|
||||
Variant = dkb.Variant ?? 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
db.Context.RemoveRange(existingBindings);
|
||||
db.Context.RemoveRange(existingSettings);
|
||||
|
||||
usage.Commit();
|
||||
}
|
||||
|
@ -2,16 +2,86 @@
|
||||
// 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.Configuration;
|
||||
using osu.Game.Database;
|
||||
|
||||
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
|
||||
{
|
||||
protected RulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null)
|
||||
: base(settings, ruleset, variant)
|
||||
private readonly RealmContextFactory realmFactory;
|
||||
|
||||
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());
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,10 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
|
||||
namespace osu.Game.Rulesets
|
||||
@ -15,12 +16,31 @@ namespace osu.Game.Rulesets
|
||||
/// </summary>
|
||||
public class RulesetConfigCache : Component
|
||||
{
|
||||
private readonly ConcurrentDictionary<int, IRulesetConfigManager> configCache = new ConcurrentDictionary<int, IRulesetConfigManager>();
|
||||
private readonly SettingsStore settingsStore;
|
||||
private readonly RealmContextFactory realmFactory;
|
||||
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>
|
||||
@ -34,7 +54,12 @@ namespace osu.Game.Rulesets
|
||||
if (ruleset.RulesetInfo.ID == 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)
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@ -17,10 +18,12 @@ namespace osu.Game.Skinning
|
||||
{
|
||||
public static class LegacySkinExtensions
|
||||
{
|
||||
[CanBeNull]
|
||||
public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-",
|
||||
bool startAtCurrentTime = true, double? frameLength = null)
|
||||
=> 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,
|
||||
string animationSeparator = "-",
|
||||
bool startAtCurrentTime = true, double? frameLength = null)
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.IO;
|
||||
@ -39,8 +38,6 @@ namespace osu.Game.Skinning
|
||||
|
||||
public List<SkinFileInfo> Files { get; set; } = new List<SkinFileInfo>();
|
||||
|
||||
public List<DatabasedSetting> Settings { get; set; }
|
||||
|
||||
public bool DeletePending { get; set; }
|
||||
|
||||
public static SkinInfo Default { get; } = new SkinInfo
|
||||
|
@ -1,8 +1,6 @@
|
||||
// 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.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
|
||||
@ -14,9 +12,5 @@ namespace osu.Game.Skinning
|
||||
: 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.
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</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.Game.Resources" Version="2021.913.0" />
|
||||
<PackageReference Include="Sentry" Version="3.9.0" />
|
||||
|