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

Fix propagation of selected mods to columns

This commit is contained in:
Bartłomiej Dach 2022-03-28 00:16:10 +02:00
parent 2921a13609
commit cd776d21a6
No known key found for this signature in database
GPG Key ID: BCECCD4FA41F6497
2 changed files with 64 additions and 21 deletions

View File

@ -31,6 +31,8 @@ namespace osu.Game.Overlays.Mods
{
public class ModColumn : CompositeDrawable
{
public readonly ModType ModType;
private Func<Mod, bool>? filter;
/// <summary>
@ -48,9 +50,8 @@ namespace osu.Game.Overlays.Mods
}
}
public Action<Mod, bool>? ModStateChanged { get; set; }
public Bindable<IReadOnlyList<Mod>> SelectedMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
private readonly ModType modType;
private readonly Key[]? toggleKeys;
private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> availableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>();
@ -71,7 +72,7 @@ namespace osu.Game.Overlays.Mods
public ModColumn(ModType modType, bool allowBulkSelection, Key[]? toggleKeys = null)
{
this.modType = modType;
ModType = modType;
this.toggleKeys = toggleKeys;
Width = 320;
@ -195,7 +196,7 @@ namespace osu.Game.Overlays.Mods
private void createHeaderText()
{
IEnumerable<string> headerTextWords = modType.Humanize(LetterCasing.Title).Split(' ');
IEnumerable<string> headerTextWords = ModType.Humanize(LetterCasing.Title).Split(' ');
if (headerTextWords.Count() > 1)
{
@ -211,7 +212,7 @@ namespace osu.Game.Overlays.Mods
{
availableMods.BindTo(game.AvailableMods);
headerBackground.Colour = accentColour = colours.ForModType(modType);
headerBackground.Colour = accentColour = colours.ForModType(ModType);
if (toggleAllCheckbox != null)
{
@ -227,6 +228,12 @@ namespace osu.Game.Overlays.Mods
{
base.LoadComplete();
availableMods.BindValueChanged(_ => Scheduler.AddOnce(updateMods));
SelectedMods.BindValueChanged(_ =>
{
// if a load is in progress, don't try to update the selection - the load flow will do so.
if (latestLoadTask == null)
updateActiveState();
});
updateMods();
}
@ -234,7 +241,7 @@ namespace osu.Game.Overlays.Mods
private void updateMods()
{
var newMods = ModUtils.FlattenMods(availableMods.Value.GetValueOrDefault(modType) ?? Array.Empty<Mod>()).ToList();
var newMods = ModUtils.FlattenMods(availableMods.Value.GetValueOrDefault(ModType) ?? Array.Empty<Mod>()).ToList();
if (newMods.SequenceEqual(panelFlow.Children.Select(p => p.Mod)))
return;
@ -252,18 +259,20 @@ namespace osu.Game.Overlays.Mods
{
panelFlow.ChildrenEnumerable = loaded;
updateActiveState();
updateToggleAllState();
updateFilter();
foreach (var panel in panelFlow)
{
panel.Active.BindValueChanged(_ =>
{
updateToggleState();
ModStateChanged?.Invoke(panel.Mod, panel.Active.Value);
updateToggleAllState();
SelectedMods.Value = panel.Active.Value
? SelectedMods.Value.Append(panel.Mod).ToArray()
: SelectedMods.Value.Except(new[] { panel.Mod }).ToArray();
});
}
updateToggleState();
updateFilter();
}, (cancellationTokenSource = new CancellationTokenSource()).Token);
loadTask.ContinueWith(_ =>
{
@ -272,6 +281,12 @@ namespace osu.Game.Overlays.Mods
});
}
private void updateActiveState()
{
foreach (var panel in panelFlow)
panel.Active.Value = SelectedMods.Value.Contains(panel.Mod, EqualityComparer<Mod>.Default);
}
#region Bulk select / deselect
private const double initial_multiple_selection_delay = 120;
@ -306,7 +321,7 @@ namespace osu.Game.Overlays.Mods
}
}
private void updateToggleState()
private void updateToggleAllState()
{
if (toggleAllCheckbox != null && !SelectionAnimationRunning)
{
@ -408,7 +423,7 @@ namespace osu.Game.Overlays.Mods
foreach (var modPanel in panelFlow)
modPanel.ApplyFilter(Filter);
updateToggleState();
updateToggleAllState();
}
#endregion

View File

@ -167,13 +167,6 @@ namespace osu.Game.Overlays.Mods
}
};
foreach (var column in columnFlow)
{
column.ModStateChanged = (mod, active) => SelectedMods.Value = active
? SelectedMods.Value.Append(mod).ToArray()
: SelectedMods.Value.Except(new[] { mod }).ToArray();
}
columnFlow.Shear = new Vector2(ModPanel.SHEAR_X, 0);
}
@ -182,11 +175,19 @@ namespace osu.Game.Overlays.Mods
base.LoadComplete();
((IBindable<IReadOnlyList<Mod>>)modSettingsArea.SelectedMods).BindTo(SelectedMods);
SelectedMods.BindValueChanged(val =>
{
updateMultiplier();
updateCustomisation(val);
updateSelectionFromBindable();
}, true);
foreach (var column in columnFlow)
{
column.SelectedMods.BindValueChanged(_ => updateBindableFromSelection());
}
customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true);
FinishTransforms(true);
@ -239,6 +240,33 @@ namespace osu.Game.Overlays.Mods
mainContent.TransformTo(nameof(Margin), new MarginPadding { Bottom = modAreaHeight }, 800, Easing.InOutCubic);
}
private bool selectionBindableSyncInProgress;
private void updateSelectionFromBindable()
{
if (selectionBindableSyncInProgress)
return;
selectionBindableSyncInProgress = true;
foreach (var column in columnFlow)
column.SelectedMods.Value = SelectedMods.Value.Where(mod => mod.Type == column.ModType).ToArray();
selectionBindableSyncInProgress = false;
}
private void updateBindableFromSelection()
{
if (selectionBindableSyncInProgress)
return;
selectionBindableSyncInProgress = true;
SelectedMods.Value = columnFlow.SelectMany(column => column.SelectedMods.Value).ToArray();
selectionBindableSyncInProgress = false;
}
protected override void PopIn()
{
base.PopIn();