From 92ccec20d787d08e19d81437ab7c89e148175abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 8 May 2022 14:44:54 +0200 Subject: [PATCH 1/4] Hide mod columns if all mods within are filtered out --- osu.Game/Overlays/Mods/ModColumn.cs | 13 +++++++ osu.Game/Overlays/Mods/ModSelectScreen.cs | 45 +++++++++++++++++------ 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index f0741cdc40..89f472a290 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -55,8 +55,18 @@ namespace osu.Game.Overlays.Mods } } + /// + /// Determines whether this column should accept user input. + /// public Bindable Active = new BindableBool(true); + private readonly Bindable allFiltered = new BindableBool(); + + /// + /// True if all of the panels in this column have been filtered out by the current . + /// + public IBindable AllFiltered => allFiltered; + /// /// List of mods marked as selected in this column. /// @@ -339,6 +349,9 @@ namespace osu.Game.Overlays.Mods panel.ApplyFilter(Filter); } + allFiltered.Value = panelFlow.All(panel => panel.Filtered.Value); + Alpha = allFiltered.Value ? 0 : 1; + if (toggleAllCheckbox != null && !SelectionAnimationRunning) { toggleAllCheckbox.Alpha = panelFlow.Any(panel => !panel.Filtered.Value) ? 1 : 0; diff --git a/osu.Game/Overlays/Mods/ModSelectScreen.cs b/osu.Game/Overlays/Mods/ModSelectScreen.cs index fc06af3f9d..6a3df3fb05 100644 --- a/osu.Game/Overlays/Mods/ModSelectScreen.cs +++ b/osu.Game/Overlays/Mods/ModSelectScreen.cs @@ -237,11 +237,11 @@ namespace osu.Game.Overlays.Mods } private ColumnDimContainer createModColumnContent(ModType modType, Key[]? toggleKeys = null) - => new ColumnDimContainer(CreateModColumn(modType, toggleKeys)) + => new ColumnDimContainer(CreateModColumn(modType, toggleKeys).With(column => column.Filter = IsValidMod)) { AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, - RequestScroll = column => columnScroll.ScrollIntoView(column, extraScroll: 140) + RequestScroll = column => columnScroll.ScrollIntoView(column, extraScroll: 140), }; private ShearedButton[] createDefaultFooterButtons() @@ -351,6 +351,8 @@ namespace osu.Game.Overlays.Mods #region Transition handling + private const float distance = 700; + protected override void PopIn() { const double fade_in_duration = 400; @@ -362,13 +364,26 @@ namespace osu.Game.Overlays.Mods .FadeIn(fade_in_duration / 2, Easing.OutQuint) .ScaleTo(1, fade_in_duration, Easing.OutElastic); + int nonFilteredColumnCount = 0; + for (int i = 0; i < columnFlow.Count; i++) { - columnFlow[i].Column - .TopLevelContent - .Delay(i * 30) - .MoveToY(0, fade_in_duration, Easing.OutQuint) - .FadeIn(fade_in_duration, Easing.OutQuint); + var column = columnFlow[i].Column; + + double delay = column.AllFiltered.Value ? 0 : nonFilteredColumnCount * 30; + double duration = column.AllFiltered.Value ? 0 : fade_in_duration; + float startingYPosition = 0; + if (!column.AllFiltered.Value) + startingYPosition = nonFilteredColumnCount % 2 == 0 ? -distance : distance; + + column.TopLevelContent + .MoveToY(startingYPosition) + .Delay(delay) + .MoveToY(0, duration, Easing.OutQuint) + .FadeIn(duration, Easing.OutQuint); + + if (!column.AllFiltered.Value) + nonFilteredColumnCount += 1; } } @@ -382,16 +397,24 @@ namespace osu.Game.Overlays.Mods .FadeOut(fade_out_duration / 2, Easing.OutQuint) .ScaleTo(0.75f, fade_out_duration, Easing.OutQuint); + int nonFilteredColumnCount = 0; + for (int i = 0; i < columnFlow.Count; i++) { - const float distance = 700; - var column = columnFlow[i].Column; + double duration = column.AllFiltered.Value ? 0 : fade_out_duration; + float newYPosition = 0; + if (!column.AllFiltered.Value) + newYPosition = nonFilteredColumnCount % 2 == 0 ? -distance : distance; + column.FlushPendingSelections(); column.TopLevelContent - .MoveToY(i % 2 == 0 ? -distance : distance, fade_out_duration, Easing.OutQuint) - .FadeOut(fade_out_duration, Easing.OutQuint); + .MoveToY(newYPosition, duration, Easing.OutQuint) + .FadeOut(duration, Easing.OutQuint); + + if (!column.AllFiltered.Value) + nonFilteredColumnCount += 1; } } From 38c004d734be28cdc973bbd8eb9f4ca19e5b55db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 8 May 2022 14:45:01 +0200 Subject: [PATCH 2/4] Add test coverage for hiding mod columns --- .../UserInterface/TestSceneModSelectScreen.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs index 42ffeba444..fa7758df59 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectScreen.cs @@ -451,6 +451,36 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("mod select hidden", () => modSelectScreen.State.Value == Visibility.Hidden); } + [Test] + public void TestColumnHiding() + { + AddStep("create screen", () => Child = modSelectScreen = new UserModSelectScreen + { + RelativeSizeAxes = Axes.Both, + State = { Value = Visibility.Visible }, + SelectedMods = { BindTarget = SelectedMods }, + IsValidMod = mod => mod.Type == ModType.DifficultyIncrease || mod.Type == ModType.Conversion + }); + waitForColumnLoad(); + changeRuleset(0); + + AddAssert("two columns visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 2); + + AddStep("unset filter", () => modSelectScreen.IsValidMod = _ => true); + AddAssert("all columns visible", () => this.ChildrenOfType().All(col => col.IsPresent)); + + AddStep("filter out everything", () => modSelectScreen.IsValidMod = _ => false); + AddAssert("no columns visible", () => this.ChildrenOfType().All(col => !col.IsPresent)); + + AddStep("hide", () => modSelectScreen.Hide()); + AddStep("set filter for 3 columns", () => modSelectScreen.IsValidMod = mod => mod.Type == ModType.DifficultyReduction + || mod.Type == ModType.Automation + || mod.Type == ModType.Conversion); + + AddStep("show", () => modSelectScreen.Show()); + AddUntilStep("3 columns visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 3); + } + private void waitForColumnLoad() => AddUntilStep("all column content loaded", () => modSelectScreen.ChildrenOfType().Any() && modSelectScreen.ChildrenOfType().All(column => column.IsLoaded && column.ItemsLoaded)); From 6bdcf893b7d6c960d8154c9908b78f8c92a6c273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 8 May 2022 15:13:29 +0200 Subject: [PATCH 3/4] Move alpha management closer to screen level Felt bad messing with alpha at the column level. --- osu.Game/Overlays/Mods/ModColumn.cs | 1 - osu.Game/Overlays/Mods/ModSelectScreen.cs | 13 ++++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 89f472a290..3a2fda0bb0 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -350,7 +350,6 @@ namespace osu.Game.Overlays.Mods } allFiltered.Value = panelFlow.All(panel => panel.Filtered.Value); - Alpha = allFiltered.Value ? 0 : 1; if (toggleAllCheckbox != null && !SelectionAnimationRunning) { diff --git a/osu.Game/Overlays/Mods/ModSelectScreen.cs b/osu.Game/Overlays/Mods/ModSelectScreen.cs index 6a3df3fb05..a2e73b9575 100644 --- a/osu.Game/Overlays/Mods/ModSelectScreen.cs +++ b/osu.Game/Overlays/Mods/ModSelectScreen.cs @@ -580,17 +580,20 @@ namespace osu.Game.Overlays.Mods protected override void LoadComplete() { base.LoadComplete(); - Active.BindValueChanged(_ => updateDim(), true); + Active.BindValueChanged(_ => updateState()); + Column.AllFiltered.BindValueChanged(_ => updateState(), true); FinishTransforms(); } protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate || Column.SelectionAnimationRunning; - private void updateDim() + private void updateState() { Colour4 targetColour; - if (Active.Value) + Column.Alpha = Column.AllFiltered.Value ? 0 : 1; + + if (Column.Active.Value) targetColour = Colour4.White; else targetColour = IsHovered ? colours.GrayC : colours.Gray8; @@ -609,14 +612,14 @@ namespace osu.Game.Overlays.Mods protected override bool OnHover(HoverEvent e) { base.OnHover(e); - updateDim(); + updateState(); return Active.Value; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - updateDim(); + updateState(); } } From d964b4f23c47df79e7c27acdcb7056b7b8774210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 8 May 2022 15:22:32 +0200 Subject: [PATCH 4/4] Fix uneven spacing when some mod columns are hidden --- osu.Game/Overlays/Mods/ModSelectScreen.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectScreen.cs b/osu.Game/Overlays/Mods/ModSelectScreen.cs index a2e73b9575..8b19e38954 100644 --- a/osu.Game/Overlays/Mods/ModSelectScreen.cs +++ b/osu.Game/Overlays/Mods/ModSelectScreen.cs @@ -129,7 +129,6 @@ namespace osu.Game.Overlays.Mods Shear = new Vector2(SHEAR, 0), RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, - Spacing = new Vector2(10, 0), Margin = new MarginPadding { Horizontal = 70 }, Children = new[] { @@ -237,12 +236,21 @@ namespace osu.Game.Overlays.Mods } private ColumnDimContainer createModColumnContent(ModType modType, Key[]? toggleKeys = null) - => new ColumnDimContainer(CreateModColumn(modType, toggleKeys).With(column => column.Filter = IsValidMod)) + { + var column = CreateModColumn(modType, toggleKeys).With(column => + { + column.Filter = IsValidMod; + // spacing applied here rather than via `columnFlow.Spacing` to avoid uneven gaps when some of the columns are hidden. + column.Margin = new MarginPadding { Right = 10 }; + }); + + return new ColumnDimContainer(column) { AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, - RequestScroll = column => columnScroll.ScrollIntoView(column, extraScroll: 140), + RequestScroll = col => columnScroll.ScrollIntoView(col, extraScroll: 140), }; + } private ShearedButton[] createDefaultFooterButtons() => new[]