diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index b26e126249..6c75530a6e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -859,6 +859,30 @@ namespace osu.Game.Tests.Visual.UserInterface () => modSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value, () => Is.EqualTo(0.3).Within(Precision.DOUBLE_EPSILON)); } + [Test] + public void TestModSettingsOrder() + { + createScreen(); + + AddStep("select DT + HD + DF", () => SelectedMods.Value = new Mod[] { new OsuModDoubleTime(), new OsuModHidden(), new OsuModDeflate() }); + AddAssert("mod settings order: DT, HD, DF", () => + { + var columns = this.ChildrenOfType().Single().ChildrenOfType(); + return columns.ElementAt(0).Mod is OsuModDoubleTime && + columns.ElementAt(1).Mod is OsuModHidden && + columns.ElementAt(2).Mod is OsuModDeflate; + }); + + AddStep("replace DT with NC", () => SelectedMods.Value = SelectedMods.Value.Where(m => m is not ModDoubleTime).Append(new OsuModNightcore()).ToList()); + AddAssert("mod settings order: NC, HD, DF", () => + { + var columns = this.ChildrenOfType().Single().ChildrenOfType(); + return columns.ElementAt(0).Mod is OsuModNightcore && + columns.ElementAt(1).Mod is OsuModHidden && + columns.ElementAt(2).Mod is OsuModDeflate; + }); + } + private void waitForColumnLoad() => AddUntilStep("all column content loaded", () => modSelectOverlay.ChildrenOfType().Any() && modSelectOverlay.ChildrenOfType().All(column => column.IsLoaded && column.ItemsLoaded) diff --git a/osu.Game/Overlays/Mods/ModSettingsArea.cs b/osu.Game/Overlays/Mods/ModSettingsArea.cs index 54bfcc7199..d0e0f7e648 100644 --- a/osu.Game/Overlays/Mods/ModSettingsArea.cs +++ b/osu.Game/Overlays/Mods/ModSettingsArea.cs @@ -86,7 +86,10 @@ namespace osu.Game.Overlays.Mods { modSettingsFlow.Clear(); - foreach (var mod in SelectedMods.Value.AsOrdered()) + // Importantly, the selected mods bindable is already ordered by the mod select overlay (following the order of mod columns and panels). + // Using AsOrdered produces a slightly different order (e.g. DT and NC no longer becoming adjacent), + // which breaks user expectations when interacting with the overlay. + foreach (var mod in SelectedMods.Value) { var settings = mod.CreateSettingsControls().ToList(); @@ -110,10 +113,14 @@ namespace osu.Game.Overlays.Mods protected override bool OnMouseDown(MouseDownEvent e) => true; protected override bool OnHover(HoverEvent e) => true; - private partial class ModSettingsColumn : CompositeDrawable + public partial class ModSettingsColumn : CompositeDrawable { + public readonly Mod Mod; + public ModSettingsColumn(Mod mod, IEnumerable settingsControls) { + Mod = mod; + Width = 250; RelativeSizeAxes = Axes.Y; Padding = new MarginPadding { Bottom = 7 };