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

Merge pull request #18126 from bdach/mod-overlay/fix-broken-mod-reference-logic

Fix several issues with new mod select reference replacement logic
This commit is contained in:
Dean Herbert 2022-05-07 14:36:05 +09:00 committed by GitHub
commit 2dd9899cd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 40 deletions

View File

@ -6,24 +6,19 @@ using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Overlays.Mods;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens.OnlinePlay;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneFreeModSelectScreen : MultiplayerTestScene
{
private FreeModSelectScreen freeModSelectScreen;
[Test]
public void TestFreeModSelect()
{
FreeModSelectScreen freeModSelectScreen = null;
AddStep("create free mod select screen", () => Child = freeModSelectScreen = new FreeModSelectScreen
{
State = { Value = Visibility.Visible }
});
AddUntilStep("all column content loaded",
() => freeModSelectScreen.ChildrenOfType<ModColumn>().Any()
&& freeModSelectScreen.ChildrenOfType<ModColumn>().All(column => column.IsLoaded && column.ItemsLoaded));
createFreeModSelect();
AddUntilStep("all visible mods are playable",
() => this.ChildrenOfType<ModPanel>()
@ -36,5 +31,26 @@ namespace osu.Game.Tests.Visual.Multiplayer
freeModSelectScreen.State.Value = visible ? Visibility.Visible : Visibility.Hidden;
});
}
[Test]
public void TestCustomisationNotAvailable()
{
createFreeModSelect();
AddStep("select difficulty adjust", () => freeModSelectScreen.SelectedMods.Value = new[] { new OsuModDifficultyAdjust() });
AddWaitStep("wait some", 3);
AddAssert("customisation area not expanded", () => this.ChildrenOfType<ModSettingsArea>().Single().Height == 0);
}
private void createFreeModSelect()
{
AddStep("create free mod select screen", () => Child = freeModSelectScreen = new FreeModSelectScreen
{
State = { Value = Visibility.Visible }
});
AddUntilStep("all column content loaded",
() => freeModSelectScreen.ChildrenOfType<ModColumn>().Any()
&& freeModSelectScreen.ChildrenOfType<ModColumn>().All(column => column.IsLoaded && column.ItemsLoaded));
}
}
}

View File

@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Mods
set
{
filter = value;
updateFilter();
updateState();
}
}
@ -292,9 +292,7 @@ namespace osu.Game.Overlays.Mods
{
panelFlow.ChildrenEnumerable = loaded;
updateActiveState();
updateToggleAllState();
updateFilter();
updateState();
foreach (var panel in panelFlow)
{
@ -308,10 +306,19 @@ namespace osu.Game.Overlays.Mods
});
}
private void updateActiveState()
private void updateState()
{
foreach (var panel in panelFlow)
{
panel.Active.Value = SelectedMods.Contains(panel.Mod);
panel.ApplyFilter(Filter);
}
if (toggleAllCheckbox != null && !SelectionAnimationRunning)
{
toggleAllCheckbox.Alpha = panelFlow.Any(panel => !panel.Filtered.Value) ? 1 : 0;
toggleAllCheckbox.Current.Value = panelFlow.Where(panel => !panel.Filtered.Value).All(panel => panel.Active.Value);
}
}
/// <summary>
@ -323,15 +330,16 @@ namespace osu.Game.Overlays.Mods
private void panelStateChanged(ModPanel panel)
{
updateToggleAllState();
if (externalSelectionUpdateInProgress)
return;
var newSelectedMods = panel.Active.Value
? SelectedMods.Append(panel.Mod)
: SelectedMods.Except(panel.Mod.Yield());
SelectedMods = newSelectedMods.ToArray();
if (!externalSelectionUpdateInProgress)
SelectionChangedByUser?.Invoke();
updateState();
SelectionChangedByUser?.Invoke();
}
/// <summary>
@ -364,7 +372,7 @@ namespace osu.Game.Overlays.Mods
}
SelectedMods = newSelection;
updateActiveState();
updateState();
externalSelectionUpdateInProgress = false;
}
@ -403,15 +411,6 @@ namespace osu.Game.Overlays.Mods
}
}
private void updateToggleAllState()
{
if (toggleAllCheckbox != null && !SelectionAnimationRunning)
{
toggleAllCheckbox.Alpha = panelFlow.Any(panel => !panel.Filtered.Value) ? 1 : 0;
toggleAllCheckbox.Current.Value = panelFlow.Where(panel => !panel.Filtered.Value).All(panel => panel.Active.Value);
}
}
/// <summary>
/// Selects all mods.
/// </summary>
@ -507,18 +506,6 @@ namespace osu.Game.Overlays.Mods
#endregion
#region Filtering support
private void updateFilter()
{
foreach (var modPanel in panelFlow)
modPanel.ApplyFilter(Filter);
updateToggleAllState();
}
#endregion
#region Keyboard selection support
protected override bool OnKeyDown(KeyDownEvent e)

View File

@ -13,6 +13,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Framework.Layout;
using osu.Framework.Lists;
using osu.Framework.Utils;
using osu.Game.Configuration;
using osu.Game.Graphics;
@ -264,7 +265,9 @@ namespace osu.Game.Overlays.Mods
{
var candidateSelection = columnFlow.Columns.SelectMany(column => column.SelectedMods).ToArray();
if (candidateSelection.SequenceEqual(SelectedMods.Value))
// the following guard intends to check cases where we've already replaced potentially-external mod references with our own and avoid endless recursion.
// TODO: replace custom comparer with System.Collections.Generic.ReferenceEqualityComparer when fully on .NET 6
if (candidateSelection.SequenceEqual(SelectedMods.Value, new FuncEqualityComparer<Mod>(ReferenceEquals)))
return;
SelectedMods.Value = ComputeNewModsFromSelection(SelectedMods.Value, candidateSelection);