From af0c7ed108387b4e77ee8bf4f902dafbd2f12551 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 01:25:57 +0900 Subject: [PATCH 01/13] Fix searching in settings not correctly invalidating the scroll position --- osu.Game/Graphics/Containers/SectionsContainer.cs | 11 ++++++++++- osu.Game/Overlays/SettingsPanel.cs | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 8ab146efe7..b3dd44f0e1 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -170,13 +170,22 @@ namespace osu.Game.Graphics.Containers if (source == InvalidationSource.Child && (invalidation & Invalidation.DrawSize) != 0) { - lastKnownScroll = null; + InvalidateScrollPosition(); result = true; } return result; } + protected void InvalidateScrollPosition() + { + Schedule(() => + { + lastKnownScroll = null; + lastClickedSection = null; + }); + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 376e36ea4e..83b0d9c7dc 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -273,6 +273,16 @@ namespace osu.Game.Overlays { public SearchContainer SearchContainer; + public string SearchTerm + { + get => SearchContainer.SearchTerm; + set + { + SearchContainer.SearchTerm = value; + InvalidateScrollPosition(); + } + } + protected override FlowContainer CreateScrollContentContainer() => SearchContainer = new SearchContainer { From a0374d4a67c2274673f05452e9d050451f7d07e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 01:26:11 +0900 Subject: [PATCH 02/13] Adjust centre point slightly to make dim feel better --- osu.Game/Graphics/Containers/SectionsContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index b3dd44f0e1..2dc69b0bd0 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -111,7 +111,7 @@ namespace osu.Game.Graphics.Containers /// /// The percentage of the container to consider the centre-point for deciding the active section (and scrolling to a requested section). /// - private const float scroll_y_centre = 0.1f; + private const float scroll_y_centre = 0.2f; public SectionsContainer() { From e87accafc88cc5ea384b7441893d1a95a3739354 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 01:26:33 +0900 Subject: [PATCH 03/13] Fix current section logic not accounting for hidden sections --- osu.Game/Graphics/Containers/SectionsContainer.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 2dc69b0bd0..e11d1e1300 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -22,6 +22,7 @@ namespace osu.Game.Graphics.Containers where T : Drawable { public Bindable SelectedSection { get; } = new Bindable(); + private Drawable lastClickedSection; public Drawable ExpandableHeader @@ -233,15 +234,17 @@ namespace osu.Game.Graphics.Containers float scrollCentre = fixedHeaderSize + scrollContainer.DisplayableContent * scroll_y_centre + selectionLenienceAboveSection; + var presentChildren = Children.Where(c => c.IsPresent); + if (Precision.AlmostBigger(0, scrollContainer.Current)) - SelectedSection.Value = lastClickedSection as T ?? Children.FirstOrDefault(); + SelectedSection.Value = lastClickedSection as T ?? presentChildren.FirstOrDefault(); else if (Precision.AlmostBigger(scrollContainer.Current, scrollContainer.ScrollableExtent)) - SelectedSection.Value = lastClickedSection as T ?? Children.LastOrDefault(); + SelectedSection.Value = lastClickedSection as T ?? presentChildren.LastOrDefault(); else { - SelectedSection.Value = Children + SelectedSection.Value = presentChildren .TakeWhile(section => scrollContainer.GetChildPosInContent(section) - currentScroll - scrollCentre <= 0) - .LastOrDefault() ?? Children.FirstOrDefault(); + .LastOrDefault() ?? presentChildren.FirstOrDefault(); } } } From 6637c64501aab585fe3e110e3833a1b2eab35fc0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 01:27:14 +0900 Subject: [PATCH 04/13] Dim all but the current section --- osu.Game/Overlays/Settings/SettingsSection.cs | 49 ++++++++++++++++++- osu.Game/Overlays/SettingsPanel.cs | 13 +++-- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index f993a46dc6..8d98ae484f 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -19,6 +21,10 @@ namespace osu.Game.Overlays.Settings protected FillFlowContainer FlowContent; protected override Container Content => FlowContent; + private IBindable selectedSection; + + private Container content; + public abstract Drawable CreateIcon(); public abstract LocalisableString Header { get; } @@ -36,6 +42,9 @@ namespace osu.Game.Overlays.Settings public bool FilteringActive { get; set; } + [Resolved] + private SettingsPanel settingsPanel { get; set; } + protected SettingsSection() { Margin = new MarginPadding { Top = margin }; @@ -65,7 +74,7 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X, Height = border_size, }, - new Container + content = new Container { Padding = new MarginPadding { @@ -91,6 +100,44 @@ namespace osu.Game.Overlays.Settings } }, }); + + selectedSection = settingsPanel.CurrentSection.GetBoundCopy(); + selectedSection.BindValueChanged(selected => + { + if (selected.NewValue == this) + content.FadeIn(500, Easing.OutQuint); + else + content.FadeTo(0.25f, 500, Easing.OutQuint); + }, true); + } + + private bool isCurrentSection => selectedSection.Value == this; + + protected override bool OnHover(HoverEvent e) + { + if (!isCurrentSection) + content.FadeTo(0.6f, 500, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + if (!isCurrentSection) + content.FadeTo(0.25f, 500, Easing.OutQuint); + base.OnHoverLost(e); + } + + protected override bool OnClick(ClickEvent e) + { + if (!isCurrentSection) + settingsPanel.SectionsContainer.ScrollTo(this); + + return base.OnClick(e); + } + + protected override bool ShouldBeConsideredForInput(Drawable child) + { + return isCurrentSection; } } } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 83b0d9c7dc..e4e76592d8 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,6 +22,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Overlays { + [Cached] public abstract class SettingsPanel : OsuFocusedOverlayContainer { public const float CONTENT_MARGINS = 15; @@ -46,7 +48,7 @@ namespace osu.Game.Overlays protected Sidebar Sidebar; private SidebarButton selectedSidebarButton; - protected SettingsSectionsContainer SectionsContainer; + public SettingsSectionsContainer SectionsContainer { get; private set; } private SeekLimitedSearchTextBox searchTextBox; @@ -65,6 +67,8 @@ namespace osu.Game.Overlays private Task sectionsLoadingTask; + public IBindable CurrentSection = new Bindable(); + protected SettingsPanel(bool showSidebar) { this.showSidebar = showSidebar; @@ -105,6 +109,7 @@ namespace osu.Game.Overlays Masking = true, RelativeSizeAxes = Axes.Both, ExpandableHeader = CreateHeader(), + SelectedSection = { BindTarget = CurrentSection }, FixedHeader = searchTextBox = new SeekLimitedSearchTextBox { RelativeSizeAxes = Axes.X, @@ -238,8 +243,10 @@ namespace osu.Game.Overlays if (selectedSidebarButton != null) selectedSidebarButton.Selected = false; - selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); - selectedSidebarButton.Selected = true; + selectedSidebarButton = Sidebar.Children.FirstOrDefault(b => b.Section == section.NewValue); + + if (selectedSidebarButton != null) + selectedSidebarButton.Selected = true; }, true); }); } From cff7b1e98f495b11c34d3d92850c7edfa9cd4e1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 16:50:27 +0900 Subject: [PATCH 05/13] Ensure the correct fade level is applied over all state changes --- osu.Game/Overlays/Settings/SettingsSection.cs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 8d98ae484f..5c38dee356 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -102,28 +102,20 @@ namespace osu.Game.Overlays.Settings }); selectedSection = settingsPanel.CurrentSection.GetBoundCopy(); - selectedSection.BindValueChanged(selected => - { - if (selected.NewValue == this) - content.FadeIn(500, Easing.OutQuint); - else - content.FadeTo(0.25f, 500, Easing.OutQuint); - }, true); + selectedSection.BindValueChanged(_ => updateContentFade(), true); } private bool isCurrentSection => selectedSection.Value == this; protected override bool OnHover(HoverEvent e) { - if (!isCurrentSection) - content.FadeTo(0.6f, 500, Easing.OutQuint); + updateContentFade(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - if (!isCurrentSection) - content.FadeTo(0.25f, 500, Easing.OutQuint); + updateContentFade(); base.OnHoverLost(e); } @@ -135,9 +127,19 @@ namespace osu.Game.Overlays.Settings return base.OnClick(e); } - protected override bool ShouldBeConsideredForInput(Drawable child) + protected override bool ShouldBeConsideredForInput(Drawable child) => + // only the current section should accept input. + // this provides the behaviour of the first click scrolling the target section to the centre of the screen. + isCurrentSection; + + private void updateContentFade() { - return isCurrentSection; + float targetFade = 1; + + if (!isCurrentSection) + targetFade = IsHovered ? 0.6f : 0.25f; + + content.FadeTo(targetFade, 500, Easing.OutQuint); } } } From c7266c74a09bcfdcdf94d95049f224d03a034397 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:00:20 +0900 Subject: [PATCH 06/13] Always prefer clicked section when present --- .../Graphics/Containers/SectionsContainer.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index e11d1e1300..4b368b98ad 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics.Containers { public Bindable SelectedSection { get; } = new Bindable(); - private Drawable lastClickedSection; + private T lastClickedSection; public Drawable ExpandableHeader { @@ -145,10 +145,12 @@ namespace osu.Game.Graphics.Containers footerHeight = null; } - public void ScrollTo(Drawable section) + public void ScrollTo(Drawable target) { - lastClickedSection = section; - scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(section) - scrollContainer.DisplayableContent * scroll_y_centre - (FixedHeader?.BoundingBox.Height ?? 0)); + if (target is T section) + lastClickedSection = section; + + scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(target) - scrollContainer.DisplayableContent * scroll_y_centre - (FixedHeader?.BoundingBox.Height ?? 0)); } public void ScrollToTop() => scrollContainer.ScrollTo(0); @@ -236,10 +238,12 @@ namespace osu.Game.Graphics.Containers var presentChildren = Children.Where(c => c.IsPresent); - if (Precision.AlmostBigger(0, scrollContainer.Current)) - SelectedSection.Value = lastClickedSection as T ?? presentChildren.FirstOrDefault(); + if (lastClickedSection != null) + SelectedSection.Value = lastClickedSection; + else if (Precision.AlmostBigger(0, scrollContainer.Current)) + SelectedSection.Value = presentChildren.FirstOrDefault(); else if (Precision.AlmostBigger(scrollContainer.Current, scrollContainer.ScrollableExtent)) - SelectedSection.Value = lastClickedSection as T ?? presentChildren.LastOrDefault(); + SelectedSection.Value = presentChildren.LastOrDefault(); else { SelectedSection.Value = presentChildren From 139ff2d6e2a5a242ac2be92ba8737e81132d4f5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:40:03 +0900 Subject: [PATCH 07/13] Only fade header in when hovering a section Feels less like the controls are interactive when hovering this way. --- osu.Game/Overlays/Settings/SettingsSection.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 5c38dee356..6f167bf059 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings private IBindable selectedSection; - private Container content; + private OsuSpriteText header; public abstract Drawable CreateIcon(); public abstract LocalisableString Header { get; } @@ -70,11 +70,12 @@ namespace osu.Game.Overlays.Settings { new Box { + Name = "separator", Colour = new Color4(0, 0, 0, 255), RelativeSizeAxes = Axes.X, Height = border_size, }, - content = new Container + new Container { Padding = new MarginPadding { @@ -85,7 +86,7 @@ namespace osu.Game.Overlays.Settings AutoSizeAxes = Axes.Y, Children = new Drawable[] { - new OsuSpriteText + header = new OsuSpriteText { Font = OsuFont.GetFont(size: header_size), Text = Header, @@ -134,12 +135,17 @@ namespace osu.Game.Overlays.Settings private void updateContentFade() { - float targetFade = 1; + float contentFade = 1; + float headerFade = 1; if (!isCurrentSection) - targetFade = IsHovered ? 0.6f : 0.25f; + { + contentFade = 0.25f; + headerFade = IsHovered ? 0.5f : 0.25f; + } - content.FadeTo(targetFade, 500, Easing.OutQuint); + header.FadeTo(headerFade, 500, Easing.OutQuint); + FlowContent.FadeTo(contentFade, 500, Easing.OutQuint); } } } From 2d19f37dc6100a605b725e8d1eeb938109c43e06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:40:41 +0900 Subject: [PATCH 08/13] Add missing `new` method in `UserTrackingScrollContainer` for scrolling into view --- osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs index 17506ce0f5..0561051e35 100644 --- a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs +++ b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs @@ -42,6 +42,12 @@ namespace osu.Game.Graphics.Containers base.OnUserScroll(value, animated, distanceDecay); } + public new void ScrollIntoView(Drawable target, bool animated = true) + { + UserScrolling = false; + base.ScrollIntoView(target, animated); + } + public new void ScrollTo(float value, bool animated = true, double? distanceDecay = null) { UserScrolling = false; From 03e6ca5ba930830960bb5541f7b7be6fb2dc0f9a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:40:56 +0900 Subject: [PATCH 09/13] Adjust scroll behaviour to feel better --- .../Graphics/Containers/SectionsContainer.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 4b368b98ad..d0aa885f3e 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -112,7 +112,7 @@ namespace osu.Game.Graphics.Containers /// /// The percentage of the container to consider the centre-point for deciding the active section (and scrolling to a requested section). /// - private const float scroll_y_centre = 0.2f; + private const float scroll_y_centre = 0.1f; public SectionsContainer() { @@ -147,10 +147,22 @@ namespace osu.Game.Graphics.Containers public void ScrollTo(Drawable target) { + lastKnownScroll = null; + + float fixedHeaderSize = FixedHeader?.BoundingBox.Height ?? 0; + + // implementation similar to ScrollIntoView but a bit more nuanced. + float top = scrollContainer.GetChildPosInContent(target); + + var bottomScrollExtent = scrollContainer.ScrollableExtent - fixedHeaderSize; + + if (top > bottomScrollExtent) + scrollContainer.ScrollToEnd(); + else + scrollContainer.ScrollTo(top - fixedHeaderSize - scrollContainer.DisplayableContent * scroll_y_centre); + if (target is T section) lastClickedSection = section; - - scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(target) - scrollContainer.DisplayableContent * scroll_y_centre - (FixedHeader?.BoundingBox.Height ?? 0)); } public void ScrollToTop() => scrollContainer.ScrollTo(0); From 591ba8cb099a0ab4d9488fea7877ea4304c6179e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:56:35 +0900 Subject: [PATCH 10/13] Ensure the final scroll target is used when checking for whether too far down --- osu.Game/Graphics/Containers/SectionsContainer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index d0aa885f3e..76492cab55 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -154,12 +154,13 @@ namespace osu.Game.Graphics.Containers // implementation similar to ScrollIntoView but a bit more nuanced. float top = scrollContainer.GetChildPosInContent(target); - var bottomScrollExtent = scrollContainer.ScrollableExtent - fixedHeaderSize; + float bottomScrollExtent = scrollContainer.ScrollableExtent - fixedHeaderSize; + float scrollTarget = top - fixedHeaderSize - scrollContainer.DisplayableContent * scroll_y_centre; - if (top > bottomScrollExtent) + if (scrollTarget > bottomScrollExtent) scrollContainer.ScrollToEnd(); else - scrollContainer.ScrollTo(top - fixedHeaderSize - scrollContainer.DisplayableContent * scroll_y_centre); + scrollContainer.ScrollTo(scrollTarget); if (target is T section) lastClickedSection = section; From d304e283e4a24506923f48097b84494086ef38d6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 18:14:59 +0900 Subject: [PATCH 11/13] Don't deselect online room when joined --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 4e106b844c..70342680e2 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -172,8 +172,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge sampleJoin?.Play(); lounge?.Join(Room, null); - - return base.OnClick(e); + return true; } public class PasswordEntryPopover : OsuPopover From cbee379f62cdc49b8227067fd952f5bd57bbe172 Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Fri, 20 Aug 2021 12:30:49 +0300 Subject: [PATCH 12/13] Test scrolled to section top is visible --- .../UserInterface/TestSceneSectionsContainer.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs index 5c2e6e457d..2312c57af2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; using osu.Game.Graphics.Containers; using osuTK.Graphics; @@ -61,10 +62,12 @@ namespace osu.Game.Tests.Visual.UserInterface )); AddStep("scroll up", () => triggerUserScroll(1)); AddStep("scroll down", () => triggerUserScroll(-1)); + AddStep("scroll up a bit", () => triggerUserScroll(0.1f)); + AddStep("scroll down a bit", () => triggerUserScroll(-0.1f)); } [Test] - public void TestCorrectSectionSelected() + public void TestCorrectSelectionAndVisibleTop() { const int sections_count = 11; float[] alternating = { 0.07f, 0.33f, 0.16f, 0.33f }; @@ -79,6 +82,12 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep($"scroll to section {scrollIndex + 1}", () => container.ScrollTo(container.Children[scrollIndex])); AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[scrollIndex]); + AddUntilStep("section top is visible", () => + { + float scrollPosition = container.ChildrenOfType().First().Current; + float sectionTop = container.Children[scrollIndex].BoundingBox.Top; + return scrollPosition < sectionTop; + }); } for (int i = 1; i < sections_count; i++) From 77149044a5954278d9deef2b014c5fe267033915 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 19:33:47 +0900 Subject: [PATCH 13/13] Allow intro screen to retrieve beatmap even if rulesets is not loaded --- osu.Game/Beatmaps/BeatmapManager.cs | 36 +++++++++++++++++++++++++++- osu.Game/Beatmaps/BeatmapStore.cs | 7 ++++++ osu.Game/Screens/Menu/IntroScreen.cs | 3 ++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 4a78ceb299..241649062e 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -365,6 +365,10 @@ namespace osu.Game.Beatmaps queryable = beatmaps.BeatmapSetsOverview; break; + case IncludedDetails.AllButRuleset: + queryable = beatmaps.BeatmapSetsWithoutRuleset; + break; + case IncludedDetails.AllButFiles: queryable = beatmaps.BeatmapSetsWithoutFiles; break; @@ -384,8 +388,33 @@ namespace osu.Game.Beatmaps /// Perform a lookup query on available s. /// /// The query. + /// The level of detail to include in the returned objects. /// Results from the provided query. - public IEnumerable QueryBeatmapSets(Expression> query) => beatmaps.ConsumableItems.AsNoTracking().Where(query); + public IEnumerable QueryBeatmapSets(Expression> query, IncludedDetails includes = IncludedDetails.All) + { + IQueryable queryable; + + switch (includes) + { + case IncludedDetails.Minimal: + queryable = beatmaps.BeatmapSetsOverview; + break; + + case IncludedDetails.AllButRuleset: + queryable = beatmaps.BeatmapSetsWithoutRuleset; + break; + + case IncludedDetails.AllButFiles: + queryable = beatmaps.BeatmapSetsWithoutFiles; + break; + + default: + queryable = beatmaps.ConsumableItems; + break; + } + + return queryable.AsNoTracking().Where(query); + } /// /// Perform a lookup query on available s. @@ -554,6 +583,11 @@ namespace osu.Game.Beatmaps /// AllButFiles, + /// + /// Include everything except ruleset. Used for cases where we aren't sure the ruleset is present but still want to consume the beatmap. + /// + AllButRuleset, + /// /// Include everything. /// diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index 642bafd2ac..e3214b7c03 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -92,6 +92,13 @@ namespace osu.Game.Beatmaps .Include(s => s.Beatmaps) .AsNoTracking(); + public IQueryable BeatmapSetsWithoutRuleset => ContextFactory.Get().BeatmapSetInfo + .Include(s => s.Metadata) + .Include(s => s.Files).ThenInclude(f => f.FileInfo) + .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) + .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata) + .AsNoTracking(); + public IQueryable BeatmapSetsWithoutFiles => ContextFactory.Get().BeatmapSetInfo .Include(s => s.Metadata) .Include(s => s.Beatmaps).ThenInclude(s => s.Ruleset) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 71f3b60026..07a94fb97e 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -109,7 +110,7 @@ namespace osu.Game.Screens.Menu bool loadThemedIntro() { - setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == BeatmapHash); + setInfo = beatmaps.QueryBeatmapSets(b => b.Hash == BeatmapHash, IncludedDetails.AllButRuleset).FirstOrDefault(); if (setInfo == null) return false;