From 24a813e907c19aae3dddae4c1bd4d4d2e7e4eb5a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 20 May 2017 04:41:06 +0800 Subject: [PATCH 01/27] Basic children management of SectionsContainer. --- .../Graphics/Containers/SectionsContainer.cs | 74 +++++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 2 files changed, 75 insertions(+) create mode 100644 osu.Game/Graphics/Containers/SectionsContainer.cs diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs new file mode 100644 index 0000000000..9c2485c49c --- /dev/null +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -0,0 +1,74 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Graphics.Containers +{ + /// + /// A container that can scroll to each section inside it. + /// + public class SectionsContainer : Container + { + private Drawable expandableHeader, fixedHeader; + private ScrollContainer scrollContainer; + + public Drawable ExpandableHeader + { + get { return expandableHeader; } + set + { + if (value == expandableHeader) return; + + scrollContainer.Remove(expandableHeader); + expandableHeader = value; + expandableHeader.Depth = float.MinValue; + scrollContainer.Add(expandableHeader); + } + } + + public Drawable FixedHeader + { + get { return fixedHeader; } + set + { + if (value == fixedHeader) return; + + scrollContainer.Remove(fixedHeader); + fixedHeader = value; + fixedHeader.Depth = float.MinValue / 2; + scrollContainer.Add(fixedHeader); + } + } + + private List sections = new List(); + public IEnumerable Sections + { + get { return sections; } + set + { + if (value == sections) return; + + foreach (var section in sections) + scrollContainer.Remove(section); + + sections = value.ToList(); + scrollContainer.Add(value); + } + } + + public SectionsContainer() + { + Add(scrollContainer = new ScrollContainer + { + RelativeSizeAxes = Axes.Both + }); + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ee906caa9b..1200276027 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -85,6 +85,7 @@ + From 058c5e18a424fcdbc5b29741ac198c1cfc17cfb3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 20 May 2017 05:48:40 +0800 Subject: [PATCH 02/27] Scrolling support for SectionsContainer. --- .../Graphics/Containers/SectionsContainer.cs | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 9c2485c49c..3557a09622 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -26,10 +24,11 @@ namespace osu.Game.Graphics.Containers { if (value == expandableHeader) return; - scrollContainer.Remove(expandableHeader); + Remove(expandableHeader); expandableHeader = value; expandableHeader.Depth = float.MinValue; - scrollContainer.Add(expandableHeader); + Add(expandableHeader); + updateSectionMargin(); } } @@ -40,10 +39,11 @@ namespace osu.Game.Graphics.Containers { if (value == fixedHeader) return; - scrollContainer.Remove(fixedHeader); + Remove(fixedHeader); fixedHeader = value; fixedHeader.Depth = float.MinValue / 2; - scrollContainer.Add(fixedHeader); + Add(fixedHeader); + updateSectionMargin(); } } @@ -59,10 +59,25 @@ namespace osu.Game.Graphics.Containers scrollContainer.Remove(section); sections = value.ToList(); - scrollContainer.Add(value); + if (sections.Count == 0) return; + + originalSectionMargin = sections[0].Margin; + updateSectionMargin(); + scrollContainer.Add(sections); } } + private MarginPadding originalSectionMargin; + private void updateSectionMargin() + { + if (sections.Count == 0) return; + + var newMargin = originalSectionMargin; + newMargin.Top += ExpandableHeader?.Height ?? 0 + FixedHeader?.Height ?? 0; + + sections[0].Margin = newMargin; + } + public SectionsContainer() { Add(scrollContainer = new ScrollContainer @@ -70,5 +85,17 @@ namespace osu.Game.Graphics.Containers RelativeSizeAxes = Axes.Both }); } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + if (expandableHeader == null) return; + + float position = scrollContainer.Current; + float offset = Math.Max(expandableHeader.Height, position); + + expandableHeader.Y = -offset; + fixedHeader.Y = -offset + expandableHeader.Height; + } } } From e06c917c95fc50e356ee0a9000c6caa6585e9776 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 20 May 2017 06:39:01 +0800 Subject: [PATCH 03/27] Selection support of SectionsContainer. --- .../Graphics/Containers/SectionsContainer.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 3557a09622..536d53554a 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -47,6 +48,9 @@ namespace osu.Game.Graphics.Containers } } + public Bindable SelectedSection { get; } = new Bindable(); + public void ScrollToSection(Drawable section) => scrollContainer.ScrollIntoView(section); + private List sections = new List(); public IEnumerable Sections { @@ -64,6 +68,7 @@ namespace osu.Game.Graphics.Containers originalSectionMargin = sections[0].Margin; updateSectionMargin(); scrollContainer.Add(sections); + SelectedSection.Value = sections[0]; } } @@ -86,6 +91,7 @@ namespace osu.Game.Graphics.Containers }); } + float lastKnownScroll; protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -96,6 +102,28 @@ namespace osu.Game.Graphics.Containers expandableHeader.Y = -offset; fixedHeader.Y = -offset + expandableHeader.Height; + + float currentScroll = scrollContainer.Current; + if (currentScroll != lastKnownScroll) + { + lastKnownScroll = currentScroll; + + Drawable bestMatch = null; + float minDiff = float.MaxValue; + + foreach (var section in sections) + { + float diff = Math.Abs(scrollContainer.GetChildPosInContent(section) - currentScroll); + if (diff < minDiff) + { + minDiff = diff; + bestMatch = section; + } + } + + if (bestMatch != null) + SelectedSection.Value = bestMatch; + } } } } From 473441dfd4e5f3b91f1c34ff4dff3b6d1e3864ee Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 20 May 2017 07:07:27 +0800 Subject: [PATCH 04/27] Fix fields being null. --- osu.Game/Graphics/Containers/SectionsContainer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 536d53554a..65bb318008 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -25,7 +25,8 @@ namespace osu.Game.Graphics.Containers { if (value == expandableHeader) return; - Remove(expandableHeader); + if (expandableHeader != null) + Remove(expandableHeader); expandableHeader = value; expandableHeader.Depth = float.MinValue; Add(expandableHeader); @@ -40,7 +41,8 @@ namespace osu.Game.Graphics.Containers { if (value == fixedHeader) return; - Remove(fixedHeader); + if (fixedHeader != null) + Remove(fixedHeader); fixedHeader = value; fixedHeader.Depth = float.MinValue / 2; Add(fixedHeader); From ecc222c0438b55d062a6853d8efc20a5b91f171e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 20 May 2017 07:20:46 +0800 Subject: [PATCH 05/27] Allow custom SectionsContainer. --- .../Graphics/Containers/SectionsContainer.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 65bb318008..d46292cd9a 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -16,7 +16,8 @@ namespace osu.Game.Graphics.Containers public class SectionsContainer : Container { private Drawable expandableHeader, fixedHeader; - private ScrollContainer scrollContainer; + private readonly ScrollContainer scrollContainer; + private readonly Container sectionsContainer; public Drawable ExpandableHeader { @@ -53,6 +54,13 @@ namespace osu.Game.Graphics.Containers public Bindable SelectedSection { get; } = new Bindable(); public void ScrollToSection(Drawable section) => scrollContainer.ScrollIntoView(section); + protected virtual Container CreateSectionsContainer() + => new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both + }; + private List sections = new List(); public IEnumerable Sections { @@ -62,14 +70,14 @@ namespace osu.Game.Graphics.Containers if (value == sections) return; foreach (var section in sections) - scrollContainer.Remove(section); + sectionsContainer.Remove(section); sections = value.ToList(); if (sections.Count == 0) return; originalSectionMargin = sections[0].Margin; updateSectionMargin(); - scrollContainer.Add(sections); + sectionsContainer.Add(sections); SelectedSection.Value = sections[0]; } } @@ -87,9 +95,10 @@ namespace osu.Game.Graphics.Containers public SectionsContainer() { - Add(scrollContainer = new ScrollContainer + Add(scrollContainer = new ScrollContainer() { - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { sectionsContainer = CreateSectionsContainer() } }); } From da47b0a2603fddc62af2c22b755e258d8d301f61 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 02:11:55 +0800 Subject: [PATCH 06/27] Fix margin and offset calculating. --- .../Graphics/Containers/SectionsContainer.cs | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index d46292cd9a..5f8ac332e4 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -29,9 +29,10 @@ namespace osu.Game.Graphics.Containers if (expandableHeader != null) Remove(expandableHeader); expandableHeader = value; + if (value == null) return; + expandableHeader.Depth = float.MinValue; Add(expandableHeader); - updateSectionMargin(); } } @@ -45,9 +46,10 @@ namespace osu.Game.Graphics.Containers if (fixedHeader != null) Remove(fixedHeader); fixedHeader = value; + if (value == null) return; + fixedHeader.Depth = float.MinValue / 2; Add(fixedHeader); - updateSectionMargin(); } } @@ -76,19 +78,19 @@ namespace osu.Game.Graphics.Containers if (sections.Count == 0) return; originalSectionMargin = sections[0].Margin; - updateSectionMargin(); sectionsContainer.Add(sections); SelectedSection.Value = sections[0]; } } + float headerHeight; private MarginPadding originalSectionMargin; private void updateSectionMargin() { if (sections.Count == 0) return; var newMargin = originalSectionMargin; - newMargin.Top += ExpandableHeader?.Height ?? 0 + FixedHeader?.Height ?? 0; + newMargin.Top += headerHeight; sections[0].Margin = newMargin; } @@ -102,23 +104,33 @@ namespace osu.Game.Graphics.Containers }); } - float lastKnownScroll; + float lastKnownScroll = float.NaN; protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); + + float height = (ExpandableHeader?.Height ?? 0) + (FixedHeader?.Height ?? 0); + if (height != headerHeight) + { + headerHeight = height; + updateSectionMargin(); + } + if (expandableHeader == null) return; - float position = scrollContainer.Current; - float offset = Math.Max(expandableHeader.Height, position); - - expandableHeader.Y = -offset; - fixedHeader.Y = -offset + expandableHeader.Height; - float currentScroll = scrollContainer.Current; if (currentScroll != lastKnownScroll) { lastKnownScroll = currentScroll; + if (expandableHeader != null) + { + float offset = Math.Min(expandableHeader.Height, currentScroll); + + expandableHeader.Y = -offset; + fixedHeader.Y = -offset + expandableHeader.Height; + } + Drawable bestMatch = null; float minDiff = float.MaxValue; From e040f297c60b4d4df0398b5dd162585eeea4d3cb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 02:15:40 +0800 Subject: [PATCH 07/27] Set Masking = false and expose ScrollContainer. --- osu.Game/Graphics/Containers/SectionsContainer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 5f8ac332e4..845970fde7 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.Containers public class SectionsContainer : Container { private Drawable expandableHeader, fixedHeader; - private readonly ScrollContainer scrollContainer; + public readonly ScrollContainer ScrollContainer; private readonly Container sectionsContainer; public Drawable ExpandableHeader @@ -54,7 +54,6 @@ namespace osu.Game.Graphics.Containers } public Bindable SelectedSection { get; } = new Bindable(); - public void ScrollToSection(Drawable section) => scrollContainer.ScrollIntoView(section); protected virtual Container CreateSectionsContainer() => new FillFlowContainer @@ -97,9 +96,10 @@ namespace osu.Game.Graphics.Containers public SectionsContainer() { - Add(scrollContainer = new ScrollContainer() + Add(ScrollContainer = new ScrollContainer() { RelativeSizeAxes = Axes.Both, + Masking = false, Children = new Drawable[] { sectionsContainer = CreateSectionsContainer() } }); } @@ -118,7 +118,7 @@ namespace osu.Game.Graphics.Containers if (expandableHeader == null) return; - float currentScroll = scrollContainer.Current; + float currentScroll = ScrollContainer.Current; if (currentScroll != lastKnownScroll) { lastKnownScroll = currentScroll; @@ -136,7 +136,7 @@ namespace osu.Game.Graphics.Containers foreach (var section in sections) { - float diff = Math.Abs(scrollContainer.GetChildPosInContent(section) - currentScroll); + float diff = Math.Abs(ScrollContainer.GetChildPosInContent(section) - currentScroll); if (diff < minDiff) { minDiff = diff; From 72621c81dc076908b67f21123b8ff0cca34b4ee0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 02:37:34 +0800 Subject: [PATCH 08/27] Handle null and invalidation of headers. --- osu.Game/Graphics/Containers/SectionsContainer.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 845970fde7..768141511c 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -33,6 +33,7 @@ namespace osu.Game.Graphics.Containers expandableHeader.Depth = float.MinValue; Add(expandableHeader); + lastKnownScroll = float.NaN; } } @@ -50,6 +51,7 @@ namespace osu.Game.Graphics.Containers fixedHeader.Depth = float.MinValue / 2; Add(fixedHeader); + lastKnownScroll = float.NaN; } } @@ -79,6 +81,7 @@ namespace osu.Game.Graphics.Containers originalSectionMargin = sections[0].Margin; sectionsContainer.Add(sections); SelectedSection.Value = sections[0]; + lastKnownScroll = float.NaN; } } @@ -104,7 +107,7 @@ namespace osu.Game.Graphics.Containers }); } - float lastKnownScroll = float.NaN; + float lastKnownScroll; protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -116,14 +119,12 @@ namespace osu.Game.Graphics.Containers updateSectionMargin(); } - if (expandableHeader == null) return; - float currentScroll = ScrollContainer.Current; if (currentScroll != lastKnownScroll) { lastKnownScroll = currentScroll; - if (expandableHeader != null) + if (expandableHeader != null && fixedHeader != null) { float offset = Math.Min(expandableHeader.Height, currentScroll); From 201b44dbf1f9421885d65f59eec11b3ca40f1182 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 03:02:51 +0800 Subject: [PATCH 09/27] Do not make the name confusing. --- osu.Game/Graphics/Containers/SectionsContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 768141511c..1cf1219941 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -57,7 +57,7 @@ namespace osu.Game.Graphics.Containers public Bindable SelectedSection { get; } = new Bindable(); - protected virtual Container CreateSectionsContainer() + protected virtual Container CreateScrollContentContainer() => new FillFlowContainer { Direction = FillDirection.Vertical, @@ -103,7 +103,7 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, Masking = false, - Children = new Drawable[] { sectionsContainer = CreateSectionsContainer() } + Children = new Drawable[] { sectionsContainer = CreateScrollContentContainer() } }); } From 93668e53a01427a2682d2dd169a2803131557a91 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 03:44:03 +0800 Subject: [PATCH 10/27] Add footer support. --- .../Graphics/Containers/SectionsContainer.cs | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 1cf1219941..09a85c7dd3 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.Containers /// public class SectionsContainer : Container { - private Drawable expandableHeader, fixedHeader; + private Drawable expandableHeader, fixedHeader, footer; public readonly ScrollContainer ScrollContainer; private readonly Container sectionsContainer; @@ -31,7 +31,6 @@ namespace osu.Game.Graphics.Containers expandableHeader = value; if (value == null) return; - expandableHeader.Depth = float.MinValue; Add(expandableHeader); lastKnownScroll = float.NaN; } @@ -49,12 +48,30 @@ namespace osu.Game.Graphics.Containers fixedHeader = value; if (value == null) return; - fixedHeader.Depth = float.MinValue / 2; Add(fixedHeader); lastKnownScroll = float.NaN; } } + public Drawable Footer + { + get { return footer; } + set + { + if (value == footer) return; + + if (footer != null) + ScrollContainer.Remove(footer); + footer = value; + if (value == null) return; + + footer.Anchor |= Anchor.y2; + footer.Origin |= Anchor.y2; + ScrollContainer.Add(footer); + lastKnownScroll = float.NaN; + } + } + public Bindable SelectedSection { get; } = new Bindable(); protected virtual Container CreateScrollContentContainer() @@ -78,23 +95,23 @@ namespace osu.Game.Graphics.Containers sections = value.ToList(); if (sections.Count == 0) return; - originalSectionMargin = sections[0].Margin; sectionsContainer.Add(sections); SelectedSection.Value = sections[0]; lastKnownScroll = float.NaN; } } - float headerHeight; - private MarginPadding originalSectionMargin; - private void updateSectionMargin() + private float headerHeight, footerHeight; + private MarginPadding originalSectionsMargin; + private void updateSectionsMargin() { if (sections.Count == 0) return; - var newMargin = originalSectionMargin; + var newMargin = originalSectionsMargin; newMargin.Top += headerHeight; + newMargin.Bottom += footerHeight; - sections[0].Margin = newMargin; + sectionsContainer.Margin = newMargin; } public SectionsContainer() @@ -105,6 +122,7 @@ namespace osu.Game.Graphics.Containers Masking = false, Children = new Drawable[] { sectionsContainer = CreateScrollContentContainer() } }); + originalSectionsMargin = sectionsContainer.Margin; } float lastKnownScroll; @@ -112,11 +130,13 @@ namespace osu.Game.Graphics.Containers { base.UpdateAfterChildren(); - float height = (ExpandableHeader?.Height ?? 0) + (FixedHeader?.Height ?? 0); - if (height != headerHeight) + float headerHeight = (ExpandableHeader?.Height ?? 0) + (FixedHeader?.Height ?? 0); + float footerHeight = Footer?.Height ?? 0; + if (headerHeight != this.headerHeight || footerHeight != this.footerHeight) { - headerHeight = height; - updateSectionMargin(); + this.headerHeight = headerHeight; + this.footerHeight = footerHeight; + updateSectionsMargin(); } float currentScroll = ScrollContainer.Current; From 35712514a4baf27fb8aa891499eadcdad9e346e8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 03:50:04 +0800 Subject: [PATCH 11/27] Update settings UI using SectionsContainer basically. --- osu.Game/Overlays/SettingsOverlay.cs | 99 +++++++++++----------------- 1 file changed, 40 insertions(+), 59 deletions(-) diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 71ad18e081..d348b2c6a1 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -7,10 +7,11 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Game.Overlays.Settings; -using System; -using osu.Game.Overlays.Settings.Sections; using osu.Framework.Input; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; +using osu.Game.Overlays.Settings.Sections; namespace osu.Game.Overlays { @@ -37,6 +38,8 @@ namespace osu.Game.Overlays private SearchContainer searchContainer; + private SettingsSectionsContainer sectionsContainer; + private float lastKnownScroll; public SettingsOverlay() @@ -68,27 +71,27 @@ namespace osu.Game.Overlays Colour = Color4.Black, Alpha = 0.6f, }, - scrollContainer = new ScrollContainer + sectionsContainer = new SettingsSectionsContainer { - ScrollDraggerVisible = false, RelativeSizeAxes = Axes.Y, Width = width, Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, - Children = new Drawable[] + ExpandableHeader = header = new SettingsHeader(() => sectionsContainer.ScrollContainer.Current), + FixedHeader = new SearchTextBox { - searchContainer = new SearchContainer + RelativeSizeAxes = Axes.X, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Width = 0.95f, + Margin = new MarginPadding { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - Children = sections, + Top = 20, + Bottom = 20 }, - footer = new SettingsFooter(), - header = new SettingsHeader(() => scrollContainer.Current) - { - Exit = Hide, - }, - } + Exit = Hide, + }, + Sections = sections, + Footer = footer = new SettingsFooter() }, sidebar = new Sidebar { @@ -104,54 +107,16 @@ namespace osu.Game.Overlays } }; - header.SearchTextBox.Current.ValueChanged += newValue => searchContainer.SearchTerm = newValue; + //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 SettingsHeader inside the SearchContainer (due to its anchoring). - searchContainer.Y = header.DrawHeight; - footer.Y = searchContainer.Y + searchContainer.DrawHeight; - } - - protected override void Update() - { - base.Update(); - - float currentScroll = scrollContainer.Current; - if (currentScroll != lastKnownScroll) - { - lastKnownScroll = currentScroll; - - SettingsSection bestCandidate = null; - float bestDistance = float.MaxValue; - - foreach (SettingsSection section in sections) - { - float distance = Math.Abs(scrollContainer.GetChildPosInContent(section) - currentScroll); - if (distance < bestDistance) - { - bestDistance = distance; - bestCandidate = section; - } - } - - var previous = sidebarButtons.SingleOrDefault(sb => sb.Selected); - var next = sidebarButtons.SingleOrDefault(sb => sb.Section == bestCandidate); - if (previous != null) previous.Selected = false; - if (next != null) next.Selected = true; - } + sectionsContainer.Padding = new MarginPadding { Top = game?.Toolbar.DrawHeight ?? 0 }; } protected override void PopIn() { base.PopIn(); - scrollContainer.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); + sectionsContainer.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); sidebar.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); FadeTo(1, TRANSITION_LENGTH / 2); @@ -162,7 +127,7 @@ namespace osu.Game.Overlays { base.PopOut(); - scrollContainer.MoveToX(-width, TRANSITION_LENGTH, EasingTypes.OutQuint); + sectionsContainer.MoveToX(-width, TRANSITION_LENGTH, EasingTypes.OutQuint); sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, EasingTypes.OutQuint); FadeTo(0, TRANSITION_LENGTH / 2); @@ -175,5 +140,21 @@ namespace osu.Game.Overlays header.SearchTextBox.TriggerFocus(state); return false; } + + private class SettingsSectionsContainer : SectionsContainer + { + public SearchContainer SearchContainer; + protected override Container CreateScrollContentContainer() + => SearchContainer = new SearchContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + }; + public SettingsSectionsContainer() + { + ScrollContainer.ScrollDraggerVisible = false; + } + } } } From a98f109d733836bb8bb6e72b93ad12d0f65bb106 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 04:01:07 +0800 Subject: [PATCH 12/27] Use LayoutSize for header and footer layout. --- osu.Game/Graphics/Containers/SectionsContainer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 09a85c7dd3..b0de350930 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -130,8 +130,8 @@ namespace osu.Game.Graphics.Containers { base.UpdateAfterChildren(); - float headerHeight = (ExpandableHeader?.Height ?? 0) + (FixedHeader?.Height ?? 0); - float footerHeight = Footer?.Height ?? 0; + float headerHeight = (ExpandableHeader?.LayoutSize.Y ?? 0) + (FixedHeader?.LayoutSize.Y ?? 0); + float footerHeight = Footer?.LayoutSize.Y ?? 0; if (headerHeight != this.headerHeight || footerHeight != this.footerHeight) { this.headerHeight = headerHeight; @@ -146,10 +146,10 @@ namespace osu.Game.Graphics.Containers if (expandableHeader != null && fixedHeader != null) { - float offset = Math.Min(expandableHeader.Height, currentScroll); + float offset = Math.Min(expandableHeader.LayoutSize.Y, currentScroll); expandableHeader.Y = -offset; - fixedHeader.Y = -offset + expandableHeader.Height; + fixedHeader.Y = -offset + expandableHeader.LayoutSize.Y; } Drawable bestMatch = null; From aa409ac1a9931e45e6083ed71fe455469541932d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 04:12:16 +0800 Subject: [PATCH 13/27] Move SearchTextBox out of SettingsHeader. --- osu.Game/Overlays/Settings/SettingsHeader.cs | 60 ++------------------ osu.Game/Overlays/SettingsOverlay.cs | 46 +++++++++------ 2 files changed, 33 insertions(+), 73 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index 56018dc7d9..c554b54a87 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -1,34 +1,16 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // 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.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using OpenTK.Graphics; namespace osu.Game.Overlays.Settings { public class SettingsHeader : Container { - public SearchTextBox SearchTextBox; - - private Box background; - - private readonly Func currentScrollOffset; - - public Action Exit; - - /// A reference to the current scroll position of the ScrollContainer we are contained within. - public SettingsHeader(Func currentScrollOffset) - { - this.currentScrollOffset = currentScrollOffset; - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -37,11 +19,6 @@ namespace osu.Game.Overlays.Settings Children = new Drawable[] { - background = new Box - { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, - }, new FillFlowContainer { AutoSizeAxes = Axes.Y, @@ -53,7 +30,8 @@ namespace osu.Game.Overlays.Settings { Text = "settings", TextSize = 40, - Margin = new MarginPadding { + Margin = new MarginPadding + { Left = SettingsOverlay.CONTENT_MARGINS, Top = Toolbar.Toolbar.TOOLTIP_HEIGHT }, @@ -63,45 +41,15 @@ namespace osu.Game.Overlays.Settings Colour = colours.Pink, Text = "Change the way osu! behaves", TextSize = 18, - Margin = new MarginPadding { + Margin = new MarginPadding + { Left = SettingsOverlay.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/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index d348b2c6a1..05834c9823 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -27,20 +27,13 @@ namespace osu.Game.Overlays private const float sidebar_padding = 10; - private ScrollContainer scrollContainer; private Sidebar sidebar; private SidebarButton[] sidebarButtons; private SettingsSection[] sections; - private SettingsHeader header; - - private SettingsFooter footer; - - private SearchContainer searchContainer; - private SettingsSectionsContainer sectionsContainer; - private float lastKnownScroll; + private SearchTextBox searchTextBox; public SettingsOverlay() { @@ -76,8 +69,8 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Y, Width = width, Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, - ExpandableHeader = header = new SettingsHeader(() => sectionsContainer.ScrollContainer.Current), - FixedHeader = new SearchTextBox + ExpandableHeader = new SettingsHeader(), + FixedHeader = searchTextBox = new SearchTextBox { RelativeSizeAxes = Axes.X, Origin = Anchor.TopCentre, @@ -91,7 +84,7 @@ namespace osu.Game.Overlays Exit = Hide, }, Sections = sections, - Footer = footer = new SettingsFooter() + Footer = new SettingsFooter() }, sidebar = new Sidebar { @@ -101,13 +94,13 @@ namespace osu.Game.Overlays { Selected = sections[0] == section, Section = section, - Action = () => scrollContainer.ScrollIntoView(section), + Action = () => sectionsContainer.ScrollContainer.ScrollIntoView(section), } ).ToArray() } }; - //header.SearchTextBox.Current.ValueChanged += newValue => searchContainer.SearchTerm = newValue; + searchTextBox.Current.ValueChanged += newValue => sectionsContainer.SearchContainer.SearchTerm = newValue; sectionsContainer.Padding = new MarginPadding { Top = game?.Toolbar.DrawHeight ?? 0 }; } @@ -120,7 +113,7 @@ namespace osu.Game.Overlays sidebar.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); FadeTo(1, TRANSITION_LENGTH / 2); - header.SearchTextBox.HoldFocus = true; + searchTextBox.HoldFocus = true; } protected override void PopOut() @@ -131,19 +124,21 @@ namespace osu.Game.Overlays sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, EasingTypes.OutQuint); FadeTo(0, TRANSITION_LENGTH / 2); - header.SearchTextBox.HoldFocus = false; - header.SearchTextBox.TriggerFocusLost(); + searchTextBox.HoldFocus = false; + searchTextBox.TriggerFocusLost(); } protected override bool OnFocus(InputState state) { - header.SearchTextBox.TriggerFocus(state); + searchTextBox.TriggerFocus(state); return false; } private class SettingsSectionsContainer : SectionsContainer { public SearchContainer SearchContainer; + private readonly Box headerBackground; + protected override Container CreateScrollContentContainer() => SearchContainer = new SearchContainer { @@ -151,9 +146,26 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X, Direction = FillDirection.Vertical, }; + public SettingsSectionsContainer() { ScrollContainer.ScrollDraggerVisible = false; + Add(headerBackground = new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.X, + Depth = float.MaxValue + }); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + // no null check because the usage of this class is strict + headerBackground.Height = ExpandableHeader.LayoutSize.Y + FixedHeader.LayoutSize.Y; + headerBackground.Y = ExpandableHeader.Y; + headerBackground.Alpha = -ExpandableHeader.Y / ExpandableHeader.LayoutSize.Y * 0.5f; } } } From f06f8b4dcd67d7e77fa3c567961267ed18fab095 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 04:32:15 +0800 Subject: [PATCH 14/27] Make sidebar buttons working. --- osu.Game/Overlays/Settings/SidebarButton.cs | 5 +++-- osu.Game/Overlays/SettingsOverlay.cs | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index 766c6cf7e2..b6e4ad3f5e 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Settings private readonly Box backgroundBox; private readonly Box selectionIndicator; private readonly Container text; - public Action Action; + public Action Action; private SettingsSection section; public SettingsSection Section @@ -75,6 +75,7 @@ namespace osu.Game.Overlays.Settings { Width = Sidebar.DEFAULT_WIDTH, RelativeSizeAxes = Axes.Y, + Colour = OsuColour.Gray(0.6f), Children = new[] { headerText = new OsuSpriteText @@ -110,7 +111,7 @@ namespace osu.Game.Overlays.Settings protected override bool OnClick(InputState state) { - Action?.Invoke(); + Action?.Invoke(section); backgroundBox.FlashColour(Color4.White, 400); return true; } diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 05834c9823..af24a057e9 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays private Sidebar sidebar; private SidebarButton[] sidebarButtons; - private SettingsSection[] sections; + private SidebarButton selectedSidebarButton; private SettingsSectionsContainer sectionsContainer; @@ -44,7 +44,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuGame game) { - sections = new SettingsSection[] + var sections = new SettingsSection[] { new GeneralSection(), new GraphicsSection(), @@ -92,14 +92,23 @@ namespace osu.Game.Overlays Children = sidebarButtons = sections.Select(section => new SidebarButton { - Selected = sections[0] == section, Section = section, - Action = () => sectionsContainer.ScrollContainer.ScrollIntoView(section), + Action = sectionsContainer.ScrollContainer.ScrollIntoView, } ).ToArray() } }; + selectedSidebarButton = sidebarButtons[0]; + selectedSidebarButton.Selected = true; + + sectionsContainer.SelectedSection.ValueChanged += section => + { + selectedSidebarButton.Selected = false; + selectedSidebarButton = sidebarButtons.Single(b => b.Section == section); + selectedSidebarButton.Selected = true; + }; + searchTextBox.Current.ValueChanged += newValue => sectionsContainer.SearchContainer.SearchTerm = newValue; sectionsContainer.Padding = new MarginPadding { Top = game?.Toolbar.DrawHeight ?? 0 }; From 7357076c4d3bf368f635886ff25bc667995a9f09 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 21 May 2017 04:48:43 +0800 Subject: [PATCH 15/27] CI fixes. --- .../Graphics/Containers/SectionsContainer.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index b0de350930..7b57cb1b56 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -87,8 +87,6 @@ namespace osu.Game.Graphics.Containers get { return sections; } set { - if (value == sections) return; - foreach (var section in sections) sectionsContainer.Remove(section); @@ -102,7 +100,7 @@ namespace osu.Game.Graphics.Containers } private float headerHeight, footerHeight; - private MarginPadding originalSectionsMargin; + private readonly MarginPadding originalSectionsMargin; private void updateSectionsMargin() { if (sections.Count == 0) return; @@ -125,17 +123,17 @@ namespace osu.Game.Graphics.Containers originalSectionsMargin = sectionsContainer.Margin; } - float lastKnownScroll; + private float lastKnownScroll; protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - float headerHeight = (ExpandableHeader?.LayoutSize.Y ?? 0) + (FixedHeader?.LayoutSize.Y ?? 0); - float footerHeight = Footer?.LayoutSize.Y ?? 0; - if (headerHeight != this.headerHeight || footerHeight != this.footerHeight) + float headerH = (ExpandableHeader?.LayoutSize.Y ?? 0) + (FixedHeader?.LayoutSize.Y ?? 0); + float footerH = Footer?.LayoutSize.Y ?? 0; + if (headerH != headerHeight || footerH != footerHeight) { - this.headerHeight = headerHeight; - this.footerHeight = footerHeight; + headerHeight = headerH; + footerHeight = footerH; updateSectionsMargin(); } From d0ddd62f84ee3138b4724ba1b6b4fc477a35b2f2 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 14:10:37 +0900 Subject: [PATCH 16/27] Add ManiaHitResult to ManiaJudgement. --- .../Judgements/ManiaHitResult.cs | 18 ++++++++++++++++++ .../Judgements/ManiaJudgement.cs | 2 ++ 2 files changed, 20 insertions(+) create mode 100644 osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs new file mode 100644 index 0000000000..08c12a8151 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs @@ -0,0 +1,18 @@ +using System.ComponentModel; + +namespace osu.Game.Rulesets.Mania.Judgements +{ + public enum ManiaHitResult + { + [Description("PERFECT")] + Perfect, + [Description("GREAT")] + Great, + [Description("GOOD")] + Good, + [Description("OK")] + Ok, + [Description("BAD")] + Bad + } +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index 8dafbd01a5..eb544d79fc 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -10,5 +10,7 @@ namespace osu.Game.Rulesets.Mania.Judgements public override string ResultString => string.Empty; public override string MaxResultString => string.Empty; + + public ManiaHitResult ManiaResult; } } From 409464381c09a2f059e9cb7ef1dceb5900b135c1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 14:11:14 +0900 Subject: [PATCH 17/27] Expose HitWindows so they're accessible from the drawable hit objects. --- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 2 +- osu.Game.Rulesets.Mania/Objects/Note.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 701947c381..41bbe08d56 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// /// The key-release hit windows for this hold note. /// - protected HitWindows ReleaseHitWindows = new HitWindows(); + public HitWindows ReleaseHitWindows { get; protected set; } = new HitWindows(); public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) { diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 1d2e4169b5..e955f6658b 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// /// The key-press hit window for this note. /// - protected HitWindows HitWindows = new HitWindows(); + public HitWindows HitWindows { get; protected set; } = new HitWindows(); public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) { From c9723352977ecf57fbe8cfb579d8497482dd42a8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 15:25:37 +0900 Subject: [PATCH 18/27] Add InputTarget to capture input from columns before hit objects. --- osu.Game.Rulesets.Mania/UI/Column.cs | 34 +++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index dea00433e6..e1a925937d 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -95,6 +95,12 @@ namespace osu.Game.Rulesets.Mania.UI Name = "Hit objects", RelativeSizeAxes = Axes.Both, }, + // For column lighting, we need to capture input events before the notes + new InputTarget + { + KeyDown = onKeyDown, + KeyUp = onKeyUp + } } }, new Container @@ -178,12 +184,9 @@ namespace osu.Game.Rulesets.Mania.UI } } - public void Add(DrawableHitObject hitObject) - { - ControlPointContainer.Add(hitObject); - } + public void Add(DrawableHitObject hitObject) => ControlPointContainer.Add(hitObject); - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + private bool onKeyDown(InputState state, KeyDownEventArgs args) { if (args.Repeat) return false; @@ -197,7 +200,7 @@ namespace osu.Game.Rulesets.Mania.UI return false; } - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + private bool onKeyUp(InputState state, KeyUpEventArgs args) { if (args.Key == Key) { @@ -207,5 +210,24 @@ namespace osu.Game.Rulesets.Mania.UI return false; } + + /// + /// This is a simple container which delegates various input events that have to be captured before the notes. + /// + private class InputTarget : Container + { + public Func KeyDown; + public Func KeyUp; + + public InputTarget() + { + RelativeSizeAxes = Axes.Both; + AlwaysPresent = true; + Alpha = 0; + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => KeyDown?.Invoke(state, args) ?? false; + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => KeyUp?.Invoke(state, args) ?? false; + } } } From 3dfe88c0684064a80947de52360b1ebbb512e186 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 15:27:38 +0900 Subject: [PATCH 19/27] Make Key a bindable, pass down to drawable hit objects. --- .../Objects/Drawables/DrawableHoldNote.cs | 6 ++++-- .../Drawables/DrawableManiaHitObject.cs | 12 ++++++++++- .../Objects/Drawables/DrawableNote.cs | 6 ++++-- osu.Game.Rulesets.Mania/UI/Column.cs | 7 ++++++- .../UI/ManiaHitRenderer.cs | 12 +++++++++-- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 21 ++++++++++--------- 6 files changed, 46 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index d9e46f4720..f9d027e7ce 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -5,6 +5,8 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using OpenTK.Graphics; +using osu.Framework.Configuration; +using OpenTK.Input; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -14,8 +16,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private readonly BodyPiece bodyPiece; private readonly NotePiece tailPiece; - public DrawableHoldNote(HoldNote hitObject) - : base(hitObject) + public DrawableHoldNote(HoldNote hitObject, Bindable key = null) + : base(hitObject, key) { RelativeSizeAxes = Axes.Both; Height = (float)HitObject.Duration; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index d33a8c48ee..4e276fddb7 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -2,6 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; +using OpenTK.Input; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Objects.Drawables; @@ -11,13 +13,21 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public abstract class DrawableManiaHitObject : DrawableHitObject where TObject : ManiaHitObject { + /// + /// The key that will trigger input for this hit object. + /// + protected Bindable Key { get; private set; } = new Bindable(); + public new TObject HitObject; - protected DrawableManiaHitObject(TObject hitObject) + protected DrawableManiaHitObject(TObject hitObject, Bindable key = null) : base(hitObject) { HitObject = hitObject; + if (key != null) + Key.BindTo(key); + RelativePositionAxes = Axes.Y; Y = (float)HitObject.StartTime; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index b216c362f5..d0519c61a8 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -2,6 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; +using OpenTK.Input; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Objects.Drawables; @@ -12,8 +14,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { private readonly NotePiece headPiece; - public DrawableNote(Note hitObject) - : base(hitObject) + public DrawableNote(Note hitObject, Bindable key = null) + : base(hitObject, key) { RelativeSizeAxes = Axes.Both; Height = 100; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index e1a925937d..72c60b28c9 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -18,6 +18,8 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Beatmaps.Timing; +using System; +using osu.Framework.Configuration; namespace osu.Game.Rulesets.Mania.UI { @@ -33,7 +35,10 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; - public Key Key; + /// + /// The key that will trigger input actions for this column and hit objects contained inside it. + /// + public Bindable Key = new Bindable(); private readonly Box background; private readonly Container hitTargetBar; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index c67866dc10..4d734d231f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -4,6 +4,8 @@ using System; using System.Linq; using OpenTK; +using OpenTK.Input; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Timing; @@ -76,13 +78,19 @@ namespace osu.Game.Rulesets.Mania.UI protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) { + var maniaPlayfield = Playfield as ManiaPlayfield; + if (maniaPlayfield == null) + return null; + + Bindable key = maniaPlayfield.Columns.ElementAt(h.Column).Key; + var holdNote = h as HoldNote; if (holdNote != null) - return new DrawableHoldNote(holdNote); + return new DrawableHoldNote(holdNote, key); var note = h as Note; if (note != null) - return new DrawableNote(note); + return new DrawableNote(note, key); return null; } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 56a86873e9..70bdd3b13c 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -55,7 +55,8 @@ namespace osu.Game.Rulesets.Mania.UI } } - public readonly FlowContainer Columns; + private readonly FlowContainer columns; + public IEnumerable Columns => columns.Children; private readonly ControlPointContainer barlineContainer; @@ -87,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.UI RelativeSizeAxes = Axes.Both, Colour = Color4.Black }, - Columns = new FillFlowContainer + columns = new FillFlowContainer { Name = "Columns", RelativeSizeAxes = Axes.Y, @@ -114,7 +115,7 @@ namespace osu.Game.Rulesets.Mania.UI }; for (int i = 0; i < columnCount; i++) - Columns.Add(new Column(timingChanges)); + columns.Add(new Column(timingChanges)); TimeSpan = time_span_default; } @@ -133,17 +134,17 @@ namespace osu.Game.Rulesets.Mania.UI // Set the special column + colour + key for (int i = 0; i < columnCount; i++) { - Column column = Columns.Children.ElementAt(i); + Column column = Columns.ElementAt(i); column.IsSpecial = isSpecialColumn(i); if (!column.IsSpecial) continue; - column.Key = Key.Space; + column.Key.Value = Key.Space; column.AccentColour = specialColumnColour; } - var nonSpecialColumns = Columns.Children.Where(c => !c.IsSpecial).ToList(); + var nonSpecialColumns = Columns.Where(c => !c.IsSpecial).ToList(); // We'll set the colours of the non-special columns in a separate loop, because the non-special // column colours are mirrored across their centre and special styles mess with this @@ -162,11 +163,11 @@ namespace osu.Game.Rulesets.Mania.UI int keyOffset = default_keys.Length / 2 - nonSpecialColumns.Count / 2 + i; if (keyOffset >= 0 && keyOffset < default_keys.Length) - column.Key = default_keys[keyOffset]; + column.Key.Value = default_keys[keyOffset]; else // There is no default key defined for this column. Let's set this to Unknown for now // however note that this will be gone after bindings are in place - column.Key = Key.Unknown; + column.Key.Value = Key.Unknown; } } @@ -189,7 +190,7 @@ namespace osu.Game.Rulesets.Mania.UI } } - public override void Add(DrawableHitObject h) => Columns.Children.ElementAt(h.HitObject.Column).Add(h); + public override void Add(DrawableHitObject h) => Columns.ElementAt(h.HitObject.Column).Add(h); protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { @@ -225,7 +226,7 @@ namespace osu.Game.Rulesets.Mania.UI timeSpan = MathHelper.Clamp(timeSpan, time_span_min, time_span_max); barlineContainer.TimeSpan = value; - Columns.Children.ForEach(c => c.ControlPointContainer.TimeSpan = value); + Columns.ForEach(c => c.ControlPointContainer.TimeSpan = value); } } From dcf3148d23578776ecb8f484b1abb551935cb037 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 15:28:51 +0900 Subject: [PATCH 20/27] Fix osu!mania failing due to 0 hp. --- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 96f04f79d4..7a9572a0c7 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -22,5 +22,12 @@ namespace osu.Game.Rulesets.Mania.Scoring protected override void OnNewJudgement(ManiaJudgement judgement) { } + + protected override void Reset() + { + base.Reset(); + + Health.Value = 1; + } } } From 60e036b5f454655b3068897483a9ebd782fc2b1f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 15:29:02 +0900 Subject: [PATCH 21/27] Fix missing reference. --- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index adcdfd5fae..408f20033e 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -56,6 +56,7 @@ + From 9a578e036e4dac1632886458c65779be52fc1ec9 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 16:09:32 +0900 Subject: [PATCH 22/27] Add xmldoc. --- osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index eb544d79fc..6e69da3da7 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -11,6 +11,9 @@ namespace osu.Game.Rulesets.Mania.Judgements public override string MaxResultString => string.Empty; + /// + /// The hit result. + /// public ManiaHitResult ManiaResult; } } From 0f3cf18345c347cab2e3febbfe98214d5123234b Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 16:15:52 +0900 Subject: [PATCH 23/27] Forgot license header. --- osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs index 08c12a8151..207a1fb251 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaHitResult.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System.ComponentModel; namespace osu.Game.Rulesets.Mania.Judgements From 62c7e97a5f4acf00f5eedc85d884654b18767e2d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 22 May 2017 16:28:44 +0900 Subject: [PATCH 24/27] Add helper method to easily compare time offset to hit windows. --- .../Judgements/HitWindows.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs b/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs index 2a0ce88506..307c03c8eb 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Database; +using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Judgements { @@ -140,6 +141,26 @@ namespace osu.Game.Rulesets.Mania.Judgements Miss = BeatmapDifficulty.DifficultyRange(difficulty, miss_max, miss_mid, miss_min); } + /// + /// Retrieves the hit result for a time offset. + /// + /// The time offset. + /// The hit result, or null if the time offset results in a miss. + public ManiaHitResult? ResultFor(double hitOffset) + { + if (hitOffset <= Perfect / 2) + return ManiaHitResult.Perfect; + if (hitOffset <= Great / 2) + return ManiaHitResult.Great; + if (hitOffset <= Good / 2) + return ManiaHitResult.Good; + if (hitOffset <= Ok / 2) + return ManiaHitResult.Ok; + if (hitOffset <= Bad / 2) + return ManiaHitResult.Bad; + return null; + } + /// /// Constructs new hit windows which have been multiplied by a value. /// From 6f00f7f0d084b274d10531f489eda396d6708c41 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 22 May 2017 16:34:38 +0900 Subject: [PATCH 25/27] Update HitWindows.cs --- osu.Game.Rulesets.Mania/Judgements/HitWindows.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs b/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs index 307c03c8eb..674d83f6f2 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Database; -using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Judgements { From 85684e5fee4b70f8f1d35d8f1fe1598a6b2add46 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 22 May 2017 15:54:58 +0800 Subject: [PATCH 26/27] Do not scroll headers to when scrolling position is negative. --- 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 7b57cb1b56..5fdb5e869e 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -137,7 +137,7 @@ namespace osu.Game.Graphics.Containers updateSectionsMargin(); } - float currentScroll = ScrollContainer.Current; + float currentScroll = Math.Max(0, ScrollContainer.Current); if (currentScroll != lastKnownScroll) { lastKnownScroll = currentScroll; From 63259a34573957888ea7b94f4faa1aa82cace6e4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 22 May 2017 15:58:01 +0800 Subject: [PATCH 27/27] Fix depth of header background. Thanks to the order of adding to parent container, the depth value is actually not needed. --- osu.Game/Overlays/SettingsOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index af24a057e9..943545e858 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -162,8 +162,7 @@ namespace osu.Game.Overlays Add(headerBackground = new Box { Colour = Color4.Black, - RelativeSizeAxes = Axes.X, - Depth = float.MaxValue + RelativeSizeAxes = Axes.X }); }