diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index b9cb406ae0..8ae619cdc0 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -123,6 +123,8 @@ namespace osu.Game.Graphics.Containers originalSectionsMargin = sectionsContainer.Margin; } + public void ScrollTo(Drawable section) => ScrollContainer.ScrollTo(ScrollContainer.GetChildPosInContent(section) - FixedHeader.BoundingBox.Height); + private float lastKnownScroll; protected override void UpdateAfterChildren() { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 961e296050..843861c0da 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -56,6 +56,8 @@ namespace osu.Game } } + public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight; + private OsuScreen screenStack; private VolumeControl volume; @@ -360,7 +362,7 @@ namespace osu.Game { base.UpdateAfterChildren(); - mainContent.Padding = new MarginPadding { Top = Toolbar.Position.Y + Toolbar.DrawHeight }; + mainContent.Padding = new MarginPadding { Top = ToolbarOffset }; Cursor.State = currentScreen?.HasLocalCursorDisplayed == false ? Visibility.Visible : Visibility.Hidden; } diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index 6c91f69fd9..44d296a079 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; +using osu.Framework; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -12,7 +14,7 @@ using osu.Game.Overlays.Toolbar; namespace osu.Game.Overlays.Settings { - public class Sidebar : Container + public class Sidebar : Container, IStateful { private readonly FillFlowContainer content; internal const float DEFAULT_WIDTH = ToolbarButton.WIDTH; @@ -47,24 +49,29 @@ namespace osu.Game.Overlays.Settings } private ScheduledDelegate expandEvent; + private ExpandedState state; protected override bool OnHover(InputState state) { - expandEvent = Scheduler.AddDelayed(() => - { - expandEvent = null; - ResizeTo(new Vector2(EXPANDED_WIDTH, Height), 150, EasingTypes.OutQuad); - }, 750); + queueExpandIfHovering(); return true; } protected override void OnHoverLost(InputState state) { expandEvent?.Cancel(); - ResizeTo(new Vector2(DEFAULT_WIDTH, Height), 150, EasingTypes.OutQuad); + lastHoveredButton = null; + State = ExpandedState.Contracted; + base.OnHoverLost(state); } + protected override bool OnMouseMove(InputState state) + { + queueExpandIfHovering(); + return base.OnMouseMove(state); + } + private class SidebarScrollContainer : ScrollContainer { public SidebarScrollContainer() @@ -74,5 +81,52 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.Both; } } + + public ExpandedState State + { + get { return state; } + set + { + if (state == value) return; + + state = value; + + switch (state) + { + default: + ResizeTo(new Vector2(DEFAULT_WIDTH, Height), 500, EasingTypes.OutQuint); + break; + case ExpandedState.Expanded: + ResizeTo(new Vector2(EXPANDED_WIDTH, Height), 500, EasingTypes.OutQuint); + break; + } + } + } + + private Drawable lastHoveredButton; + + private Drawable hoveredButton => content.Children.FirstOrDefault(c => c.IsHovered); + + private void queueExpandIfHovering() + { + // only expand when we hover a different button. + if (lastHoveredButton == hoveredButton) return; + + if (!IsHovered) return; + + if (State != ExpandedState.Expanded) + { + expandEvent?.Cancel(); + expandEvent = Scheduler.AddDelayed(() => State = ExpandedState.Expanded, 750); + } + + lastHoveredButton = hoveredButton; + } + } + + public enum ExpandedState + { + Contracted, + Expanded, } } \ No newline at end of file diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 4a5a0de890..66b15234c3 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -35,6 +36,8 @@ namespace osu.Game.Overlays private SearchTextBox searchTextBox; + private Func getToolbarHeight; + public SettingsOverlay() { RelativeSizeAxes = Axes.Y; @@ -93,7 +96,11 @@ namespace osu.Game.Overlays new SidebarButton { Section = section, - Action = b => sectionsContainer.ScrollContainer.ScrollTo(b), + Action = s => + { + sectionsContainer.ScrollTo(s); + sidebar.State = ExpandedState.Contracted; + }, } ).ToArray() } @@ -111,7 +118,7 @@ namespace osu.Game.Overlays searchTextBox.Current.ValueChanged += newValue => sectionsContainer.SearchContainer.SearchTerm = newValue; - sectionsContainer.Padding = new MarginPadding { Top = game?.Toolbar.DrawHeight ?? 0 }; + getToolbarHeight = () => game?.ToolbarOffset ?? 0; } protected override void PopIn() @@ -148,6 +155,14 @@ namespace osu.Game.Overlays base.OnFocus(state); } + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + sectionsContainer.Margin = new MarginPadding { Left = sidebar.DrawWidth }; + sectionsContainer.Padding = new MarginPadding { Top = getToolbarHeight() }; + } + private class SettingsSectionsContainer : SectionsContainer { public SearchContainer SearchContainer;