1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 12:02:55 +08:00

Expose available mod state outwardly as a bindable

This commit is contained in:
Bartłomiej Dach 2022-05-25 22:20:10 +02:00
parent f0303d76e8
commit 071e158a29
No known key found for this signature in database
GPG Key ID: BCECCD4FA41F6497

View File

@ -34,6 +34,15 @@ namespace osu.Game.Overlays.Mods
[Cached]
public Bindable<IReadOnlyList<Mod>> SelectedMods { get; private set; } = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
/// <summary>
/// Contains a dictionary with the current <see cref="ModState"/> of all mods applicable for the current ruleset.
/// </summary>
/// <remarks>
/// Contrary to <see cref="OsuGameBase.AvailableMods"/> and <see cref="globalAvailableMods"/>, the <see cref="Mod"/> instances
/// inside the <see cref="ModState"/> objects are owned solely by this <see cref="ModSelectOverlay"/> instance.
/// </remarks>
public Bindable<Dictionary<ModType, IReadOnlyList<ModState>>> AvailableMods { get; } = new Bindable<Dictionary<ModType, IReadOnlyList<ModState>>>(new Dictionary<ModType, IReadOnlyList<ModState>>());
private Func<Mod, bool> isValidMod = m => true;
/// <summary>
@ -79,9 +88,9 @@ namespace osu.Game.Overlays.Mods
yield return new DeselectAllModsButton(this);
}
private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> availableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>();
private readonly Dictionary<ModType, IReadOnlyList<ModState>> localAvailableMods = new Dictionary<ModType, IReadOnlyList<ModState>>();
private IEnumerable<ModState> allLocalAvailableMods => localAvailableMods.SelectMany(pair => pair.Value);
private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> globalAvailableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>();
private IEnumerable<ModState> allAvailableMods => AvailableMods.Value.SelectMany(pair => pair.Value);
private readonly BindableBool customisationVisible = new BindableBool();
@ -204,13 +213,13 @@ namespace osu.Game.Overlays.Mods
})
};
availableMods.BindTo(game.AvailableMods);
globalAvailableMods.BindTo(game.AvailableMods);
}
protected override void LoadComplete()
{
// this is called before base call so that the mod state is populated early, and the transition in `PopIn()` can play out properly.
availableMods.BindValueChanged(_ => createLocalMods(), true);
globalAvailableMods.BindValueChanged(_ => createLocalMods(), true);
base.LoadComplete();
@ -275,9 +284,9 @@ namespace osu.Game.Overlays.Mods
private void createLocalMods()
{
localAvailableMods.Clear();
var newLocalAvailableMods = new Dictionary<ModType, IReadOnlyList<ModState>>();
foreach (var (modType, mods) in availableMods.Value)
foreach (var (modType, mods) in globalAvailableMods.Value)
{
var modStates = mods.SelectMany(ModUtils.FlattenMod)
.Select(mod => new ModState(mod.DeepClone()))
@ -286,18 +295,19 @@ namespace osu.Game.Overlays.Mods
foreach (var modState in modStates)
modState.Active.BindValueChanged(_ => updateFromInternalSelection());
localAvailableMods[modType] = modStates;
newLocalAvailableMods[modType] = modStates;
}
AvailableMods.Value = newLocalAvailableMods;
filterMods();
foreach (var column in columnFlow.Columns)
column.AvailableMods = localAvailableMods.GetValueOrDefault(column.ModType, Array.Empty<ModState>());
column.AvailableMods = AvailableMods.Value.GetValueOrDefault(column.ModType, Array.Empty<ModState>());
}
private void filterMods()
{
foreach (var modState in allLocalAvailableMods)
foreach (var modState in allAvailableMods)
modState.Filtered.Value = !modState.Mod.HasImplementation || !IsValidMod.Invoke(modState.Mod);
}
@ -378,7 +388,7 @@ namespace osu.Game.Overlays.Mods
var newSelection = new List<Mod>();
foreach (var modState in allLocalAvailableMods)
foreach (var modState in allAvailableMods)
{
var matchingSelectedMod = SelectedMods.Value.SingleOrDefault(selected => selected.GetType() == modState.Mod.GetType());
@ -405,9 +415,9 @@ namespace osu.Game.Overlays.Mods
if (externalSelectionUpdateInProgress)
return;
var candidateSelection = allLocalAvailableMods.Where(modState => modState.Active.Value)
.Select(modState => modState.Mod)
.ToArray();
var candidateSelection = allAvailableMods.Where(modState => modState.Active.Value)
.Select(modState => modState.Mod)
.ToArray();
SelectedMods.Value = ComputeNewModsFromSelection(SelectedMods.Value, candidateSelection);
}