From e6fbb199518c3c07a2f8a11f7d9a7f0fe2ccae8f Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 21 Apr 2022 03:59:36 +0700 Subject: [PATCH 01/14] Implement new search textbox design --- .../TestSceneShearedSearchTextBox.cs | 46 +++++ .../UserInterface/ShearedSearchTextBox.cs | 192 ++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs create mode 100644 osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs new file mode 100644 index 0000000000..e1dbf04133 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs @@ -0,0 +1,46 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneShearedSearchTextBox : OsuTestScene + { + [Test] + public void TestAllColourSchemes() + { + foreach (var scheme in Enum.GetValues(typeof(OverlayColourScheme)).Cast()) + AddStep($"set {scheme} scheme", () => Child = createContent(scheme)); + } + + private Drawable createContent(OverlayColourScheme colourScheme) + { + var colourProvider = new OverlayColourProvider(colourScheme); + + return new DependencyProvidingContainer + { + RelativeSizeAxes = Axes.Both, + CachedDependencies = new (Type, object)[] + { + (typeof(OverlayColourProvider), colourProvider) + }, + Children = new Drawable[] + { + new ShearedSearchTextBox + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Width = 0.5f + } + } + }; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs new file mode 100644 index 0000000000..e3dc118faa --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -0,0 +1,192 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +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.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; +using osuTK; +using osuTK.Graphics; +using osuTK.Input; + +namespace osu.Game.Graphics.UserInterface +{ + public class ShearedSearchTextBox : CompositeDrawable, IHasCurrentValue + { + private const float icon_container_width = 50; + private const float corner_radius = 10; + private const float height = 42; + private readonly Vector2 shear = new Vector2(0.2f, 0); + + public FocusedTextBox TextBox; + + public Bindable Current + { + get => TextBox.Current; + set => TextBox.Current = value; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Height = height; + Shear = shear; + Masking = true; + CornerRadius = corner_radius; + InternalChild = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + Colour = colourProvider.Background3, + RelativeSizeAxes = Axes.Both + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + Name = @"Search box container", + RelativeSizeAxes = Axes.Both, + CornerRadius = corner_radius, + Masking = true, + Children = new Drawable[] + { + new Box + { + Colour = colourProvider.Background4, + RelativeSizeAxes = Axes.Both + }, + TextBox = new SearchTextBox + { + Shear = -shear, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding + { + Horizontal = corner_radius + } + } + } + }, + new Container + { + Name = @"Icon container", + RelativeSizeAxes = Axes.Y, + Width = icon_container_width, + Origin = Anchor.CentreRight, + Anchor = Anchor.CentreRight, + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.Search, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(16), + Shear = -shear + } + } + } + } + }, + ColumnDimensions = new[] { new Dimension(), new Dimension(GridSizeMode.AutoSize) } + } + } + }; + } + + public override bool HandleNonPositionalInput => TextBox.HandleNonPositionalInput; + + private class SearchTextBox : FocusedTextBox + { + protected virtual bool AllowCommit => false; + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + BackgroundFocused = colourProvider.Background4; + BackgroundUnfocused = colourProvider.Background4; + Placeholder.Colour = Color4.White; + PlaceholderText = @"Search"; + } + + protected override SpriteText CreatePlaceholder() => new OsuSpriteText + { + Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold) + }; + + protected override Drawable GetDrawableCharacter(char c) => new FallingDownContainer + { + AutoSizeAxes = Axes.Both, + Child = new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold) }, + }; + + public override bool OnPressed(KeyBindingPressEvent e) + { + switch (e.Action) + { + case PlatformAction.MoveBackwardLine: + case PlatformAction.MoveForwardLine: + // Shift+delete is handled via PlatformAction on macOS. this is not so useful in the context of a SearchTextBox + // as we do not allow arrow key navigation in the first place (ie. the caret should always be at the end of text) + // Avoid handling it here to allow other components to potentially consume the shortcut. + case PlatformAction.DeleteForwardChar: + return false; + } + + return base.OnPressed(e); + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (!e.ControlPressed && !e.ShiftPressed) + { + switch (e.Key) + { + case Key.Left: + case Key.Right: + case Key.Up: + case Key.Down: + return false; + } + } + + if (!AllowCommit) + { + switch (e.Key) + { + case Key.KeypadEnter: + case Key.Enter: + return false; + } + } + + if (e.ShiftPressed) + { + switch (e.Key) + { + case Key.Delete: + return false; + } + } + + return base.OnKeyDown(e); + } + } + } +} From a436ff877f19d509ee0eb0a81a76659997aa99b1 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Fri, 22 Apr 2022 22:01:56 +0700 Subject: [PATCH 02/14] Apply review --- osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index e3dc118faa..89373ec8db 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -12,6 +12,7 @@ using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; +using osu.Game.Overlays.Mods; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -21,9 +22,9 @@ namespace osu.Game.Graphics.UserInterface public class ShearedSearchTextBox : CompositeDrawable, IHasCurrentValue { private const float icon_container_width = 50; - private const float corner_radius = 10; + private const float corner_radius = 7; private const float height = 42; - private readonly Vector2 shear = new Vector2(0.2f, 0); + private readonly Vector2 shear = new Vector2(ShearedOverlayContainer.SHEAR, 0); public FocusedTextBox TextBox; @@ -78,7 +79,7 @@ namespace osu.Game.Graphics.UserInterface RelativeSizeAxes = Axes.X, Padding = new MarginPadding { - Horizontal = corner_radius + Horizontal = corner_radius + shear.X } } } From e03d086305626e3fe30e69787911f6c6b636a7a3 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Tue, 3 May 2022 11:24:48 +0700 Subject: [PATCH 03/14] Inherit `SearchTextBox` instead --- .../UserInterface/ShearedSearchTextBox.cs | 58 +------------------ 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index 89373ec8db..04c060a5bc 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -8,14 +8,11 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input; -using osu.Framework.Input.Events; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osuTK; using osuTK.Graphics; -using osuTK.Input; namespace osu.Game.Graphics.UserInterface { @@ -113,9 +110,8 @@ namespace osu.Game.Graphics.UserInterface public override bool HandleNonPositionalInput => TextBox.HandleNonPositionalInput; - private class SearchTextBox : FocusedTextBox + private class InnerSearchTextBox : SearchTextBox { - protected virtual bool AllowCommit => false; [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) @@ -136,58 +132,6 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Both, Child = new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold) }, }; - - public override bool OnPressed(KeyBindingPressEvent e) - { - switch (e.Action) - { - case PlatformAction.MoveBackwardLine: - case PlatformAction.MoveForwardLine: - // Shift+delete is handled via PlatformAction on macOS. this is not so useful in the context of a SearchTextBox - // as we do not allow arrow key navigation in the first place (ie. the caret should always be at the end of text) - // Avoid handling it here to allow other components to potentially consume the shortcut. - case PlatformAction.DeleteForwardChar: - return false; - } - - return base.OnPressed(e); - } - - protected override bool OnKeyDown(KeyDownEvent e) - { - if (!e.ControlPressed && !e.ShiftPressed) - { - switch (e.Key) - { - case Key.Left: - case Key.Right: - case Key.Up: - case Key.Down: - return false; - } - } - - if (!AllowCommit) - { - switch (e.Key) - { - case Key.KeypadEnter: - case Key.Enter: - return false; - } - } - - if (e.ShiftPressed) - { - switch (e.Key) - { - case Key.Delete: - return false; - } - } - - return base.OnKeyDown(e); - } } } } From a35502a834189826e4435ec7faf1cc3654d12481 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Tue, 3 May 2022 11:25:14 +0700 Subject: [PATCH 04/14] Move implementation to ctor instead of bdl method --- .../UserInterface/ShearedSearchTextBox.cs | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index 04c060a5bc..4076c4f76b 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -22,17 +22,27 @@ namespace osu.Game.Graphics.UserInterface private const float corner_radius = 7; private const float height = 42; private readonly Vector2 shear = new Vector2(ShearedOverlayContainer.SHEAR, 0); - - public FocusedTextBox TextBox; + private readonly Box background; + private readonly Box searchBoxBackground; + private readonly SearchTextBox textBox; public Bindable Current { - get => TextBox.Current; - set => TextBox.Current = value; + get => textBox.Current; + set => textBox.Current = value; } - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + public bool HoldFocus + { + get => textBox.HoldFocus; + set => textBox.HoldFocus = value; + } + + public void TakeFocus() => textBox.TakeFocus(); + + public void KillFocus() => textBox.KillFocus(); + + public ShearedSearchTextBox() { Height = height; Shear = shear; @@ -43,9 +53,8 @@ namespace osu.Game.Graphics.UserInterface RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Box + background = new Box { - Colour = colourProvider.Background3, RelativeSizeAxes = Axes.Both }, new GridContainer @@ -63,12 +72,11 @@ namespace osu.Game.Graphics.UserInterface Masking = true, Children = new Drawable[] { - new Box + searchBoxBackground = new Box { - Colour = colourProvider.Background4, RelativeSizeAxes = Axes.Both }, - TextBox = new SearchTextBox + textBox = new InnerSearchTextBox { Shear = -shear, Anchor = Anchor.CentreLeft, @@ -108,11 +116,17 @@ namespace osu.Game.Graphics.UserInterface }; } - public override bool HandleNonPositionalInput => TextBox.HandleNonPositionalInput; + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + background.Colour = colourProvider.Background3; + searchBoxBackground.Colour = colourProvider.Background4; + } + + public override bool HandleNonPositionalInput => textBox.HandleNonPositionalInput; private class InnerSearchTextBox : SearchTextBox { - [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { From 4a56297c1c187083878aa7c9e8b83c9fedf33cee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 May 2022 14:28:58 +0900 Subject: [PATCH 05/14] Add localisation and improve visuals of placeholder text --- .../UserInterface/ShearedSearchTextBox.cs | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index 4076c4f76b..5dda8598bc 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -11,8 +11,8 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.Mods; +using osu.Game.Resources.Localisation.Web; using osuTK; -using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { @@ -132,14 +132,29 @@ namespace osu.Game.Graphics.UserInterface { BackgroundFocused = colourProvider.Background4; BackgroundUnfocused = colourProvider.Background4; - Placeholder.Colour = Color4.White; - PlaceholderText = @"Search"; + + Placeholder.Font = OsuFont.GetFont(size: CalculatedTextSize, weight: FontWeight.SemiBold); + PlaceholderText = CommonStrings.InputSearch; } - protected override SpriteText CreatePlaceholder() => new OsuSpriteText + protected override SpriteText CreatePlaceholder() => new SearchPlaceholder(); + + internal class SearchPlaceholder : SpriteText { - Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold) - }; + public override void Show() + { + this + .MoveToY(0, 250, Easing.OutQuint) + .FadeIn(250, Easing.OutQuint); + } + + public override void Hide() + { + this + .MoveToY(3, 250, Easing.OutQuint) + .FadeOut(250, Easing.OutQuint); + } + } protected override Drawable GetDrawableCharacter(char c) => new FallingDownContainer { From 8e0235392f9df3fed2007cbb69f94fad0990be17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 May 2022 14:30:38 +0900 Subject: [PATCH 06/14] Inline single-use constants --- .../UserInterface/ShearedSearchTextBox.cs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index 5dda8598bc..639331196d 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -18,10 +18,8 @@ namespace osu.Game.Graphics.UserInterface { public class ShearedSearchTextBox : CompositeDrawable, IHasCurrentValue { - private const float icon_container_width = 50; private const float corner_radius = 7; - private const float height = 42; - private readonly Vector2 shear = new Vector2(ShearedOverlayContainer.SHEAR, 0); + private readonly Box background; private readonly Box searchBoxBackground; private readonly SearchTextBox textBox; @@ -44,8 +42,8 @@ namespace osu.Game.Graphics.UserInterface public ShearedSearchTextBox() { - Height = height; - Shear = shear; + Height = 42; + Shear = new Vector2(ShearedOverlayContainer.SHEAR, 0); Masking = true; CornerRadius = corner_radius; InternalChild = new Container @@ -78,13 +76,13 @@ namespace osu.Game.Graphics.UserInterface }, textBox = new InnerSearchTextBox { - Shear = -shear, + Shear = -new Vector2(ShearedOverlayContainer.SHEAR, 0), Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, RelativeSizeAxes = Axes.X, Padding = new MarginPadding { - Horizontal = corner_radius + shear.X + Horizontal = corner_radius + new Vector2(ShearedOverlayContainer.SHEAR, 0).X } } } @@ -93,7 +91,7 @@ namespace osu.Game.Graphics.UserInterface { Name = @"Icon container", RelativeSizeAxes = Axes.Y, - Width = icon_container_width, + Width = 50, Origin = Anchor.CentreRight, Anchor = Anchor.CentreRight, Children = new Drawable[] @@ -104,13 +102,17 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.Centre, Anchor = Anchor.Centre, Size = new Vector2(16), - Shear = -shear + Shear = -new Vector2(ShearedOverlayContainer.SHEAR, 0) } } } } }, - ColumnDimensions = new[] { new Dimension(), new Dimension(GridSizeMode.AutoSize) } + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize) + } } } }; From bc88c4ee8e201f3734d9b60a725e77978e002cd7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 May 2022 14:34:18 +0900 Subject: [PATCH 07/14] Reduce container nesting by one level --- .../UserInterface/ShearedSearchTextBox.cs | 103 +++++++++--------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index 639331196d..8b49f1d90e 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -46,73 +46,70 @@ namespace osu.Game.Graphics.UserInterface Shear = new Vector2(ShearedOverlayContainer.SHEAR, 0); Masking = true; CornerRadius = corner_radius; - InternalChild = new Container + + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + background = new Box { - background = new Box + RelativeSizeAxes = Axes.Both + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] { - RelativeSizeAxes = Axes.Both - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] + new Drawable[] { - new Drawable[] + new Container { - new Container + Name = @"Search box container", + RelativeSizeAxes = Axes.Both, + CornerRadius = corner_radius, + Masking = true, + Children = new Drawable[] { - Name = @"Search box container", - RelativeSizeAxes = Axes.Both, - CornerRadius = corner_radius, - Masking = true, - Children = new Drawable[] + searchBoxBackground = new Box { - searchBoxBackground = new Box - { - RelativeSizeAxes = Axes.Both - }, - textBox = new InnerSearchTextBox - { - Shear = -new Vector2(ShearedOverlayContainer.SHEAR, 0), - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - Padding = new MarginPadding - { - Horizontal = corner_radius + new Vector2(ShearedOverlayContainer.SHEAR, 0).X - } - } - } - }, - new Container - { - Name = @"Icon container", - RelativeSizeAxes = Axes.Y, - Width = 50, - Origin = Anchor.CentreRight, - Anchor = Anchor.CentreRight, - Children = new Drawable[] + RelativeSizeAxes = Axes.Both + }, + textBox = new InnerSearchTextBox { - new SpriteIcon + Shear = -Shear, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding { - Icon = FontAwesome.Solid.Search, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(16), - Shear = -new Vector2(ShearedOverlayContainer.SHEAR, 0) + Horizontal = corner_radius + Shear.X } } } + }, + new Container + { + Name = @"Icon container", + RelativeSizeAxes = Axes.Y, + Width = 50, + Origin = Anchor.CentreRight, + Anchor = Anchor.CentreRight, + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.Search, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(16), + Shear = -Shear + } + } } - }, - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(GridSizeMode.AutoSize) } + }, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize) } } }; From b5ea26f2fa7b4f2c99c733f49111c16b8704a2be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 May 2022 14:45:17 +0900 Subject: [PATCH 08/14] Fix incorrect shear masking on nested textbox --- .../UserInterface/ShearedSearchTextBox.cs | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index 8b49f1d90e..d16ae2498a 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -21,7 +21,6 @@ namespace osu.Game.Graphics.UserInterface private const float corner_radius = 7; private readonly Box background; - private readonly Box searchBoxBackground; private readonly SearchTextBox textBox; public Bindable Current @@ -60,30 +59,12 @@ namespace osu.Game.Graphics.UserInterface { new Drawable[] { - new Container + textBox = new InnerSearchTextBox { - Name = @"Search box container", + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, RelativeSizeAxes = Axes.Both, - CornerRadius = corner_radius, - Masking = true, - Children = new Drawable[] - { - searchBoxBackground = new Box - { - RelativeSizeAxes = Axes.Both - }, - textBox = new InnerSearchTextBox - { - Shear = -Shear, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.X, - Padding = new MarginPadding - { - Horizontal = corner_radius + Shear.X - } - } - } + Size = Vector2.One }, new Container { @@ -119,7 +100,6 @@ namespace osu.Game.Graphics.UserInterface private void load(OverlayColourProvider colourProvider) { background.Colour = colourProvider.Background3; - searchBoxBackground.Colour = colourProvider.Background4; } public override bool HandleNonPositionalInput => textBox.HandleNonPositionalInput; @@ -134,6 +114,9 @@ namespace osu.Game.Graphics.UserInterface Placeholder.Font = OsuFont.GetFont(size: CalculatedTextSize, weight: FontWeight.SemiBold); PlaceholderText = CommonStrings.InputSearch; + + CornerRadius = corner_radius; + TextContainer.Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0); } protected override SpriteText CreatePlaceholder() => new SearchPlaceholder(); From 983eed32fc8f328837cb50428b621a0ac1b93385 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 May 2022 14:48:00 +0900 Subject: [PATCH 09/14] Reduce complexity of icon container nesting --- .../UserInterface/ShearedSearchTextBox.cs | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index d16ae2498a..0c34a04a65 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -66,31 +66,20 @@ namespace osu.Game.Graphics.UserInterface RelativeSizeAxes = Axes.Both, Size = Vector2.One }, - new Container + new SpriteIcon { - Name = @"Icon container", - RelativeSizeAxes = Axes.Y, - Width = 50, - Origin = Anchor.CentreRight, - Anchor = Anchor.CentreRight, - Children = new Drawable[] - { - new SpriteIcon - { - Icon = FontAwesome.Solid.Search, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(16), - Shear = -Shear - } - } + Icon = FontAwesome.Solid.Search, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(16), + Shear = -Shear } } }, ColumnDimensions = new[] { new Dimension(), - new Dimension(GridSizeMode.AutoSize) + new Dimension(GridSizeMode.Absolute, 50), } } }; From a555c472127a9d900ac239b91ae82f1802c8f8d7 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 3 May 2022 15:02:57 +0900 Subject: [PATCH 10/14] Reduce sorting complexity in worst-case of diffcalc --- osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index bbd2f079aa..d13d4ebf2e 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -65,6 +65,10 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// private void saveCurrentPeak() { + // Ignore sections with 0 strain to avoid edge cases of long maps with a lot of spacing between objects (e.g. /b/2351871). + if (currentSectionPeak == 0) + return; + strainPeaks.Add(currentSectionPeak); } From 637f81769609d8d56223d2d70263b57d6617444a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 3 May 2022 16:06:20 +0900 Subject: [PATCH 11/14] Ignore zero-sections on a per-case basis --- .../Difficulty/Skills/OsuStrainSkill.cs | 6 +++++- .../Difficulty/TaikoDifficultyCalculator.cs | 8 +++++++- osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs | 10 +++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index e47edc37cc..dcd2c7d321 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs @@ -38,7 +38,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills double difficulty = 0; double weight = 1; - List strains = GetCurrentStrainPeaks().OrderByDescending(d => d).ToList(); + // Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871). + // These sections will not contribute to the difficulty. + var peaks = GetCurrentStrainPeaks().Where(p => p > 0); + + List strains = peaks.OrderByDescending(d => d).ToList(); // We are reducing the highest strains first to account for extreme difficulty spikes for (int i = 0; i < Math.Min(strains.Count, ReducedSectionCount); i++) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 6afdef3f3c..a9d512f076 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -141,7 +141,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty double colourPeak = colourPeaks[i] * colour_skill_multiplier; double rhythmPeak = rhythmPeaks[i] * rhythm_skill_multiplier; double staminaPeak = (staminaRightPeaks[i] + staminaLeftPeaks[i]) * stamina_skill_multiplier * staminaPenalty; - peaks.Add(norm(2, colourPeak, rhythmPeak, staminaPeak)); + + double peak = norm(2, colourPeak, rhythmPeak, staminaPeak); + + // Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871). + // These sections will not contribute to the difficulty. + if (peak > 0) + peaks.Add(peak); } double difficulty = 0; diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index d13d4ebf2e..97266562e4 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -65,10 +65,6 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// private void saveCurrentPeak() { - // Ignore sections with 0 strain to avoid edge cases of long maps with a lot of spacing between objects (e.g. /b/2351871). - if (currentSectionPeak == 0) - return; - strainPeaks.Add(currentSectionPeak); } @@ -104,9 +100,13 @@ namespace osu.Game.Rulesets.Difficulty.Skills double difficulty = 0; double weight = 1; + // Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871). + // These sections will not contribute to the difficulty. + var peaks = GetCurrentStrainPeaks().Where(p => p > 0); + // Difficulty is the weighted sum of the highest strains from every section. // We're sorting from highest to lowest strain. - foreach (double strain in GetCurrentStrainPeaks().OrderByDescending(d => d)) + foreach (double strain in peaks.OrderByDescending(d => d)) { difficulty += strain * weight; weight *= DecayWeight; From bb086800b1e528205cfcd635c093798bc87e2a0c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 May 2022 13:41:30 +0900 Subject: [PATCH 12/14] Remove ugly playfield border --- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index bd26a99e51..ba7c6e9d33 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -59,11 +59,6 @@ namespace osu.Game.Rulesets.Osu.Edit { LayerBelowRuleset.AddRange(new Drawable[] { - new PlayfieldBorder - { - RelativeSizeAxes = Axes.Both, - PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Corners } - }, distanceSnapGridContainer = new Container { RelativeSizeAxes = Axes.Both From 0bb90c7b07169096984972b9741b6f9a9dbebb2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 May 2022 13:41:55 +0900 Subject: [PATCH 13/14] Fix gridline centering and ensure lines are always rendered using a fixed screen-space width --- .../Components/RectangularPositionSnapGrid.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs index 95b4b2fe53..4c0b4f8beb 100644 --- a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Layout; +using osu.Framework.Utils; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components @@ -72,25 +73,29 @@ namespace osu.Game.Screens.Edit.Compose.Components int index = 0; float currentPosition = startPosition; - while ((endPosition - currentPosition) * Math.Sign(step) > 0) + // Make lines the same width independent of display resolution. + float lineWidth = DrawWidth / ScreenSpaceDrawQuad.Width; + + while (Precision.AlmostBigger((endPosition - currentPosition) * Math.Sign(step), 0)) { var gridLine = new Box { Colour = Colour4.White, Alpha = index == 0 ? 0.3f : 0.1f, - EdgeSmoothness = new Vector2(0.2f) }; if (direction == Direction.Horizontal) { + gridLine.Origin = Anchor.CentreLeft; gridLine.RelativeSizeAxes = Axes.X; - gridLine.Height = 1; + gridLine.Height = lineWidth; gridLine.Y = currentPosition; } else { + gridLine.Origin = Anchor.TopCentre; gridLine.RelativeSizeAxes = Axes.Y; - gridLine.Width = 1; + gridLine.Width = lineWidth; gridLine.X = currentPosition; } From df530cb5ab2d2c598fcf8f02d20475d20abde36a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 May 2022 13:49:02 +0900 Subject: [PATCH 14/14] Add highlighting to the position snap grid edges in addition to centre lines --- .../Components/RectangularPositionSnapGrid.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs index 4c0b4f8beb..f0d26c7b6a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -76,12 +78,14 @@ namespace osu.Game.Screens.Edit.Compose.Components // Make lines the same width independent of display resolution. float lineWidth = DrawWidth / ScreenSpaceDrawQuad.Width; + List generatedLines = new List(); + while (Precision.AlmostBigger((endPosition - currentPosition) * Math.Sign(step), 0)) { var gridLine = new Box { Colour = Colour4.White, - Alpha = index == 0 ? 0.3f : 0.1f, + Alpha = 0.1f, }; if (direction == Direction.Horizontal) @@ -99,11 +103,19 @@ namespace osu.Game.Screens.Edit.Compose.Components gridLine.X = currentPosition; } - AddInternal(gridLine); + generatedLines.Add(gridLine); index += 1; currentPosition = startPosition + index * step; } + + if (generatedLines.Count == 0) + return; + + generatedLines.First().Alpha = 0.3f; + generatedLines.Last().Alpha = 0.3f; + + AddRangeInternal(generatedLines); } public Vector2 GetSnappedPosition(Vector2 original)