diff --git a/osu.Game/Screens/Select/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs similarity index 91% rename from osu.Game/Screens/Select/SearchTextBox.cs rename to osu.Game/Graphics/UserInterface/SearchTextBox.cs index 4f2ab221cb..18148e9d31 100644 --- a/osu.Game/Screens/Select/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -1,14 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; +using OpenTK.Input; -namespace osu.Game.Screens.Select +namespace osu.Game.Graphics.UserInterface { /// <summary> /// A textbox which holds focus eagerly. diff --git a/osu.Game/Overlays/Music/FilterControl.cs b/osu.Game/Overlays/Music/FilterControl.cs index c6572c5ed2..0b4e067fff 100644 --- a/osu.Game/Overlays/Music/FilterControl.cs +++ b/osu.Game/Overlays/Music/FilterControl.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; -using osu.Game.Screens.Select; using OpenTK; using OpenTK.Graphics; using System; diff --git a/osu.Game/Overlays/Options/OptionsHeader.cs b/osu.Game/Overlays/Options/OptionsHeader.cs new file mode 100644 index 0000000000..8b97a607a2 --- /dev/null +++ b/osu.Game/Overlays/Options/OptionsHeader.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using OpenTK.Graphics; + +namespace osu.Game.Overlays.Options +{ + public class OptionsHeader : Container + { + public SearchTextBox SearchTextBox; + + private Box background; + + private readonly Func<float> currentScrollOffset; + + public Action Exit; + + /// <param name="currentScrollOffset">A reference to the current scroll position of the ScrollContainer we are contained within.</param> + public OptionsHeader(Func<float> currentScrollOffset) + { + this.currentScrollOffset = currentScrollOffset; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Children = new Drawable[] + { + background = new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = "settings", + TextSize = 40, + Margin = new MarginPadding { + Left = OptionsOverlay.CONTENT_MARGINS, + Top = Toolbar.Toolbar.TOOLTIP_HEIGHT + }, + }, + new OsuSpriteText + { + Colour = colours.Pink, + Text = "Change the way osu! behaves", + TextSize = 18, + Margin = new MarginPadding { + Left = OptionsOverlay.CONTENT_MARGINS, + Bottom = 30 + }, + }, + SearchTextBox = new SearchTextBox + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Width = 0.95f, + Margin = new MarginPadding { + Top = 20, + Bottom = 20 + }, + Exit = () => Exit(), + }, + } + } + }; + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + // the point at which we will start anchoring to the top. + float anchorOffset = SearchTextBox.Y; + + float scrollPosition = currentScrollOffset(); + + // we want to anchor the search field to the top of the screen when scrolling. + Margin = new MarginPadding { Top = Math.Max(0, scrollPosition - anchorOffset) }; + + // we don't want the header to scroll when scrolling beyond the upper extent. + Y = Math.Min(0, scrollPosition); + + // we get darker as scroll progresses + background.Alpha = Math.Min(1, scrollPosition / anchorOffset) * 0.5f; + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Options/OptionsSection.cs b/osu.Game/Overlays/Options/OptionsSection.cs index d5dafad9ba..5e36f79467 100644 --- a/osu.Game/Overlays/Options/OptionsSection.cs +++ b/osu.Game/Overlays/Options/OptionsSection.cs @@ -10,10 +10,12 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Overlays.Options { - public abstract class OptionsSection : Container + public abstract class OptionsSection : Container, IHasFilterableChildren { protected FillFlowContainer FlowContent; protected override Container<Drawable> Content => FlowContent; @@ -21,6 +23,16 @@ namespace osu.Game.Overlays.Options public abstract FontAwesome Icon { get; } public abstract string Header { get; } + public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>(); + public string[] FilterTerms => new[] { Header }; + public bool MatchingCurrentFilter + { + set + { + FadeTo(value ? 1 : 0); + } + } + private readonly SpriteText headerLabel; protected OptionsSection() diff --git a/osu.Game/Overlays/Options/OptionsSubsection.cs b/osu.Game/Overlays/Options/OptionsSubsection.cs index 9fd2e8fb1e..ff9e60c273 100644 --- a/osu.Game/Overlays/Options/OptionsSubsection.cs +++ b/osu.Game/Overlays/Options/OptionsSubsection.cs @@ -6,10 +6,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Game.Graphics.Sprites; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Overlays.Options { - public abstract class OptionsSubsection : FillFlowContainer + public abstract class OptionsSubsection : FillFlowContainer, IHasFilterableChildren { protected override Container<Drawable> Content => content; @@ -17,6 +19,16 @@ namespace osu.Game.Overlays.Options protected abstract string Header { get; } + public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>(); + public string[] FilterTerms => new[] { Header }; + public bool MatchingCurrentFilter + { + set + { + FadeTo(value ? 1 : 0); + } + } + protected OptionsSubsection() { RelativeSizeAxes = Axes.X; diff --git a/osu.Game/Overlays/OptionsOverlay.cs b/osu.Game/Overlays/OptionsOverlay.cs index dcbce80c69..6d1a3a64fc 100644 --- a/osu.Game/Overlays/OptionsOverlay.cs +++ b/osu.Game/Overlays/OptionsOverlay.cs @@ -10,9 +10,8 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Options; using System; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Options.Sections; +using osu.Framework.Input; namespace osu.Game.Overlays { @@ -32,6 +31,13 @@ namespace osu.Game.Overlays private Sidebar sidebar; private SidebarButton[] sidebarButtons; private OptionsSection[] sections; + + private OptionsHeader header; + + private OptionsFooter footer; + + private SearchContainer searchContainer; + private float lastKnownScroll; public OptionsOverlay() @@ -41,7 +47,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuGame game, OsuColour colours) + private void load(OsuGame game) { sections = new OptionsSection[] { @@ -69,39 +75,20 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Y, Width = width, Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, - Children = new[] + Children = new Drawable[] { - new FillFlowContainer + searchContainer = new SearchContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Direction = FillDirection.Vertical, - - Children = new Drawable[] - { - new OsuSpriteText - { - Text = "settings", - TextSize = 40, - Margin = new MarginPadding { Left = CONTENT_MARGINS, Top = Toolbar.Toolbar.TOOLTIP_HEIGHT }, - }, - new OsuSpriteText - { - Colour = colours.Pink, - Text = "Change the way osu! behaves", - TextSize = 18, - Margin = new MarginPadding { Left = CONTENT_MARGINS, Bottom = 30 }, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - Children = sections, - }, - new OptionsFooter() - } - } + Children = sections, + }, + footer = new OptionsFooter(), + header = new OptionsHeader(() => scrollContainer.Current) + { + Exit = Hide, + }, } }, sidebar = new Sidebar @@ -118,9 +105,20 @@ namespace osu.Game.Overlays } }; + header.SearchTextBox.Current.ValueChanged += newValue => searchContainer.SearchTerm = newValue; + scrollContainer.Padding = new MarginPadding { Top = game?.Toolbar.DrawHeight ?? 0 }; } + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + //we need to update these manually because we can't put the OptionsHeader inside the SearchContainer (due to its anchoring). + searchContainer.Y = header.DrawHeight; + footer.Y = searchContainer.Y + searchContainer.DrawHeight; + } + protected override void Update() { base.Update(); @@ -157,6 +155,8 @@ namespace osu.Game.Overlays scrollContainer.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); sidebar.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); FadeTo(1, TRANSITION_LENGTH / 2); + + header.SearchTextBox.HoldFocus = true; } protected override void PopOut() @@ -166,6 +166,15 @@ namespace osu.Game.Overlays scrollContainer.MoveToX(-width, TRANSITION_LENGTH, EasingTypes.OutQuint); sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, EasingTypes.OutQuint); FadeTo(0, TRANSITION_LENGTH / 2); + + header.SearchTextBox.HoldFocus = false; + header.SearchTextBox.TriggerFocusLost(); + } + + protected override bool OnFocus(InputState state) + { + header.SearchTextBox.TriggerFocus(state); + return false; } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ebe92d0cad..ee6153dc55 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -79,6 +79,7 @@ <Compile Include="Overlays\Music\FilterControl.cs" /> <Compile Include="Overlays\Music\PlaylistItem.cs" /> <Compile Include="Overlays\Music\PlaylistList.cs" /> + <Compile Include="Overlays\Options\OptionsHeader.cs" /> <Compile Include="Overlays\Options\Sections\Audio\MainMenuOptions.cs" /> <Compile Include="Overlays\Toolbar\ToolbarChatButton.cs" /> <Compile Include="Rulesets\Beatmaps\BeatmapConverter.cs" /> @@ -384,7 +385,7 @@ <Compile Include="Configuration\ScreenshotFormat.cs" /> <Compile Include="Graphics\OsuColour.cs" /> <Compile Include="Screens\Select\FilterControl.cs" /> - <Compile Include="Screens\Select\SearchTextBox.cs" /> + <Compile Include="Graphics\UserInterface\SearchTextBox.cs" /> <Compile Include="Screens\Select\FooterButton.cs" /> <Compile Include="Screens\Select\Footer.cs" /> <Compile Include="Screens\Play\SongProgress.cs" />