1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 11:20:04 +08:00

Simplify skin bindable flow

Now, nothing touches the configuration apart from `OsuGame`, making
everything else flow better and avoid weird cyclic set bugs.

Closes https://github.com/ppy/osu/issues/20234.
This commit is contained in:
Dean Herbert 2022-09-12 19:51:49 +09:00
parent cb6d02ec3a
commit f31deaef7c
3 changed files with 36 additions and 70 deletions

View File

@ -56,14 +56,12 @@ using osu.Game.Screens.Menu;
using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Select;
using osu.Game.Skinning;
using osu.Game.Skinning.Editor;
using osu.Game.Updater;
using osu.Game.Users;
using osu.Game.Utils;
using osuTK.Graphics;
using Sentry;
using Logger = osu.Framework.Logging.Logger;
namespace osu.Game
{
@ -294,25 +292,13 @@ namespace osu.Game
Ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ShortName;
// bind config int to database SkinInfo
configSkin = LocalConfig.GetBindable<string>(OsuSetting.Skin);
// Transfer skin from config to realm instance once on startup.
SkinManager.SetSkinFromConfiguration(configSkin.Value);
// Transfer any runtime changes back to configuration file.
SkinManager.CurrentSkinInfo.ValueChanged += skin => configSkin.Value = skin.NewValue.ID.ToString();
configSkin.ValueChanged += skinId =>
{
Live<SkinInfo> skinInfo = null;
if (Guid.TryParse(skinId.NewValue, out var guid))
skinInfo = SkinManager.Query(s => s.ID == guid);
if (skinInfo == null)
{
if (guid == SkinInfo.CLASSIC_SKIN)
skinInfo = DefaultLegacySkin.CreateInfo().ToLiveUnmanaged();
}
SkinManager.CurrentSkinInfo.Value = skinInfo ?? DefaultSkin.CreateInfo().ToLiveUnmanaged();
};
configSkin.TriggerChange();
IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true);

View File

@ -14,7 +14,6 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
@ -36,9 +35,6 @@ namespace osu.Game.Overlays.Settings.Sections
Icon = FontAwesome.Solid.PaintBrush
};
private readonly Bindable<Live<SkinInfo>> dropdownBindable = new Bindable<Live<SkinInfo>> { Default = DefaultSkin.CreateInfo().ToLiveUnmanaged() };
private readonly Bindable<string> configBindable = new Bindable<string>();
private static readonly Live<SkinInfo> random_skin_info = new SkinInfo
{
ID = SkinInfo.RANDOM_SKIN,
@ -56,13 +52,14 @@ namespace osu.Game.Overlays.Settings.Sections
private IDisposable realmSubscription;
[BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuConfigManager config, [CanBeNull] SkinEditorOverlay skinEditor)
private void load([CanBeNull] SkinEditorOverlay skinEditor)
{
Children = new Drawable[]
{
skinDropdown = new SkinSettingsDropdown
{
LabelText = SkinSettingsStrings.CurrentSkin,
Current = skins.CurrentSkinInfo,
Keywords = new[] { @"skins" }
},
new SettingsButton
@ -73,47 +70,30 @@ namespace osu.Game.Overlays.Settings.Sections
new ExportSkinButton(),
new DeleteSkinButton(),
};
config.BindWith(OsuSetting.Skin, configBindable);
}
protected override void LoadComplete()
{
base.LoadComplete();
skinDropdown.Current = dropdownBindable;
skinDropdown.Current = skins.CurrentSkinInfo;
realmSubscription = realm.RegisterForNotifications(_ => realm.Realm.All<SkinInfo>()
.Where(s => !s.DeletePending)
.OrderByDescending(s => s.Protected) // protected skins should be at the top.
.ThenBy(s => s.Name, StringComparer.OrdinalIgnoreCase), skinsChanged);
configBindable.BindValueChanged(_ => Scheduler.AddOnce(updateSelectedSkinFromConfig));
dropdownBindable.BindValueChanged(dropdownSelectionChanged);
}
private void dropdownSelectionChanged(ValueChangedEvent<Live<SkinInfo>> skin)
{
// Only handle cases where it's clear the user has intent to change skins.
if (skin.OldValue == null) return;
if (skin.NewValue.Equals(random_skin_info))
skinDropdown.Current.BindValueChanged(skin =>
{
var skinBefore = skins.CurrentSkinInfo.Value;
skins.SelectRandomSkin();
if (skinBefore == skins.CurrentSkinInfo.Value)
if (skin.NewValue == random_skin_info)
{
// the random selection didn't change the skin, so we should manually update the dropdown to match.
dropdownBindable.Value = skins.CurrentSkinInfo.Value;
// before selecting random, set the skin back to the previous selection.
// this is done because at this point it will be random_skin_info, and would
// cause SelectRandomSkin to be unable to skip the previous selection.
skins.CurrentSkinInfo.Value = skin.OldValue;
skins.SelectRandomSkin();
}
return;
}
configBindable.Value = skin.NewValue.ID.ToString();
});
}
private void skinsChanged(IRealmCollection<SkinInfo> sender, ChangeSet changes, Exception error)
@ -132,25 +112,7 @@ namespace osu.Game.Overlays.Settings.Sections
dropdownItems.Add(skin.ToLive(realm));
dropdownItems.Insert(protectedCount, random_skin_info);
Schedule(() =>
{
skinDropdown.Items = dropdownItems;
updateSelectedSkinFromConfig();
});
}
private void updateSelectedSkinFromConfig()
{
if (!skinDropdown.Items.Any())
return;
Live<SkinInfo> skin = null;
if (Guid.TryParse(configBindable.Value, out var configId))
skin = skinDropdown.Items.FirstOrDefault(s => s.ID == configId);
dropdownBindable.Value = skin ?? skinDropdown.Items.First();
Schedule(() => skinDropdown.Items = dropdownItems);
}
protected override void Dispose(bool isDisposing)

View File

@ -119,7 +119,9 @@ namespace osu.Game.Skinning
Realm.Run(r =>
{
// choose from only user skins, removing the current selection to ensure a new one is chosen.
var randomChoices = r.All<SkinInfo>().Where(s => !s.DeletePending && s.ID != CurrentSkinInfo.Value.ID).ToArray();
var randomChoices = r.All<SkinInfo>()
.Where(s => !s.DeletePending && s.ID != CurrentSkinInfo.Value.ID)
.ToArray();
if (randomChoices.Length == 0)
{
@ -297,5 +299,21 @@ namespace osu.Game.Skinning
Delete(items.ToList(), silent);
});
}
public void SetSkinFromConfiguration(string guidString)
{
Live<SkinInfo> skinInfo = null;
if (Guid.TryParse(guidString, out var guid))
skinInfo = Query(s => s.ID == guid);
if (skinInfo == null)
{
if (guid == SkinInfo.CLASSIC_SKIN)
skinInfo = DefaultLegacySkin.SkinInfo;
}
CurrentSkinInfo.Value = skinInfo ?? DefaultSkin.SkinInfo;
}
}
}