From 18b4317e99921e133aed5549a00e0b31445a63cf Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 1 Dec 2022 11:57:50 +0100 Subject: [PATCH 001/154] Create Basic V2 footer and test --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 29 ++++++++++++++ osu.Game/Screens/Select/FooterV2/FooterV2.cs | 39 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs create mode 100644 osu.Game/Screens/Select/FooterV2/FooterV2.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs new file mode 100644 index 0000000000..d61c86b69b --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Screens.Select.FooterV2; + +namespace osu.Game.Tests.Visual.SongSelect +{ + public partial class TestSceneSongSelectFooterV2 : OsuManualInputManagerTestScene + { + [SetUp] + public void SetUp() => Schedule(() => + { + FooterV2 footer; + + Child = footer = new FooterV2 + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + }); + + [Test] + public void TestBasic() + { + } + } +} diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs new file mode 100644 index 0000000000..10050e24fc --- /dev/null +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -0,0 +1,39 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Select.FooterV2 +{ + public partial class FooterV2 : CompositeDrawable + { + //Should be 60, setting to 50 for now for the sake of matching the current BackButton height. + private const int height = 50; + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + RelativeSizeAxes = Axes.X; + Height = height; + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colour.B5 + } + }; + } + + protected override bool OnMouseDown(MouseDownEvent e) => true; + + protected override bool OnClick(ClickEvent e) => true; + + protected override bool OnHover(HoverEvent e) => true; + } +} From 774eb178a19ca8689f5eb6f5306d229bbc385bbc Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 1 Dec 2022 13:13:37 +0100 Subject: [PATCH 002/154] Add basic button design and footer button addition flow --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 2 + .../Screens/Select/FooterV2/FooterButtonV2.cs | 65 +++++++++++++++++++ osu.Game/Screens/Select/FooterV2/FooterV2.cs | 51 +++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index d61c86b69b..5a7797b3da 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -19,6 +19,8 @@ namespace osu.Game.Tests.Visual.SongSelect Anchor = Anchor.Centre, Origin = Anchor.Centre }; + + footer.AddButton(new FooterButtonV2()); }); [Test] diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs new file mode 100644 index 0000000000..daad52eb5e --- /dev/null +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -0,0 +1,65 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; +using osu.Game.Overlays; +using osuTK; + +namespace osu.Game.Screens.Select.FooterV2 +{ + public partial class FooterButtonV2 : OsuClickableContainer, IKeyBindingHandler + { + private const int button_height = 120; + private const int button_width = 140; + private const int corner_radius = 10; + + public const float SHEAR_WIDTH = 16; + + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + + protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / button_height, 0); + + [BackgroundDependencyLoader] + private void load() + { + Shear = SHEAR; + Size = new Vector2(button_width, button_height); + Masking = true; + CornerRadius = corner_radius; + InternalChildren = new Drawable[] + { + new Box + { + Colour = colourProvider.Background3, + RelativeSizeAxes = Axes.Both + }, + + //For elements that should not be sheared. + new Container + { + Shear = -SHEAR + } + }; + } + + public Action Hovered = null!; + public Action HoverLost = null!; + public GlobalAction? Hotkey; + + public bool OnPressed(KeyBindingPressEvent e) + { + return false; + } + + public void OnReleased(KeyBindingReleaseEvent e) { } + } +} diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs index 10050e24fc..54b2f08eda 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -1,12 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osuTK; namespace osu.Game.Screens.Select.FooterV2 { @@ -14,6 +17,33 @@ namespace osu.Game.Screens.Select.FooterV2 { //Should be 60, setting to 50 for now for the sake of matching the current BackButton height. private const int height = 50; + private const int padding = 80; + + private readonly List overlays = new List(); + + public void AddButton(FooterButtonV2 button, OverlayContainer? overlay = null) + { + if (overlay != null) + { + overlays.Add(overlay); + button.Action = () => showOverlay(overlay); + } + + buttons.Add(button); + } + + private void showOverlay(OverlayContainer overlay) + { + foreach (var o in overlays) + { + if (o == overlay) + o.ToggleVisibility(); + else + o.Hide(); + } + } + + private FillFlowContainer buttons = null!; [BackgroundDependencyLoader] private void load(OsuColour colour) @@ -26,6 +56,27 @@ namespace osu.Game.Screens.Select.FooterV2 { RelativeSizeAxes = Axes.Both, Colour = colour.B5 + }, + new FillFlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Position = new Vector2(TwoLayerButton.SIZE_EXTENDED.X + padding, 40), + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(padding, 0), + Children = new Drawable[] + { + buttons = new FillFlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(-FooterButtonV2.SHEAR_WIDTH, 5), + AutoSizeAxes = Axes.Both + } + } } }; } From 1530495e7c8e86d47f0bb82d914d116c1c3fc847 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 1 Dec 2022 15:34:09 +0100 Subject: [PATCH 003/154] Add button "accent" colour, bottom bar, icon, text --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 4 +- .../Select/FooterV2/FooterButtonFreeModsV2.cs | 21 ++++++ .../Select/FooterV2/FooterButtonModsV2.cs | 20 ++++++ .../Select/FooterV2/FooterButtonOptionsV2.cs | 20 ++++++ .../Select/FooterV2/FooterButtonRandomV2.cs | 20 ++++++ .../Screens/Select/FooterV2/FooterButtonV2.cs | 72 ++++++++++++++++++- osu.Game/Screens/Select/FooterV2/FooterV2.cs | 2 +- 7 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Screens/Select/FooterV2/FooterButtonFreeModsV2.cs create mode 100644 osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs create mode 100644 osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs create mode 100644 osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index 5a7797b3da..b23739e0ca 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -20,7 +20,9 @@ namespace osu.Game.Tests.Visual.SongSelect Origin = Anchor.Centre }; - footer.AddButton(new FooterButtonV2()); + footer.AddButton(new FooterButtonModsV2()); + footer.AddButton(new FooterButtonRandomV2()); + footer.AddButton(new FooterButtonOptionsV2()); }); [Test] diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonFreeModsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonFreeModsV2.cs new file mode 100644 index 0000000000..523a2afa36 --- /dev/null +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonFreeModsV2.cs @@ -0,0 +1,21 @@ +// 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.Graphics.Sprites; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Select.FooterV2 +{ + public partial class FooterButtonFreeModsV2 : FooterButtonV2 + { + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + //No design exists for this button! + Icon = FontAwesome.Solid.ExpandArrowsAlt; + Text = "Freemods"; + AccentColour = colour.Yellow; + } + } +} diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs new file mode 100644 index 0000000000..fe6ebd5506 --- /dev/null +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs @@ -0,0 +1,20 @@ +// 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.Graphics; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Screens.Select.FooterV2 +{ + public partial class FooterButtonModsV2 : FooterButtonV2 + { + [BackgroundDependencyLoader] + private void load() + { + Text = "Mods"; + Icon = FontAwesome.Solid.ArrowsAlt; + AccentColour = Colour4.FromHex("#B2FF66"); + } + } +} diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs new file mode 100644 index 0000000000..211feb0b53 --- /dev/null +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs @@ -0,0 +1,20 @@ +// 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.Graphics; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Screens.Select.FooterV2 +{ + public partial class FooterButtonOptionsV2 : FooterButtonV2 + { + [BackgroundDependencyLoader] + private void load() + { + Text = "Options"; + Icon = FontAwesome.Solid.Cog; + AccentColour = Colour4.FromHex("#8C66FF"); + } + } +} diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs new file mode 100644 index 0000000000..ccc5caa049 --- /dev/null +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs @@ -0,0 +1,20 @@ +// 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.Graphics; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Screens.Select.FooterV2 +{ + public partial class FooterButtonRandomV2 : FooterButtonV2 + { + [BackgroundDependencyLoader] + private void load() + { + Text = "Random"; + Icon = FontAwesome.Solid.Random; + AccentColour = Colour4.FromHex("#66CCFF"); + } + } +} diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index daad52eb5e..264db1c770 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -5,10 +5,13 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osuTK; @@ -23,14 +26,47 @@ namespace osu.Game.Screens.Select.FooterV2 public const float SHEAR_WIDTH = 16; + protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / button_height, 0); + [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); - protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / button_height, 0); + private Colour4 buttonAccentColour; + + protected Colour4 AccentColour + { + set + { + buttonAccentColour = value; + bar.Colour = buttonAccentColour; + icon.Colour = buttonAccentColour; + } + } + + protected IconUsage Icon + { + set => icon.Icon = value; + } + + protected string Text + { + set => text.Text = value; + } + + private SpriteIcon icon = null!; + private OsuSpriteText text = null!; + private Box bar = null!; [BackgroundDependencyLoader] private void load() { + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Radius = 5, + Roundness = 10, + Colour = Colour4.Black.Opacity(0.25f) + }; Shear = SHEAR; Size = new Vector2(button_width, button_height); Masking = true; @@ -46,7 +82,39 @@ namespace osu.Game.Screens.Select.FooterV2 //For elements that should not be sheared. new Container { - Shear = -SHEAR + Shear = -SHEAR, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + icon = new SpriteIcon + { + //We want to offset this by the same amount as the text for aesthetic purposes + Position = new Vector2(-SHEAR_WIDTH * (52f / button_height), 12), + Size = new Vector2(20), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + text = new OsuSpriteText + { + Position = new Vector2(-SHEAR_WIDTH * (52f / button_height), 42), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + new Container + { + //Offset the bar to centre it with consideration for the shearing + Position = new Vector2(-SHEAR_WIDTH * (80f / button_height), -40), + Anchor = Anchor.BottomCentre, + Origin = Anchor.Centre, + Size = new Vector2(120, 6), + Masking = true, + CornerRadius = 3, + Child = bar = new Box + { + RelativeSizeAxes = Axes.Both, + } + } + } } }; } diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs index 54b2f08eda..719512b1ab 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select.FooterV2 Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Direction = FillDirection.Horizontal, - Spacing = new Vector2(-FooterButtonV2.SHEAR_WIDTH, 5), + Spacing = new Vector2(-FooterButtonV2.SHEAR_WIDTH + 7, 0), AutoSizeAxes = Axes.Both } } From d7cea51551e403c606c0c8017589576bb8e234dd Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 1 Dec 2022 16:29:52 +0100 Subject: [PATCH 004/154] Add functionality of Random button --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 78 +++++++++- .../Select/FooterV2/FooterButtonRandomV2.cs | 142 +++++++++++++++++- .../Screens/Select/FooterV2/FooterButtonV2.cs | 59 ++++++-- 3 files changed, 266 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index b23739e0ca..4ca193a2c6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -1,17 +1,29 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Testing; using osu.Game.Screens.Select.FooterV2; +using osuTK; +using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect { public partial class TestSceneSongSelectFooterV2 : OsuManualInputManagerTestScene { + private FooterButtonRandomV2 randomButton = null!; + + private bool nextRandomCalled; + private bool previousRandomCalled; + [SetUp] public void SetUp() => Schedule(() => { + nextRandomCalled = false; + previousRandomCalled = false; + FooterV2 footer; Child = footer = new FooterV2 @@ -21,13 +33,75 @@ namespace osu.Game.Tests.Visual.SongSelect }; footer.AddButton(new FooterButtonModsV2()); - footer.AddButton(new FooterButtonRandomV2()); + footer.AddButton(randomButton = new FooterButtonRandomV2 + { + NextRandom = () => nextRandomCalled = true, + PreviousRandom = () => previousRandomCalled = true + }); footer.AddButton(new FooterButtonOptionsV2()); + + InputManager.MoveMouseTo(Vector2.Zero); }); [Test] - public void TestBasic() + public void TestState() { + AddRepeatStep("toggle options state", () => this.ChildrenOfType().Last().Enabled.Toggle(), 20); + } + + [Test] + public void TestFooterRandom() + { + AddStep("press F2", () => InputManager.Key(Key.F2)); + AddAssert("next random invoked", () => nextRandomCalled && !previousRandomCalled); + } + + [Test] + public void TestFooterRandomViaMouse() + { + AddStep("click button", () => + { + InputManager.MoveMouseTo(randomButton); + InputManager.Click(MouseButton.Left); + }); + AddAssert("next random invoked", () => nextRandomCalled && !previousRandomCalled); + } + + [Test] + public void TestFooterRewind() + { + AddStep("press Shift+F2", () => + { + InputManager.PressKey(Key.LShift); + InputManager.PressKey(Key.F2); + InputManager.ReleaseKey(Key.F2); + InputManager.ReleaseKey(Key.LShift); + }); + AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); + } + + [Test] + public void TestFooterRewindViaShiftMouseLeft() + { + AddStep("shift + click button", () => + { + InputManager.PressKey(Key.LShift); + InputManager.MoveMouseTo(randomButton); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.LShift); + }); + AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); + } + + [Test] + public void TestFooterRewindViaMouseRight() + { + AddStep("right click button", () => + { + InputManager.MoveMouseTo(randomButton); + InputManager.Click(MouseButton.Right); + }); + AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs index ccc5caa049..7da31c6dad 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs @@ -1,20 +1,160 @@ // 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 osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Input.Bindings; +using osuTK; +using osuTK.Input; namespace osu.Game.Screens.Select.FooterV2 { public partial class FooterButtonRandomV2 : FooterButtonV2 { + public Action NextRandom { get; set; } = null!; + public Action PreviousRandom { get; set; } = null!; + + private Container persistentText = null!; + private OsuSpriteText randomSpriteText = null!; + private OsuSpriteText rewindSpriteText = null!; + private bool rewindSearch; + [BackgroundDependencyLoader] private void load() { - Text = "Random"; + //TODO: use https://fontawesome.com/icons/shuffle?s=solid&f=classic when local Fontawesome is updated Icon = FontAwesome.Solid.Random; AccentColour = Colour4.FromHex("#66CCFF"); + TextContainer.Add(persistentText = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AlwaysPresent = true, + AutoSizeAxes = Axes.Both, + Children = new[] + { + randomSpriteText = new OsuSpriteText + { + Font = OsuFont.TorusAlternate.With(size: 16), + AlwaysPresent = true, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Random", + }, + rewindSpriteText = new OsuSpriteText + { + Font = OsuFont.TorusAlternate.With(size: 16), + AlwaysPresent = true, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Rewind", + Alpha = 0f, + } + } + }); + + Action = () => + { + if (rewindSearch) + { + const double fade_time = 500; + + OsuSpriteText fallingRewind; + + TextContainer.Add(fallingRewind = new OsuSpriteText + { + Alpha = 0, + Text = rewindSpriteText.Text, + AlwaysPresent = true, // make sure the button is sized large enough to always show this + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre + }); + + fallingRewind.FadeOutFromOne(fade_time, Easing.In); + fallingRewind.MoveTo(Vector2.Zero).MoveTo(new Vector2(0, 10), fade_time, Easing.In); + fallingRewind.Expire(); + + persistentText.FadeInFromZero(fade_time, Easing.In); + + PreviousRandom.Invoke(); + } + else + { + NextRandom.Invoke(); + } + }; + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + updateText(e.ShiftPressed); + return base.OnKeyDown(e); + } + + protected override void OnKeyUp(KeyUpEvent e) + { + updateText(e.ShiftPressed); + base.OnKeyUp(e); + } + + protected override bool OnClick(ClickEvent e) + { + try + { + // this uses OR to handle rewinding when clicks are triggered by other sources (i.e. right button in OnMouseUp). + rewindSearch |= e.ShiftPressed; + return base.OnClick(e); + } + finally + { + rewindSearch = false; + } + } + + protected override void OnMouseUp(MouseUpEvent e) + { + if (e.Button == MouseButton.Right) + { + rewindSearch = true; + TriggerClick(); + return; + } + + base.OnMouseUp(e); + } + + public override bool OnPressed(KeyBindingPressEvent e) + { + rewindSearch = e.Action == GlobalAction.SelectPreviousRandom; + + if (e.Action != GlobalAction.SelectNextRandom && e.Action != GlobalAction.SelectPreviousRandom) + { + return false; + } + + if (!e.Repeat) + TriggerClick(); + return true; + } + + public override void OnReleased(KeyBindingReleaseEvent e) + { + if (e.Action == GlobalAction.SelectPreviousRandom) + { + rewindSearch = false; + } + } + + private void updateText(bool rewind = false) + { + randomSpriteText.Alpha = rewind ? 0 : 1; + rewindSpriteText.Alpha = rewind ? 1 : 0; } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 264db1c770..5125aaa552 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -10,6 +10,8 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; @@ -48,13 +50,14 @@ namespace osu.Game.Screens.Select.FooterV2 set => icon.Icon = value; } - protected string Text + protected LocalisableString Text { set => text.Text = value; } + private SpriteText text = null!; private SpriteIcon icon = null!; - private OsuSpriteText text = null!; + protected Container TextContainer = null!; private Box bar = null!; [BackgroundDependencyLoader] @@ -86,6 +89,18 @@ namespace osu.Game.Screens.Select.FooterV2 RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + TextContainer = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Position = new Vector2(-SHEAR_WIDTH * (52f / button_height), 42), + AutoSizeAxes = Axes.Both, + Child = text = new OsuSpriteText + { + Font = OsuFont.TorusAlternate.With(size: 16), + AlwaysPresent = true + } + }, icon = new SpriteIcon { //We want to offset this by the same amount as the text for aesthetic purposes @@ -94,12 +109,6 @@ namespace osu.Game.Screens.Select.FooterV2 Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre }, - text = new OsuSpriteText - { - Position = new Vector2(-SHEAR_WIDTH * (52f / button_height), 42), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - }, new Container { //Offset the bar to centre it with consideration for the shearing @@ -123,11 +132,41 @@ namespace osu.Game.Screens.Select.FooterV2 public Action HoverLost = null!; public GlobalAction? Hotkey; - public bool OnPressed(KeyBindingPressEvent e) + protected override void UpdateAfterChildren() { + } + + protected override bool OnHover(HoverEvent e) + { + Hovered?.Invoke(); + + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + HoverLost?.Invoke(); + } + + protected override bool OnClick(ClickEvent e) + { + if (!Enabled.Value) + return true; + + return base.OnClick(e); + } + + public virtual bool OnPressed(KeyBindingPressEvent e) + { + if (e.Action == Hotkey && !e.Repeat) + { + TriggerClick(); + return true; + } + return false; } - public void OnReleased(KeyBindingReleaseEvent e) { } + public virtual void OnReleased(KeyBindingReleaseEvent e) { } } } From 55a21a75a4c30e255bf1d98486a16f87526c9cd6 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 1 Dec 2022 22:07:28 +0100 Subject: [PATCH 005/154] Add hover lightening --- .../Screens/Select/FooterV2/FooterButtonV2.cs | 24 +++++++++++++++---- osu.Game/Screens/Select/FooterV2/FooterV2.cs | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 5125aaa552..81883700bd 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; @@ -59,6 +60,7 @@ namespace osu.Game.Screens.Select.FooterV2 private SpriteIcon icon = null!; protected Container TextContainer = null!; private Box bar = null!; + private Box backGroundBox = null!; [BackgroundDependencyLoader] private void load() @@ -76,7 +78,7 @@ namespace osu.Game.Screens.Select.FooterV2 CornerRadius = corner_radius; InternalChildren = new Drawable[] { - new Box + backGroundBox = new Box { Colour = colourProvider.Background3, RelativeSizeAxes = Axes.Both @@ -138,14 +140,21 @@ namespace osu.Game.Screens.Select.FooterV2 protected override bool OnHover(HoverEvent e) { - Hovered?.Invoke(); - + updateHover(true); return true; } protected override void OnHoverLost(HoverLostEvent e) { - HoverLost?.Invoke(); + updateHover(false); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (!Enabled.Value) + return true; + + return base.OnMouseDown(e); } protected override bool OnClick(ClickEvent e) @@ -168,5 +177,12 @@ namespace osu.Game.Screens.Select.FooterV2 } public virtual void OnReleased(KeyBindingReleaseEvent e) { } + + private void updateHover(bool hovered) + { + Colour4 targetColour = hovered ? colourProvider.Background3.Lighten(.3f) : colourProvider.Background3; + + backGroundBox.FadeColour(targetColour, 500, Easing.OutQuint); + } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs index 719512b1ab..82e6323507 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Screens.Select.FooterV2 { - public partial class FooterV2 : CompositeDrawable + public partial class FooterV2 : Container { //Should be 60, setting to 50 for now for the sake of matching the current BackButton height. private const int height = 50; From ea882f687433beabfe8858ac53f27c2beccdb157 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 1 Dec 2022 22:31:14 +0100 Subject: [PATCH 006/154] Add disabled button dimming. --- .../Screens/Select/FooterV2/FooterButtonV2.cs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 81883700bd..26a0335baf 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -1,7 +1,6 @@ // 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 osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -130,23 +129,27 @@ namespace osu.Game.Screens.Select.FooterV2 }; } - public Action Hovered = null!; - public Action HoverLost = null!; + protected override void LoadComplete() + { + base.LoadComplete(); + Enabled.BindValueChanged(_ => updateDisplay(), true); + } + public GlobalAction? Hotkey; - protected override void UpdateAfterChildren() - { - } + private bool isHovered; protected override bool OnHover(HoverEvent e) { - updateHover(true); + isHovered = true; + updateDisplay(); return true; } protected override void OnHoverLost(HoverLostEvent e) { - updateHover(false); + isHovered = false; + updateDisplay(); } protected override bool OnMouseDown(MouseDownEvent e) @@ -178,11 +181,16 @@ namespace osu.Game.Screens.Select.FooterV2 public virtual void OnReleased(KeyBindingReleaseEvent e) { } - private void updateHover(bool hovered) + private void updateDisplay() { - Colour4 targetColour = hovered ? colourProvider.Background3.Lighten(.3f) : colourProvider.Background3; + if (!Enabled.Value) + { + backGroundBox.FadeColour(colourProvider.Background3.Darken(.3f)); + return; + } - backGroundBox.FadeColour(targetColour, 500, Easing.OutQuint); + //Hover logic. + backGroundBox.FadeColour(isHovered && Enabled.Value ? colourProvider.Background3.Lighten(.3f) : colourProvider.Background3, 500, Easing.OutQuint); } } } From c5bad816db30d851b86aafe33f2ff940789b370b Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Fri, 2 Dec 2022 18:44:21 +0100 Subject: [PATCH 007/154] Add button colouring whilst corresponding overlay is present --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 47 +++++++++++++++++-- .../Screens/Select/FooterV2/FooterButtonV2.cs | 20 +++++++- osu.Game/Screens/Select/FooterV2/FooterV2.cs | 1 + 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index 4ca193a2c6..a1ba8daf8e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -3,8 +3,12 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Overlays; +using osu.Game.Overlays.Mods; using osu.Game.Screens.Select.FooterV2; using osuTK; using osuTK.Input; @@ -14,10 +18,13 @@ namespace osu.Game.Tests.Visual.SongSelect public partial class TestSceneSongSelectFooterV2 : OsuManualInputManagerTestScene { private FooterButtonRandomV2 randomButton = null!; + private FooterButtonModsV2 modsButton = null!; private bool nextRandomCalled; private bool previousRandomCalled; + private DummyOverlay overlay = null!; + [SetUp] public void SetUp() => Schedule(() => { @@ -26,13 +33,17 @@ namespace osu.Game.Tests.Visual.SongSelect FooterV2 footer; - Child = footer = new FooterV2 + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre + footer = new FooterV2 + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }, + overlay = new DummyOverlay() }; - footer.AddButton(new FooterButtonModsV2()); + footer.AddButton(modsButton = new FooterButtonModsV2(), overlay); footer.AddButton(randomButton = new FooterButtonRandomV2 { NextRandom = () => nextRandomCalled = true, @@ -41,6 +52,8 @@ namespace osu.Game.Tests.Visual.SongSelect footer.AddButton(new FooterButtonOptionsV2()); InputManager.MoveMouseTo(Vector2.Zero); + + overlay.Hide(); }); [Test] @@ -103,5 +116,31 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled); } + + [Test] + public void TestOverlayPresent() + { + AddStep("Press F1", () => + { + InputManager.MoveMouseTo(modsButton); + InputManager.Click(MouseButton.Left); + }); + AddAssert("Overlay visible", () => overlay.State.Value == Visibility.Visible); + AddStep("Hide", () => overlay.Hide()); + } + + private partial class DummyOverlay : ShearedOverlayContainer + { + public DummyOverlay() + : base(OverlayColourScheme.Green) + { + } + + [BackgroundDependencyLoader] + private void load() + { + Header.Title = "An overlay"; + } + } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 26a0335baf..7fb9bf42bd 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -25,9 +26,12 @@ namespace osu.Game.Screens.Select.FooterV2 private const int button_height = 120; private const int button_width = 140; private const int corner_radius = 10; + private const int transition_length = 500; public const float SHEAR_WIDTH = 16; + public Bindable OverlayState = new Bindable(); + protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / button_height, 0); [Cached] @@ -133,6 +137,7 @@ namespace osu.Game.Screens.Select.FooterV2 { base.LoadComplete(); Enabled.BindValueChanged(_ => updateDisplay(), true); + OverlayState.BindValueChanged(_ => updateDisplay()); } public GlobalAction? Hotkey; @@ -185,12 +190,23 @@ namespace osu.Game.Screens.Select.FooterV2 { if (!Enabled.Value) { - backGroundBox.FadeColour(colourProvider.Background3.Darken(.3f)); + backGroundBox.FadeColour(colourProvider.Background3.Darken(0.3f), transition_length, Easing.OutQuint); return; } + switch (OverlayState.Value) + { + case Visibility.Visible: + backGroundBox.FadeColour(buttonAccentColour.Darken(0.5f), transition_length, Easing.OutQuint); + return; + + case Visibility.Hidden: + backGroundBox.FadeColour(buttonAccentColour, transition_length, Easing.OutQuint); + break; + } + //Hover logic. - backGroundBox.FadeColour(isHovered && Enabled.Value ? colourProvider.Background3.Lighten(.3f) : colourProvider.Background3, 500, Easing.OutQuint); + backGroundBox.FadeColour(isHovered && Enabled.Value ? colourProvider.Background3.Lighten(.3f) : colourProvider.Background3, transition_length, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs index 82e6323507..8ac26c2e58 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -27,6 +27,7 @@ namespace osu.Game.Screens.Select.FooterV2 { overlays.Add(overlay); button.Action = () => showOverlay(overlay); + button.OverlayState.BindTo(overlay.State); } buttons.Add(button); From 7373d79ba6bd7e152d0918c0694a67968c74459c Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Fri, 2 Dec 2022 19:16:25 +0100 Subject: [PATCH 008/154] Use OsuColour instead of hex for button accent colour --- osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs | 6 +++--- osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs | 6 +++--- osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs index fe6ebd5506..daa1de2e7b 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs @@ -2,19 +2,19 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; namespace osu.Game.Screens.Select.FooterV2 { public partial class FooterButtonModsV2 : FooterButtonV2 { [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colour) { Text = "Mods"; Icon = FontAwesome.Solid.ArrowsAlt; - AccentColour = Colour4.FromHex("#B2FF66"); + AccentColour = colour.Lime1; } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs index 211feb0b53..be0fdef9db 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs @@ -2,19 +2,19 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; namespace osu.Game.Screens.Select.FooterV2 { public partial class FooterButtonOptionsV2 : FooterButtonV2 { [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colour) { Text = "Options"; Icon = FontAwesome.Solid.Cog; - AccentColour = Colour4.FromHex("#8C66FF"); + AccentColour = colour.Purple1; } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs index 7da31c6dad..3ecf616a16 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs @@ -26,11 +26,11 @@ namespace osu.Game.Screens.Select.FooterV2 private bool rewindSearch; [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colour) { //TODO: use https://fontawesome.com/icons/shuffle?s=solid&f=classic when local Fontawesome is updated Icon = FontAwesome.Solid.Random; - AccentColour = Colour4.FromHex("#66CCFF"); + AccentColour = colour.Blue1; TextContainer.Add(persistentText = new Container { Anchor = Anchor.Centre, From 407b0a0ad3c29948162df5eae5e230335f93de7b Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 19 Dec 2022 11:30:23 +0100 Subject: [PATCH 009/154] Address issues from Joehuu review --- .../Select/FooterV2/FooterButtonModsV2.cs | 2 +- .../Select/FooterV2/FooterButtonRandomV2.cs | 4 +-- .../Screens/Select/FooterV2/FooterButtonV2.cs | 30 +++++++++++-------- osu.Game/Screens/Select/FooterV2/FooterV2.cs | 11 ++----- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs index daa1de2e7b..b8c9f0b34b 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonModsV2.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Select.FooterV2 private void load(OsuColour colour) { Text = "Mods"; - Icon = FontAwesome.Solid.ArrowsAlt; + Icon = FontAwesome.Solid.ExchangeAlt; AccentColour = colour.Lime1; } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs index 3ecf616a16..ebb9c4b6e5 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Select.FooterV2 { randomSpriteText = new OsuSpriteText { - Font = OsuFont.TorusAlternate.With(size: 16), + Font = OsuFont.TorusAlternate.With(size: 19), AlwaysPresent = true, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select.FooterV2 }, rewindSpriteText = new OsuSpriteText { - Font = OsuFont.TorusAlternate.With(size: 16), + Font = OsuFont.TorusAlternate.With(size: 19), AlwaysPresent = true, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 7fb9bf42bd..d7d018afc3 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -23,12 +23,13 @@ namespace osu.Game.Screens.Select.FooterV2 { public partial class FooterButtonV2 : OsuClickableContainer, IKeyBindingHandler { - private const int button_height = 120; + private const int button_height = 90; private const int button_width = 140; private const int corner_radius = 10; private const int transition_length = 500; - public const float SHEAR_WIDTH = 16; + //Accounts for corner radius margin on bottom, would be 12 + public const float SHEAR_WIDTH = 13.5f; public Bindable OverlayState = new Bindable(); @@ -63,7 +64,7 @@ namespace osu.Game.Screens.Select.FooterV2 private SpriteIcon icon = null!; protected Container TextContainer = null!; private Box bar = null!; - private Box backGroundBox = null!; + private Box backgroundBox = null!; [BackgroundDependencyLoader] private void load() @@ -81,7 +82,7 @@ namespace osu.Game.Screens.Select.FooterV2 CornerRadius = corner_radius; InternalChildren = new Drawable[] { - backGroundBox = new Box + backgroundBox = new Box { Colour = colourProvider.Background3, RelativeSizeAxes = Axes.Both @@ -90,6 +91,8 @@ namespace osu.Game.Screens.Select.FooterV2 //For elements that should not be sheared. new Container { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, Shear = -SHEAR, RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -98,18 +101,18 @@ namespace osu.Game.Screens.Select.FooterV2 { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Position = new Vector2(-SHEAR_WIDTH * (52f / button_height), 42), + Y = 42, AutoSizeAxes = Axes.Both, Child = text = new OsuSpriteText { - Font = OsuFont.TorusAlternate.With(size: 16), + //figma design says the size is 16, but due to the issues with font sizes 19 matches better + Font = OsuFont.TorusAlternate.With(size: 19), AlwaysPresent = true } }, icon = new SpriteIcon { - //We want to offset this by the same amount as the text for aesthetic purposes - Position = new Vector2(-SHEAR_WIDTH * (52f / button_height), 12), + Y = 12, Size = new Vector2(20), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre @@ -117,7 +120,7 @@ namespace osu.Game.Screens.Select.FooterV2 new Container { //Offset the bar to centre it with consideration for the shearing - Position = new Vector2(-SHEAR_WIDTH * (80f / button_height), -40), + Position = new Vector2(-0.15f * 35, -10), Anchor = Anchor.BottomCentre, Origin = Anchor.Centre, Size = new Vector2(120, 6), @@ -136,6 +139,7 @@ namespace osu.Game.Screens.Select.FooterV2 protected override void LoadComplete() { base.LoadComplete(); + Enabled.BindValueChanged(_ => updateDisplay(), true); OverlayState.BindValueChanged(_ => updateDisplay()); } @@ -190,23 +194,23 @@ namespace osu.Game.Screens.Select.FooterV2 { if (!Enabled.Value) { - backGroundBox.FadeColour(colourProvider.Background3.Darken(0.3f), transition_length, Easing.OutQuint); + backgroundBox.FadeColour(colourProvider.Background3.Darken(0.3f), transition_length, Easing.OutQuint); return; } switch (OverlayState.Value) { case Visibility.Visible: - backGroundBox.FadeColour(buttonAccentColour.Darken(0.5f), transition_length, Easing.OutQuint); + backgroundBox.FadeColour(buttonAccentColour.Darken(0.5f), transition_length, Easing.OutQuint); return; case Visibility.Hidden: - backGroundBox.FadeColour(buttonAccentColour, transition_length, Easing.OutQuint); + backgroundBox.FadeColour(buttonAccentColour, transition_length, Easing.OutQuint); break; } //Hover logic. - backGroundBox.FadeColour(isHovered && Enabled.Value ? colourProvider.Background3.Lighten(.3f) : colourProvider.Background3, transition_length, Easing.OutQuint); + backgroundBox.FadeColour(isHovered && Enabled.Value ? colourProvider.Background3.Lighten(.3f) : colourProvider.Background3, transition_length, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs index 8ac26c2e58..7e2d9d6695 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -6,14 +6,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osuTK; namespace osu.Game.Screens.Select.FooterV2 { - public partial class FooterV2 : Container + public partial class FooterV2 : InputBlockingContainer { //Should be 60, setting to 50 for now for the sake of matching the current BackButton height. private const int height = 50; @@ -62,7 +61,7 @@ namespace osu.Game.Screens.Select.FooterV2 { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Position = new Vector2(TwoLayerButton.SIZE_EXTENDED.X + padding, 40), + Position = new Vector2(TwoLayerButton.SIZE_EXTENDED.X + padding, 10), RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Direction = FillDirection.Horizontal, @@ -81,11 +80,5 @@ namespace osu.Game.Screens.Select.FooterV2 } }; } - - protected override bool OnMouseDown(MouseDownEvent e) => true; - - protected override bool OnClick(ClickEvent e) => true; - - protected override bool OnHover(HoverEvent e) => true; } } From 626f4b0dfd0b22b02eaf3ab5c046a1597b62085b Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 19 Dec 2022 16:35:20 +0100 Subject: [PATCH 010/154] fix test failures, improve button logic --- .../Select/FooterV2/FooterButtonOptionsV2.cs | 2 + .../Select/FooterV2/FooterButtonRandomV2.cs | 3 +- .../Screens/Select/FooterV2/FooterButtonV2.cs | 57 +++++++------------ osu.Game/Screens/Select/FooterV2/FooterV2.cs | 2 + 4 files changed, 28 insertions(+), 36 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs index be0fdef9db..87cca0042a 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Input.Bindings; namespace osu.Game.Screens.Select.FooterV2 { @@ -15,6 +16,7 @@ namespace osu.Game.Screens.Select.FooterV2 Text = "Options"; Icon = FontAwesome.Solid.Cog; AccentColour = colour.Purple1; + Hotkey = GlobalAction.ToggleBeatmapOptions; } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs index ebb9c4b6e5..e3882588d9 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs @@ -73,7 +73,8 @@ namespace osu.Game.Screens.Select.FooterV2 Text = rewindSpriteText.Text, AlwaysPresent = true, // make sure the button is sized large enough to always show this Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre + Origin = Anchor.BottomCentre, + Font = OsuFont.TorusAlternate.With(size: 19), }); fallingRewind.FadeOutFromOne(fade_time, Easing.In); diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index d7d018afc3..ea4db1f8fa 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -60,14 +60,14 @@ namespace osu.Game.Screens.Select.FooterV2 set => text.Text = value; } - private SpriteText text = null!; - private SpriteIcon icon = null!; - protected Container TextContainer = null!; - private Box bar = null!; - private Box backgroundBox = null!; + private readonly SpriteText text; + private readonly SpriteIcon icon; - [BackgroundDependencyLoader] - private void load() + protected Container TextContainer; + private readonly Box bar; + private readonly Box backgroundBox; + + public FooterButtonV2() { EdgeEffect = new EdgeEffectParameters { @@ -146,46 +146,33 @@ namespace osu.Game.Screens.Select.FooterV2 public GlobalAction? Hotkey; - private bool isHovered; - protected override bool OnHover(HoverEvent e) { - isHovered = true; updateDisplay(); return true; } protected override void OnHoverLost(HoverLostEvent e) { - isHovered = false; updateDisplay(); } protected override bool OnMouseDown(MouseDownEvent e) { - if (!Enabled.Value) - return true; - - return base.OnMouseDown(e); + return !Enabled.Value || base.OnMouseDown(e); } protected override bool OnClick(ClickEvent e) { - if (!Enabled.Value) - return true; - - return base.OnClick(e); + return !Enabled.Value || base.OnClick(e); } public virtual bool OnPressed(KeyBindingPressEvent e) { - if (e.Action == Hotkey && !e.Repeat) - { - TriggerClick(); - return true; - } + if (e.Action != Hotkey || e.Repeat) return false; - return false; + TriggerClick(); + return true; } public virtual void OnReleased(KeyBindingReleaseEvent e) { } @@ -198,19 +185,19 @@ namespace osu.Game.Screens.Select.FooterV2 return; } - switch (OverlayState.Value) + if (OverlayState.Value == Visibility.Visible) { - case Visibility.Visible: - backgroundBox.FadeColour(buttonAccentColour.Darken(0.5f), transition_length, Easing.OutQuint); - return; - - case Visibility.Hidden: - backgroundBox.FadeColour(buttonAccentColour, transition_length, Easing.OutQuint); - break; + backgroundBox.FadeColour(buttonAccentColour.Darken(0.5f), transition_length, Easing.OutQuint); + return; } - //Hover logic. - backgroundBox.FadeColour(isHovered && Enabled.Value ? colourProvider.Background3.Lighten(.3f) : colourProvider.Background3, transition_length, Easing.OutQuint); + if (IsHovered) + { + backgroundBox.FadeColour(colourProvider.Background3.Lighten(0.3f), transition_length, Easing.OutQuint); + return; + } + + backgroundBox.FadeColour(colourProvider.Background3, transition_length, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs index 7e2d9d6695..2bfa03d319 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -20,6 +20,8 @@ namespace osu.Game.Screens.Select.FooterV2 private readonly List overlays = new List(); + /// The button to be added. + /// The to be toggled by this button. public void AddButton(FooterButtonV2 button, OverlayContainer? overlay = null) { if (overlay != null) From 680646d3a6b41a133fb6e0ab15537d2a1710dbc1 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 29 Dec 2022 12:02:08 +0100 Subject: [PATCH 011/154] Make offsetting of bottom bar more readable --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index ea4db1f8fa..342f5d1bd7 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -119,8 +119,9 @@ namespace osu.Game.Screens.Select.FooterV2 }, new Container { - //Offset the bar to centre it with consideration for the shearing - Position = new Vector2(-0.15f * 35, -10), + // The X offset has to multiplied as such to account for the fact that we only want to offset by the distance from the CenterLeft point of the container + // not the whole shear width + Position = new Vector2(-SHEAR.X * (button_height / 2 - 10), -10), Anchor = Anchor.BottomCentre, Origin = Anchor.Centre, Size = new Vector2(120, 6), From 92a755c5da93c4077ace0342b784539e21072941 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 17 Jan 2023 22:16:59 +0100 Subject: [PATCH 012/154] adjust colourbar to position itself in a more simple fashion --- .../Screens/Select/FooterV2/FooterButtonV2.cs | 47 ++++++++----------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 342f5d1bd7..33bf062abb 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -117,21 +117,22 @@ namespace osu.Game.Screens.Select.FooterV2 Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre }, - new Container - { - // The X offset has to multiplied as such to account for the fact that we only want to offset by the distance from the CenterLeft point of the container - // not the whole shear width - Position = new Vector2(-SHEAR.X * (button_height / 2 - 10), -10), - Anchor = Anchor.BottomCentre, - Origin = Anchor.Centre, - Size = new Vector2(120, 6), - Masking = true, - CornerRadius = 3, - Child = bar = new Box - { - RelativeSizeAxes = Axes.Both, - } - } + } + }, + new Container + { + // The X offset has to multiplied as such to account for the fact that we only want to offset by the distance from the CenterLeft point of the container + // not the whole shear width + Shear = -SHEAR, + Anchor = Anchor.BottomCentre, + Origin = Anchor.Centre, + Y = -10, + Size = new Vector2(120, 6), + Masking = true, + CornerRadius = 3, + Child = bar = new Box + { + RelativeSizeAxes = Axes.Both, } } }; @@ -153,20 +154,10 @@ namespace osu.Game.Screens.Select.FooterV2 return true; } - protected override void OnHoverLost(HoverLostEvent e) - { - updateDisplay(); - } + protected override void OnHoverLost(HoverLostEvent e) => updateDisplay(); - protected override bool OnMouseDown(MouseDownEvent e) - { - return !Enabled.Value || base.OnMouseDown(e); - } - - protected override bool OnClick(ClickEvent e) - { - return !Enabled.Value || base.OnClick(e); - } + protected override bool OnMouseDown(MouseDownEvent e) => !Enabled.Value || base.OnMouseDown(e); + protected override bool OnClick(ClickEvent e) => !Enabled.Value || base.OnClick(e); public virtual bool OnPressed(KeyBindingPressEvent e) { From 64c96549101a7006ea946f80d23a2aebb019a16c Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 22 Jan 2023 13:32:05 -0300 Subject: [PATCH 013/154] Make probationary groups a bit transparent --- .../Online/TestSceneUserProfileOverlay.cs | 4 +++- .../Profile/Header/Components/GroupBadge.cs | 21 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index fc8c2c0b6e..67de015708 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -90,7 +90,9 @@ namespace osu.Game.Tests.Visual.Online { new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" }, new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators", Playmodes = new[] { "mania" } }, - new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators", Playmodes = new[] { "osu", "taiko" } } + new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators", Playmodes = new[] { "osu", "taiko" } }, + new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators", Playmodes = new[] { "osu", "taiko", "fruits", "mania" } }, + new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators (Probationary)", Playmodes = new[] { "osu", "taiko", "fruits", "mania" }, IsProbationary = true } }, ProfileOrder = new[] { diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs index 4d6ee36254..afe7f278d4 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -42,12 +42,15 @@ namespace osu.Game.Overlays.Profile.Header.Components { FillFlowContainer innerContainer; - AddRangeInternal(new Drawable[] + // Normal background color is 0.75 opacity, probationary doesn't have this cause it will make them a bit transparent + var bgColor = group.IsProbationary ? colourProvider?.Background6 ?? Colour4.Black : (colourProvider?.Background6 ?? Colour4.Black).Opacity(0.75f); + + var groupDrawables = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = colourProvider?.Background6 ?? Colour4.Black + Colour = bgColor }, innerContainer = new FillFlowContainer { @@ -68,7 +71,19 @@ namespace osu.Game.Overlays.Profile.Header.Components } } } - }); + }; + + AddRangeInternal(groupDrawables); + + // Probationary groups have an opacity of 60% + if (group.IsProbationary) + { + foreach (var drawable in groupDrawables) + { + drawable.Alpha = 0.6f; + } + } + if (group.Playmodes?.Length > 0) { From 933fc8cc836c6824c34752344e879e73df8984de Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 22 Jan 2023 13:33:36 -0300 Subject: [PATCH 014/154] Fix comment --- osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs index afe7f278d4..4634ab4381 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { FillFlowContainer innerContainer; - // Normal background color is 0.75 opacity, probationary doesn't have this cause it will make them a bit transparent + // Normal background color is 0.75 opacity, probationary doesn't have this cause they are a bit transparent already var bgColor = group.IsProbationary ? colourProvider?.Background6 ?? Colour4.Black : (colourProvider?.Background6 ?? Colour4.Black).Opacity(0.75f); var groupDrawables = new Drawable[] From de5eb63ceb17829ef6f8822ae07bc9dabc40808b Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 22 Jan 2023 13:38:13 -0300 Subject: [PATCH 015/154] Fix codefactor --- osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs index 4634ab4381..435cd43634 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -84,7 +84,6 @@ namespace osu.Game.Overlays.Profile.Header.Components } } - if (group.Playmodes?.Length > 0) { innerContainer.AddRange(group.Playmodes.Select(p => From e60a089f1a725c21d2842fc52f0e1ea3c9c73ad3 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 22 Jan 2023 15:02:02 -0300 Subject: [PATCH 016/154] Set alpha on container instead of children --- osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs index 435cd43634..e21b616a17 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -78,10 +78,7 @@ namespace osu.Game.Overlays.Profile.Header.Components // Probationary groups have an opacity of 60% if (group.IsProbationary) { - foreach (var drawable in groupDrawables) - { - drawable.Alpha = 0.6f; - } + Alpha = 0.6f; } if (group.Playmodes?.Length > 0) From aeebbe4003ce85c3b8e48f6db68026daae3e0785 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 22 Jan 2023 15:12:40 -0300 Subject: [PATCH 017/154] Add group badges test from #22280 --- .../Visual/Online/TestSceneGroupBagdes.cs | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs b/osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs new file mode 100644 index 0000000000..61158c0788 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs @@ -0,0 +1,92 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Profile.Header.Components; +using osuTK; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public partial class TestSceneGroupBagdes : OsuTestScene + { + public TestSceneGroupBagdes() + { + var groups = new[] + { + new APIUser(), + new APIUser + { + Groups = new[] + { + new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" }, + } + }, + new APIUser + { + Groups = new[] + { + new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" }, + new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators", Playmodes = new[] { "osu", "taiko" } } + } + }, + new APIUser + { + Groups = new[] + { + new APIUserGroup { Colour = "#0066FF", ShortName = "PPY", Name = "peppy" }, + new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" }, + new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators", Playmodes = new[] { "osu", "taiko" } } + } + }, + new APIUser + { + Groups = new[] + { + new APIUserGroup { Colour = "#0066FF", ShortName = "PPY", Name = "peppy" }, + new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" }, + new APIUserGroup { Colour = "#999999", ShortName = "ALM", Name = "osu! Alumni" }, + new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators", Playmodes = new[] { "osu", "taiko" } }, + new APIUserGroup { Colour = "#A347EB", ShortName = "BN", Name = "Beatmap Nominators (Probationary)", Playmodes = new[] { "osu", "taiko" }, IsProbationary = true } + } + } + }; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.DarkGray + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(40), + Children = new[] + { + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(5), + ChildrenEnumerable = groups.Select(g => new GroupBadgeFlow { User = { Value = g } }) + }, + } + } + }; + } + } +} From 55976df3073110e3b1fe8672b257870e8d867744 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 22 Jan 2023 16:43:03 -0300 Subject: [PATCH 018/154] Fix typo in test class name --- osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs b/osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs index 61158c0788..cbf9c33b78 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs @@ -13,9 +13,9 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public partial class TestSceneGroupBagdes : OsuTestScene + public partial class TestSceneGroupBadges : OsuTestScene { - public TestSceneGroupBagdes() + public TestSceneGroupBadges() { var groups = new[] { From b62d4deb6f32b36eba85a7af306d3c2f4309dae1 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 22 Jan 2023 17:17:19 -0300 Subject: [PATCH 019/154] Fix also typo on filename --- .../Online/{TestSceneGroupBagdes.cs => TestSceneGroupBadges.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Tests/Visual/Online/{TestSceneGroupBagdes.cs => TestSceneGroupBadges.cs} (100%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs b/osu.Game.Tests/Visual/Online/TestSceneGroupBadges.cs similarity index 100% rename from osu.Game.Tests/Visual/Online/TestSceneGroupBagdes.cs rename to osu.Game.Tests/Visual/Online/TestSceneGroupBadges.cs From 8d4889d5ce45655673059837e130a2fca99bda70 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 22 Jan 2023 17:42:53 -0300 Subject: [PATCH 020/154] Cleanup --- .../Profile/Header/Components/GroupBadge.cs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs index e21b616a17..50eb37b74e 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -35,6 +35,11 @@ namespace osu.Game.Overlays.Profile.Header.Components CornerRadius = 8; TooltipText = group.Name; + + if (group.IsProbationary) + { + Alpha = 0.6f; + } } [BackgroundDependencyLoader] @@ -42,15 +47,15 @@ namespace osu.Game.Overlays.Profile.Header.Components { FillFlowContainer innerContainer; - // Normal background color is 0.75 opacity, probationary doesn't have this cause they are a bit transparent already - var bgColor = group.IsProbationary ? colourProvider?.Background6 ?? Colour4.Black : (colourProvider?.Background6 ?? Colour4.Black).Opacity(0.75f); + var bgColor = colourProvider?.Background6 ?? Colour4.Black; - var groupDrawables = new Drawable[] + AddRangeInternal(new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = bgColor + // Normal background color is 0.75 opacity, probationary doesn't have this cause they are a bit transparent already + Colour = group.IsProbationary ? bgColor : bgColor.Opacity(0.75f), }, innerContainer = new FillFlowContainer { @@ -71,15 +76,7 @@ namespace osu.Game.Overlays.Profile.Header.Components } } } - }; - - AddRangeInternal(groupDrawables); - - // Probationary groups have an opacity of 60% - if (group.IsProbationary) - { - Alpha = 0.6f; - } + }); if (group.Playmodes?.Length > 0) { From bc94f1b7732dd09d25b660eb150ac38a655f41f6 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 23 Jan 2023 16:43:38 +0100 Subject: [PATCH 021/154] add free mods button to test --- osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index a1ba8daf8e..534bd0ad28 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -50,6 +50,7 @@ namespace osu.Game.Tests.Visual.SongSelect PreviousRandom = () => previousRandomCalled = true }); footer.AddButton(new FooterButtonOptionsV2()); + footer.AddButton(new FooterButtonFreeModsV2()); InputManager.MoveMouseTo(Vector2.Zero); From 0eaebfd40a7a67e6ba9bd9f164b56d9140ce02bc Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Wed, 25 Jan 2023 10:22:42 -0300 Subject: [PATCH 022/154] Use Alpha instead of opacity on bg color --- osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs index 50eb37b74e..4feb25e60b 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -47,15 +47,14 @@ namespace osu.Game.Overlays.Profile.Header.Components { FillFlowContainer innerContainer; - var bgColor = colourProvider?.Background6 ?? Colour4.Black; - AddRangeInternal(new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, // Normal background color is 0.75 opacity, probationary doesn't have this cause they are a bit transparent already - Colour = group.IsProbationary ? bgColor : bgColor.Opacity(0.75f), + Colour = colourProvider?.Background6 ?? Colour4.Black, + Alpha = group.IsProbationary ? 1 : 0.75f, }, innerContainer = new FillFlowContainer { From 398813147548513d6ceb47ea74f813dfed2adea9 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 12:12:56 +0100 Subject: [PATCH 023/154] Rename OsuSliderBar.cs as NormalSliderBar.cs --- osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs | 2 +- osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs | 8 ++++---- .../UserInterface/TestSceneModDifficultyAdjustSettings.cs | 4 ++-- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 2 +- osu.Game/Graphics/UserInterface/ExpandableSlider.cs | 4 ++-- .../UserInterface/{OsuSliderBar.cs => NormalSliderBar.cs} | 4 ++-- osu.Game/Graphics/UserInterface/RangeSlider.cs | 2 +- osu.Game/Graphics/UserInterface/TimeSlider.cs | 2 +- osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs | 2 +- .../Overlays/Settings/Sections/Audio/VolumeSettings.cs | 2 +- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- .../Overlays/Settings/Sections/Input/MouseSettings.cs | 2 +- osu.Game/Overlays/Settings/Sections/SizeSlider.cs | 2 +- osu.Game/Overlays/Settings/SettingsSlider.cs | 4 ++-- osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs | 2 +- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 2 +- osu.Game/Rulesets/Mods/ModMuted.cs | 2 +- osu.Game/Rulesets/Mods/ModNoScope.cs | 2 +- osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs | 4 ++-- 19 files changed, 27 insertions(+), 27 deletions(-) rename osu.Game/Graphics/UserInterface/{OsuSliderBar.cs => NormalSliderBar.cs} (98%) diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index f5a5771386..5642fb4bdb 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Mania }; } - private partial class ManiaScrollSlider : OsuSliderBar + private partial class ManiaScrollSlider : NormalSliderBar { public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip(Current.Value, (int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / Current.Value)); } diff --git a/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs b/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs index cc72731493..791a5651b6 100644 --- a/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs +++ b/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs @@ -31,8 +31,8 @@ namespace osu.Game.Tests.Visual.Audio private WaveformTestBeatmap beatmap; - private OsuSliderBar lowPassSlider; - private OsuSliderBar highPassSlider; + private NormalSliderBar lowPassSlider; + private NormalSliderBar highPassSlider; [BackgroundDependencyLoader] private void load(AudioManager audio) @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Audio Text = $"Low Pass: {lowPassFilter.Cutoff}hz", Font = new FontUsage(size: 40) }, - lowPassSlider = new OsuSliderBar + lowPassSlider = new NormalSliderBar { Width = 500, Height = 50, @@ -69,7 +69,7 @@ namespace osu.Game.Tests.Visual.Audio Text = $"High Pass: {highPassFilter.Cutoff}hz", Font = new FontUsage(size: 40) }, - highPassSlider = new OsuSliderBar + highPassSlider = new NormalSliderBar { Width = 500, Height = 50, diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs index f45f5b9f59..5e2b5ca4ff 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs @@ -261,7 +261,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep($"Set {name} slider to {value}", () => this.ChildrenOfType().First(c => c.LabelText == name) - .ChildrenOfType>().First().Current.Value = value); + .ChildrenOfType>().First().Current.Value = value); } private void checkBindableAtValue(string name, float? expectedValue) @@ -275,7 +275,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddAssert($"Slider {name} at {expectedValue}", () => this.ChildrenOfType().First(c => c.LabelText == name) - .ChildrenOfType>().First().Current.Value == expectedValue); + .ChildrenOfType>().First().Current.Value == expectedValue); } private void setBeatmapWithDifficultyParameters(float value) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index eff320a575..1cbb798981 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -270,7 +270,7 @@ namespace osu.Game.Tests.Visual.UserInterface createScreen(); AddStep("select difficulty adjust via panel", () => getPanelForMod(typeof(OsuModDifficultyAdjust)).TriggerClick()); - AddStep("set setting", () => modSelectOverlay.ChildrenOfType>().First().Current.Value = 8); + AddStep("set setting", () => modSelectOverlay.ChildrenOfType>().First().Current.Value = 8); AddAssert("ensure setting is propagated", () => SelectedMods.Value.OfType().Single().CircleSize.Value == 8); diff --git a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs index 9669fe89a5..e960f55501 100644 --- a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs +++ b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs @@ -21,7 +21,7 @@ namespace osu.Game.Graphics.UserInterface /// public partial class ExpandableSlider : CompositeDrawable, IExpandable, IHasCurrentValue where T : struct, IEquatable, IComparable, IConvertible - where TSlider : OsuSliderBar, new() + where TSlider : NormalSliderBar, new() { private readonly OsuSpriteText label; private readonly TSlider slider; @@ -130,7 +130,7 @@ namespace osu.Game.Graphics.UserInterface /// /// An implementation for the UI slider bar control. /// - public partial class ExpandableSlider : ExpandableSlider> + public partial class ExpandableSlider : ExpandableSlider> where T : struct, IEquatable, IComparable, IConvertible { } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs similarity index 98% rename from osu.Game/Graphics/UserInterface/OsuSliderBar.cs rename to osu.Game/Graphics/UserInterface/NormalSliderBar.cs index 6d6a591673..71422f097f 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs @@ -25,7 +25,7 @@ using osu.Game.Utils; namespace osu.Game.Graphics.UserInterface { - public partial class OsuSliderBar : SliderBar, IHasTooltip, IHasAccentColour + public partial class NormalSliderBar : SliderBar, IHasTooltip, IHasAccentColour where T : struct, IEquatable, IComparable, IConvertible { /// @@ -77,7 +77,7 @@ namespace osu.Game.Graphics.UserInterface } } - public OsuSliderBar() + public NormalSliderBar() { Height = Nub.HEIGHT; RangePadding = Nub.EXPANDED_SIZE / 2; diff --git a/osu.Game/Graphics/UserInterface/RangeSlider.cs b/osu.Game/Graphics/UserInterface/RangeSlider.cs index 4e23b06c2b..2f3dc07a91 100644 --- a/osu.Game/Graphics/UserInterface/RangeSlider.cs +++ b/osu.Game/Graphics/UserInterface/RangeSlider.cs @@ -158,7 +158,7 @@ namespace osu.Game.Graphics.UserInterface && screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X; } - protected partial class BoundSlider : OsuSliderBar + protected partial class BoundSlider : NormalSliderBar { public string? DefaultString; public LocalisableString? DefaultTooltip; diff --git a/osu.Game/Graphics/UserInterface/TimeSlider.cs b/osu.Game/Graphics/UserInterface/TimeSlider.cs index 46f0821033..15fc0a465b 100644 --- a/osu.Game/Graphics/UserInterface/TimeSlider.cs +++ b/osu.Game/Graphics/UserInterface/TimeSlider.cs @@ -10,7 +10,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A slider bar which displays a millisecond time value. /// - public partial class TimeSlider : OsuSliderBar + public partial class TimeSlider : NormalSliderBar { public override LocalisableString TooltipText => $"{Current.Value:N0} ms"; } diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs b/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs index 1bcb1bcdf4..75aedc298e 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.FirstRunSetup public override bool? AllowTrackAdjustments => false; } - private partial class UIScaleSlider : OsuSliderBar + private partial class UIScaleSlider : NormalSliderBar { public override LocalisableString TooltipText => base.TooltipText + "x"; } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index a83707b5f6..0c62cb169f 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override Drawable CreateControl() { - var sliderBar = (OsuSliderBar)base.CreateControl(); + var sliderBar = (NormalSliderBar)base.CreateControl(); sliderBar.PlaySamplesOnAdjust = false; return sliderBar; } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index f140c14a0b..805cf4ca0b 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -329,7 +329,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } - private partial class UIScaleSlider : OsuSliderBar + private partial class UIScaleSlider : NormalSliderBar { public override LocalisableString TooltipText => base.TooltipText + "x"; } diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index 5a6338dc09..f403012793 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - public partial class SensitivitySlider : OsuSliderBar + public partial class SensitivitySlider : NormalSliderBar { public override LocalisableString TooltipText => Current.Disabled ? MouseSettingsStrings.EnableHighPrecisionForSensitivityAdjust : $"{base.TooltipText}x"; } diff --git a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs index 26d6147bb7..b596212007 100644 --- a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs +++ b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections /// /// A slider intended to show a "size" multiplier number, where 1x is 1.0. /// - public partial class SizeSlider : OsuSliderBar + public partial class SizeSlider : NormalSliderBar where T : struct, IEquatable, IComparable, IConvertible, IFormattable { public override LocalisableString TooltipText => Current.Value.ToString(@"0.##x", NumberFormatInfo.CurrentInfo); diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index babac8ec69..a7305b4e03 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -10,14 +10,14 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public partial class SettingsSlider : SettingsSlider> + public partial class SettingsSlider : SettingsSlider> where T : struct, IEquatable, IComparable, IConvertible { } public partial class SettingsSlider : SettingsItem where TValue : struct, IEquatable, IComparable, IConvertible - where TSlider : OsuSliderBar, new() + where TSlider : NormalSliderBar, new() { protected override Drawable CreateControl() => new TSlider { diff --git a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs index 38ced4c9e7..58810fc127 100644 --- a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs +++ b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Mods { InternalChildren = new Drawable[] { - new OsuSliderBar + new NormalSliderBar { RelativeSizeAxes = Axes.X, Current = currentNumber, diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 59fbfe49b6..a7b00ac88b 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Mods } } - public partial class PercentSlider : OsuSliderBar + public partial class PercentSlider : NormalSliderBar { public PercentSlider() { diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 59c4cfa85b..d2d8284083 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Mods public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } - public partial class MuteComboSlider : OsuSliderBar + public partial class MuteComboSlider : NormalSliderBar { public override LocalisableString TooltipText => Current.Value == 0 ? "always muted" : base.TooltipText; } diff --git a/osu.Game/Rulesets/Mods/ModNoScope.cs b/osu.Game/Rulesets/Mods/ModNoScope.cs index cfac44066e..3736eca780 100644 --- a/osu.Game/Rulesets/Mods/ModNoScope.cs +++ b/osu.Game/Rulesets/Mods/ModNoScope.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Mods } } - public partial class HiddenComboSlider : OsuSliderBar + public partial class HiddenComboSlider : NormalSliderBar { public override LocalisableString TooltipText => Current.Value == 0 ? "always hidden" : base.TooltipText; } diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index 45d4995753..985a414bc0 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -15,11 +15,11 @@ namespace osu.Game.Screens.Play.PlayerSettings public partial class PlayerSliderBar : SettingsSlider where T : struct, IEquatable, IComparable, IConvertible { - public OsuSliderBar Bar => (OsuSliderBar)Control; + public NormalSliderBar Bar => (NormalSliderBar)Control; protected override Drawable CreateControl() => new SliderBar(); - protected partial class SliderBar : OsuSliderBar + protected partial class SliderBar : NormalSliderBar { public SliderBar() { From ac3ad9cf8d21cf7daa4b0806c114b3087255747e Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 12:16:51 +0100 Subject: [PATCH 024/154] Implement OsuSliderBar.cs as base ( non framework side ) class from which NormalSliderBar.cs inherits --- osu.Game/Graphics/UserInterface/NormalSliderBar.cs | 3 +-- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/OsuSliderBar.cs diff --git a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs index 71422f097f..0d06995ccf 100644 --- a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs @@ -14,7 +14,6 @@ using osu.Framework.Audio.Sample; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; @@ -25,7 +24,7 @@ using osu.Game.Utils; namespace osu.Game.Graphics.UserInterface { - public partial class NormalSliderBar : SliderBar, IHasTooltip, IHasAccentColour + public partial class NormalSliderBar : OsuSliderBar, IHasTooltip, IHasAccentColour where T : struct, IEquatable, IComparable, IConvertible { /// diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs new file mode 100644 index 0000000000..d82850d181 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -0,0 +1,13 @@ +// 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 osu.Framework.Graphics.UserInterface; + +namespace osu.Game.Graphics.UserInterface +{ + public abstract partial class OsuSliderBar : SliderBar + where T : struct, IEquatable, IComparable, IConvertible + { + } +} From 9afc8681ef12f9ddcb8f021f1629e97a8ff10804 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 12:25:05 +0100 Subject: [PATCH 025/154] Extract tooltip implementation into base OsuSliderBar.cs from NormalSliderBar.cs --- .../Graphics/UserInterface/NormalSliderBar.cs | 37 +----------- .../Graphics/UserInterface/OsuSliderBar.cs | 56 ++++++++++++++++++- 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs index 0d06995ccf..1a894046d9 100644 --- a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs @@ -14,24 +14,16 @@ using osu.Framework.Audio.Sample; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Overlays; -using osu.Game.Utils; namespace osu.Game.Graphics.UserInterface { - public partial class NormalSliderBar : OsuSliderBar, IHasTooltip, IHasAccentColour + public partial class NormalSliderBar : OsuSliderBar, IHasAccentColour where T : struct, IEquatable, IComparable, IConvertible { - /// - /// Maximum number of decimal digits to be displayed in the tooltip. - /// - private const int max_decimal_digits = 5; - private Sample sample; private double lastSampleTime; private T lastSampleValue; @@ -41,17 +33,10 @@ namespace osu.Game.Graphics.UserInterface protected readonly Box RightBox; private readonly Container nubContainer; - public virtual LocalisableString TooltipText { get; private set; } - public bool PlaySamplesOnAdjust { get; set; } = true; private readonly HoverClickSounds hoverClickSounds; - /// - /// Whether to format the tooltip as a percentage or the actual value. - /// - public bool DisplayAsPercentage { get; set; } - private Color4 accentColour; public Color4 AccentColour @@ -150,7 +135,6 @@ namespace osu.Game.Graphics.UserInterface protected override void LoadComplete() { base.LoadComplete(); - CurrentNumber.BindValueChanged(current => TooltipText = getTooltipText(current.NewValue), true); Current.BindDisabledChanged(disabled => { @@ -189,7 +173,6 @@ namespace osu.Game.Graphics.UserInterface { base.OnUserChange(value); playSample(value); - TooltipText = getTooltipText(value); } private void playSample(T value) @@ -217,24 +200,6 @@ namespace osu.Game.Graphics.UserInterface channel.Play(); } - private LocalisableString getTooltipText(T value) - { - if (CurrentNumber.IsInteger) - return value.ToInt32(NumberFormatInfo.InvariantInfo).ToString("N0"); - - double floatValue = value.ToDouble(NumberFormatInfo.InvariantInfo); - - if (DisplayAsPercentage) - return floatValue.ToString("0%"); - - decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); - - // Find the number of significant digits (we could have less than 5 after normalize()) - int significantDigits = FormatUtils.FindPrecision(decimalPrecision); - - return floatValue.ToString($"N{significantDigits}"); - } - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index d82850d181..6a8f81a4b6 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -2,12 +2,66 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Globalization; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; +using osu.Game.Utils; namespace osu.Game.Graphics.UserInterface { - public abstract partial class OsuSliderBar : SliderBar + public abstract partial class OsuSliderBar : SliderBar, IHasTooltip where T : struct, IEquatable, IComparable, IConvertible { + public virtual LocalisableString TooltipText { get; private set; } + + /// + /// Maximum number of decimal digits to be displayed in the tooltip. + /// + private const int max_decimal_digits = 5; + + /// + /// Whether to format the tooltip as a percentage or the actual value. + /// + public bool DisplayAsPercentage { get; set; } + + protected override void LoadComplete() + { + base.LoadComplete(); + CurrentNumber.BindValueChanged(current => TooltipText = getTooltipText(current.NewValue), true); + } + + protected override void OnUserChange(T value) + { + base.OnUserChange(value); + TooltipText = getTooltipText(value); + } + + private LocalisableString getTooltipText(T value) + { + if (CurrentNumber.IsInteger) + return value.ToInt32(NumberFormatInfo.InvariantInfo).ToString("N0"); + + double floatValue = value.ToDouble(NumberFormatInfo.InvariantInfo); + + if (DisplayAsPercentage) + return floatValue.ToString("0%"); + + decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); + + // Find the number of significant digits (we could have less than 5 after normalize()) + int significantDigits = FormatUtils.FindPrecision(decimalPrecision); + + return floatValue.ToString($"N{significantDigits}"); + } + + /// + /// Removes all non-significant digits, keeping at most a requested number of decimal digits. + /// + /// The decimal to normalize. + /// The maximum number of decimal digits to keep. The final result may have fewer decimal digits than this value. + /// The normalised decimal. + private decimal normalise(decimal d, int sd) + => decimal.Parse(Math.Round(d, sd).ToString(string.Concat("0.", new string('#', sd)), CultureInfo.InvariantCulture), CultureInfo.InvariantCulture); } } From fc99165df7f5e3a046d1cd754f2b10da78022bcc Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 12:36:05 +0100 Subject: [PATCH 026/154] Extract samples into base OsuSliderBar.cs from NormalSliderBar.cs --- .../Graphics/UserInterface/NormalSliderBar.cs | 55 +------------------ .../Graphics/UserInterface/OsuSliderBar.cs | 45 +++++++++++++++ 2 files changed, 47 insertions(+), 53 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs index 1a894046d9..902609d7a6 100644 --- a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs @@ -4,37 +4,27 @@ #nullable disable using System; -using System.Globalization; using JetBrains.Annotations; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.Utils; using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterface { - public partial class NormalSliderBar : OsuSliderBar, IHasAccentColour + public partial class NormalSliderBar : OsuSliderBar where T : struct, IEquatable, IComparable, IConvertible { - private Sample sample; - private double lastSampleTime; - private T lastSampleValue; - protected readonly Nub Nub; protected readonly Box LeftBox; protected readonly Box RightBox; private readonly Container nubContainer; - public bool PlaySamplesOnAdjust { get; set; } = true; - private readonly HoverClickSounds hoverClickSounds; private Color4 accentColour; @@ -118,9 +108,8 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader(true)] - private void load(AudioManager audio, [CanBeNull] OverlayColourProvider colourProvider, OsuColour colours) + private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour colours) { - sample = audio.Samples.Get(@"UI/notch-tick"); AccentColour = colourProvider?.Highlight1 ?? colours.Pink; BackgroundColour = colourProvider?.Background5 ?? colours.PinkDarker.Darken(1); } @@ -169,37 +158,6 @@ namespace osu.Game.Graphics.UserInterface Nub.Glowing = !Current.Disabled && (IsHovered || IsDragged); } - protected override void OnUserChange(T value) - { - base.OnUserChange(value); - playSample(value); - } - - private void playSample(T value) - { - if (!PlaySamplesOnAdjust) - return; - - if (Clock == null || Clock.CurrentTime - lastSampleTime <= 30) - return; - - if (value.Equals(lastSampleValue)) - return; - - lastSampleValue = value; - lastSampleTime = Clock.CurrentTime; - - var channel = sample.GetChannel(); - - channel.Frequency.Value = 0.99f + RNG.NextDouble(0.02f) + NormalizedValue * 0.2f; - - // intentionally pitched down, even when hitting max. - if (NormalizedValue == 0 || NormalizedValue == 1) - channel.Frequency.Value -= 0.5f; - - channel.Play(); - } - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -211,14 +169,5 @@ namespace osu.Game.Graphics.UserInterface { Nub.MoveToX(value, 250, Easing.OutQuint); } - - /// - /// Removes all non-significant digits, keeping at most a requested number of decimal digits. - /// - /// The decimal to normalize. - /// The maximum number of decimal digits to keep. The final result may have fewer decimal digits than this value. - /// The normalised decimal. - private decimal normalise(decimal d, int sd) - => decimal.Parse(Math.Round(d, sd).ToString(string.Concat("0.", new string('#', sd)), CultureInfo.InvariantCulture), CultureInfo.InvariantCulture); } } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 6a8f81a4b6..ee1f75c419 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -3,9 +3,13 @@ using System; using System.Globalization; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; +using osu.Framework.Utils; using osu.Game.Utils; namespace osu.Game.Graphics.UserInterface @@ -13,6 +17,19 @@ namespace osu.Game.Graphics.UserInterface public abstract partial class OsuSliderBar : SliderBar, IHasTooltip where T : struct, IEquatable, IComparable, IConvertible { + private Sample sample = null!; + + private double lastSampleTime; + private T lastSampleValue; + + public bool PlaySamplesOnAdjust { get; set; } = true; + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sample = audio.Samples.Get(@"UI/notch-tick"); + } + public virtual LocalisableString TooltipText { get; private set; } /// @@ -34,9 +51,37 @@ namespace osu.Game.Graphics.UserInterface protected override void OnUserChange(T value) { base.OnUserChange(value); + + playSample(value); + TooltipText = getTooltipText(value); } + private void playSample(T value) + { + if (!PlaySamplesOnAdjust) + return; + + if (Clock == null || Clock.CurrentTime - lastSampleTime <= 30) + return; + + if (value.Equals(lastSampleValue)) + return; + + lastSampleValue = value; + lastSampleTime = Clock.CurrentTime; + + var channel = sample.GetChannel(); + + channel.Frequency.Value = 0.99f + RNG.NextDouble(0.02f) + NormalizedValue * 0.2f; + + // intentionally pitched down, even when hitting max. + if (NormalizedValue == 0 || NormalizedValue == 1) + channel.Frequency.Value -= 0.5f; + + channel.Play(); + } + private LocalisableString getTooltipText(T value) { if (CurrentNumber.IsInteger) From 7355397e83e9bf2df030445622ae95ac36369368 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 12:58:58 +0100 Subject: [PATCH 027/154] Enable NRT on NormalSliderBar.cs --- osu.Game/Graphics/UserInterface/NormalSliderBar.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs index 902609d7a6..92febaa6e6 100644 --- a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs @@ -1,10 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; -using JetBrains.Annotations; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -108,7 +105,7 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader(true)] - private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour colours) + private void load(OverlayColourProvider? colourProvider, OsuColour colours) { AccentColour = colourProvider?.Highlight1 ?? colours.Pink; BackgroundColour = colourProvider?.Background5 ?? colours.PinkDarker.Darken(1); From 374c3b56f6f2e8b74fd87c538baa5354bf59d708 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 13:21:20 +0100 Subject: [PATCH 028/154] Rename Nub.cs to NormalNub.cs --- .../UserInterface/TestSceneRangeSlider.cs | 2 +- .../UserInterface/{Nub.cs => NormalNub.cs} | 4 +-- .../Graphics/UserInterface/NormalSliderBar.cs | 18 ++++++------ .../Graphics/UserInterface/OsuCheckbox.cs | 28 +++++++++---------- .../Graphics/UserInterface/RangeSlider.cs | 18 ++++++------ .../OsuDirectorySelectorHiddenToggle.cs | 6 ++-- osu.Game/Overlays/Mods/ModColumn.cs | 6 ++-- .../Play/PlayerSettings/PlayerCheckbox.cs | 6 ++-- .../Play/PlayerSettings/PlayerSliderBar.cs | 6 ++-- 9 files changed, 47 insertions(+), 47 deletions(-) rename osu.Game/Graphics/UserInterface/{Nub.cs => NormalNub.cs} (97%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs index b780764e7f..0100b2a1a0 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.UserInterface LowerBound = customStart, UpperBound = customEnd, TooltipSuffix = "suffix", - NubWidth = Nub.HEIGHT * 2, + NubWidth = NormalNub.HEIGHT * 2, DefaultStringLowerBound = "Start", DefaultStringUpperBound = "End", MinRange = 10 diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/NormalNub.cs similarity index 97% rename from osu.Game/Graphics/UserInterface/Nub.cs rename to osu.Game/Graphics/UserInterface/NormalNub.cs index 7921dcf593..549b3ffa04 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/NormalNub.cs @@ -19,7 +19,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterface { - public partial class Nub : Container, IHasCurrentValue, IHasAccentColour + public partial class NormalNub : Container, IHasCurrentValue, IHasAccentColour { public const float HEIGHT = 15; @@ -30,7 +30,7 @@ namespace osu.Game.Graphics.UserInterface private readonly Box fill; private readonly Container main; - public Nub() + public NormalNub() { Size = new Vector2(EXPANDED_SIZE, HEIGHT); diff --git a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs index 92febaa6e6..bc27c9af4c 100644 --- a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs @@ -17,7 +17,7 @@ namespace osu.Game.Graphics.UserInterface public partial class NormalSliderBar : OsuSliderBar where T : struct, IEquatable, IComparable, IConvertible { - protected readonly Nub Nub; + protected readonly NormalNub NormalNub; protected readonly Box LeftBox; protected readonly Box RightBox; private readonly Container nubContainer; @@ -50,8 +50,8 @@ namespace osu.Game.Graphics.UserInterface public NormalSliderBar() { - Height = Nub.HEIGHT; - RangePadding = Nub.EXPANDED_SIZE / 2; + Height = NormalNub.HEIGHT; + RangePadding = NormalNub.EXPANDED_SIZE / 2; Children = new Drawable[] { new Container @@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface nubContainer = new Container { RelativeSizeAxes = Axes.Both, - Child = Nub = new Nub + Child = NormalNub = new NormalNub { Origin = Anchor.TopCentre, RelativePositionAxes = Axes.X, @@ -142,7 +142,7 @@ namespace osu.Game.Graphics.UserInterface } protected override bool ShouldHandleAsRelativeDrag(MouseDownEvent e) - => Nub.ReceivePositionalInputAt(e.ScreenSpaceMouseDownPosition); + => NormalNub.ReceivePositionalInputAt(e.ScreenSpaceMouseDownPosition); protected override void OnDragEnd(DragEndEvent e) { @@ -152,19 +152,19 @@ namespace osu.Game.Graphics.UserInterface private void updateGlow() { - Nub.Glowing = !Current.Disabled && (IsHovered || IsDragged); + NormalNub.Glowing = !Current.Disabled && (IsHovered || IsDragged); } protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - LeftBox.Scale = new Vector2(Math.Clamp(RangePadding + Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, Math.Max(0, DrawWidth)), 1); - RightBox.Scale = new Vector2(Math.Clamp(DrawWidth - Nub.DrawPosition.X - RangePadding - Nub.DrawWidth / 2, 0, Math.Max(0, DrawWidth)), 1); + LeftBox.Scale = new Vector2(Math.Clamp(RangePadding + NormalNub.DrawPosition.X - NormalNub.DrawWidth / 2, 0, Math.Max(0, DrawWidth)), 1); + RightBox.Scale = new Vector2(Math.Clamp(DrawWidth - NormalNub.DrawPosition.X - RangePadding - NormalNub.DrawWidth / 2, 0, Math.Max(0, DrawWidth)), 1); } protected override void UpdateValue(float value) { - Nub.MoveToX(value, 250, Easing.OutQuint); + NormalNub.MoveToX(value, 250, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 160105af1a..982706f87b 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface } } - protected readonly Nub Nub; + protected readonly NormalNub NormalNub; protected readonly OsuTextFlowContainer LabelTextFlowContainer; private Sample sampleChecked; @@ -61,28 +61,28 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, }, - Nub = new Nub(), + NormalNub = new NormalNub(), new HoverSounds() }; if (nubOnRight) { - Nub.Anchor = Anchor.CentreRight; - Nub.Origin = Anchor.CentreRight; - Nub.Margin = new MarginPadding { Right = nub_padding }; - LabelTextFlowContainer.Padding = new MarginPadding { Right = Nub.EXPANDED_SIZE + nub_padding * 2 }; + NormalNub.Anchor = Anchor.CentreRight; + NormalNub.Origin = Anchor.CentreRight; + NormalNub.Margin = new MarginPadding { Right = nub_padding }; + LabelTextFlowContainer.Padding = new MarginPadding { Right = NormalNub.EXPANDED_SIZE + nub_padding * 2 }; } else { - Nub.Anchor = Anchor.CentreLeft; - Nub.Origin = Anchor.CentreLeft; - Nub.Margin = new MarginPadding { Left = nub_padding }; - LabelTextFlowContainer.Padding = new MarginPadding { Left = Nub.EXPANDED_SIZE + nub_padding * 2 }; + NormalNub.Anchor = Anchor.CentreLeft; + NormalNub.Origin = Anchor.CentreLeft; + NormalNub.Margin = new MarginPadding { Left = nub_padding }; + LabelTextFlowContainer.Padding = new MarginPadding { Left = NormalNub.EXPANDED_SIZE + nub_padding * 2 }; } - Nub.Current.BindTo(Current); + NormalNub.Current.BindTo(Current); - Current.DisabledChanged += disabled => LabelTextFlowContainer.Alpha = Nub.Alpha = disabled ? 0.3f : 1; + Current.DisabledChanged += disabled => LabelTextFlowContainer.Alpha = NormalNub.Alpha = disabled ? 0.3f : 1; } /// @@ -101,13 +101,13 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { - Nub.Glowing = true; + NormalNub.Glowing = true; return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - Nub.Glowing = false; + NormalNub.Glowing = false; base.OnHoverLost(e); } diff --git a/osu.Game/Graphics/UserInterface/RangeSlider.cs b/osu.Game/Graphics/UserInterface/RangeSlider.cs index 2f3dc07a91..963c859198 100644 --- a/osu.Game/Graphics/UserInterface/RangeSlider.cs +++ b/osu.Game/Graphics/UserInterface/RangeSlider.cs @@ -141,7 +141,7 @@ namespace osu.Game.Graphics.UserInterface public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) - && screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X; + && screenSpacePos.X <= NormalNub.ScreenSpaceDrawQuad.TopRight.X; } private partial class UpperBoundSlider : BoundSlider @@ -155,7 +155,7 @@ namespace osu.Game.Graphics.UserInterface public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) - && screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X; + && screenSpacePos.X >= NormalNub.ScreenSpaceDrawQuad.TopLeft.X; } protected partial class BoundSlider : NormalSliderBar @@ -163,7 +163,7 @@ namespace osu.Game.Graphics.UserInterface public string? DefaultString; public LocalisableString? DefaultTooltip; public string? TooltipSuffix; - public float NubWidth { get; set; } = Nub.HEIGHT; + public float NubWidth { get; set; } = NormalNub.HEIGHT; public override LocalisableString TooltipText => (Current.IsDefault ? DefaultTooltip : Current.Value.ToString($@"0.## {TooltipSuffix}")) ?? Current.Value.ToString($@"0.## {TooltipSuffix}"); @@ -177,12 +177,12 @@ namespace osu.Game.Graphics.UserInterface protected override void LoadComplete() { base.LoadComplete(); - Nub.Width = NubWidth; - RangePadding = Nub.Width / 2; + NormalNub.Width = NubWidth; + RangePadding = NormalNub.Width / 2; OsuSpriteText currentDisplay; - Nub.Add(currentDisplay = new OsuSpriteText + NormalNub.Add(currentDisplay = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -203,9 +203,9 @@ namespace osu.Game.Graphics.UserInterface if (colourProvider == null) return; AccentColour = colourProvider.Background2; - Nub.AccentColour = colourProvider.Background2; - Nub.GlowingAccentColour = colourProvider.Background1; - Nub.GlowColour = colourProvider.Background2; + NormalNub.AccentColour = colourProvider.Background2; + NormalNub.GlowingAccentColour = colourProvider.Background1; + NormalNub.GlowColour = colourProvider.Background2; } } } diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs index 7665ed507f..79f72495c8 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs @@ -30,9 +30,9 @@ namespace osu.Game.Graphics.UserInterfaceV2 if (overlayColourProvider != null) return; - Nub.AccentColour = colours.GreySeaFoamLighter; - Nub.GlowingAccentColour = Color4.White; - Nub.GlowColour = Color4.White; + NormalNub.AccentColour = colours.GreySeaFoamLighter; + NormalNub.GlowingAccentColour = Color4.White; + NormalNub.GlowColour = Color4.White; } } } diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 5d9f616e5f..97a766259a 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -267,9 +267,9 @@ namespace osu.Game.Overlays.Mods private void updateState() { - Nub.AccentColour = AccentColour; - Nub.GlowingAccentColour = AccentHoverColour; - Nub.GlowColour = AccentHoverColour.Opacity(0.2f); + NormalNub.AccentColour = AccentColour; + NormalNub.GlowingAccentColour = AccentHoverColour; + NormalNub.GlowColour = AccentHoverColour.Opacity(0.2f); } protected override void OnUserChange(bool value) diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs index 49c9cbf385..960904282d 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs @@ -18,9 +18,9 @@ namespace osu.Game.Screens.Play.PlayerSettings [BackgroundDependencyLoader] private void load(OsuColour colours) { - Nub.AccentColour = colours.Yellow; - Nub.GlowingAccentColour = colours.YellowLighter; - Nub.GlowColour = colours.YellowDark; + NormalNub.AccentColour = colours.Yellow; + NormalNub.GlowingAccentColour = colours.YellowLighter; + NormalNub.GlowColour = colours.YellowDark; } } } diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index 985a414bc0..b54207886e 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -30,9 +30,9 @@ namespace osu.Game.Screens.Play.PlayerSettings private void load(OsuColour colours) { AccentColour = colours.Yellow; - Nub.AccentColour = colours.Yellow; - Nub.GlowingAccentColour = colours.YellowLighter; - Nub.GlowColour = colours.YellowDark; + NormalNub.AccentColour = colours.Yellow; + NormalNub.GlowingAccentColour = colours.YellowLighter; + NormalNub.GlowColour = colours.YellowDark; } } } From 63efe79abcdd7465f0b7f137efbcfe66424b0d2c Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 13:22:49 +0100 Subject: [PATCH 029/154] Enable NRT for NormalNub.cs --- osu.Game/Graphics/UserInterface/NormalNub.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/NormalNub.cs b/osu.Game/Graphics/UserInterface/NormalNub.cs index 549b3ffa04..1affbabd9d 100644 --- a/osu.Game/Graphics/UserInterface/NormalNub.cs +++ b/osu.Game/Graphics/UserInterface/NormalNub.cs @@ -1,10 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; -using JetBrains.Annotations; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -58,7 +55,7 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader(true)] - private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour colours) + private void load(OverlayColourProvider? colourProvider, OsuColour colours) { AccentColour = colourProvider?.Highlight1 ?? colours.Pink; GlowingAccentColour = colourProvider?.Highlight1.Lighten(0.2f) ?? colours.PinkLighter; From b8ae689b31e87437732c4fa59422f386acc0614c Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 13:41:14 +0100 Subject: [PATCH 030/154] Re-add Nub.cs and move logic from NormalNub.cs to it. --- osu.Game/Graphics/UserInterface/NormalNub.cs | 170 ++----------------- osu.Game/Graphics/UserInterface/Nub.cs | 162 ++++++++++++++++++ 2 files changed, 174 insertions(+), 158 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/Nub.cs diff --git a/osu.Game/Graphics/UserInterface/NormalNub.cs b/osu.Game/Graphics/UserInterface/NormalNub.cs index 1affbabd9d..1fe87da7a8 100644 --- a/osu.Game/Graphics/UserInterface/NormalNub.cs +++ b/osu.Game/Graphics/UserInterface/NormalNub.cs @@ -1,180 +1,34 @@ // 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 osuTK; -using osuTK.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Overlays; +using osuTK; namespace osu.Game.Graphics.UserInterface { - public partial class NormalNub : Container, IHasCurrentValue, IHasAccentColour + public partial class NormalNub : Nub { public const float HEIGHT = 15; public const float EXPANDED_SIZE = 50; - private const float border_width = 3; - - private readonly Box fill; - private readonly Container main; - public NormalNub() { Size = new Vector2(EXPANDED_SIZE, HEIGHT); + } - InternalChildren = new[] + protected override Container CreateNubContainer() + { + return new CircularContainer { - main = new CircularContainer - { - BorderColour = Color4.White, - BorderThickness = border_width, - Masking = true, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Children = new Drawable[] - { - fill = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - }, - } - }, + BorderColour = Colour4.White, + BorderThickness = BORDER_WIDTH, + Masking = true, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, }; } - - [BackgroundDependencyLoader(true)] - private void load(OverlayColourProvider? colourProvider, OsuColour colours) - { - AccentColour = colourProvider?.Highlight1 ?? colours.Pink; - GlowingAccentColour = colourProvider?.Highlight1.Lighten(0.2f) ?? colours.PinkLighter; - GlowColour = colourProvider?.Highlight1 ?? colours.PinkLighter; - - main.EdgeEffect = new EdgeEffectParameters - { - Colour = GlowColour.Opacity(0), - Type = EdgeEffectType.Glow, - Radius = 8, - Roundness = 4, - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - Current.BindValueChanged(onCurrentValueChanged, true); - } - - private bool glowing; - - public bool Glowing - { - get => glowing; - set - { - glowing = value; - - if (value) - { - main.FadeColour(GlowingAccentColour.Lighten(0.5f), 40, Easing.OutQuint) - .Then() - .FadeColour(GlowingAccentColour, 800, Easing.OutQuint); - - main.FadeEdgeEffectTo(Color4.White.Opacity(0.1f), 40, Easing.OutQuint) - .Then() - .FadeEdgeEffectTo(GlowColour.Opacity(0.1f), 800, Easing.OutQuint); - } - else - { - main.FadeEdgeEffectTo(GlowColour.Opacity(0), 800, Easing.OutQuint); - main.FadeColour(AccentColour, 800, Easing.OutQuint); - } - } - } - - private readonly Bindable current = new Bindable(); - - public Bindable Current - { - get => current; - set - { - ArgumentNullException.ThrowIfNull(value); - - current.UnbindBindings(); - current.BindTo(value); - } - } - - private Color4 accentColour; - - public Color4 AccentColour - { - get => accentColour; - set - { - accentColour = value; - if (!Glowing) - main.Colour = value; - } - } - - private Color4 glowingAccentColour; - - public Color4 GlowingAccentColour - { - get => glowingAccentColour; - set - { - glowingAccentColour = value; - if (Glowing) - main.Colour = value; - } - } - - private Color4 glowColour; - - public Color4 GlowColour - { - get => glowColour; - set - { - glowColour = value; - - var effect = main.EdgeEffect; - effect.Colour = Glowing ? value : value.Opacity(0); - main.EdgeEffect = effect; - } - } - - private void onCurrentValueChanged(ValueChangedEvent filled) - { - const double duration = 200; - - fill.FadeTo(filled.NewValue ? 1 : 0, duration, Easing.OutQuint); - - if (filled.NewValue) - { - main.ResizeWidthTo(1, duration, Easing.OutElasticHalf); - main.TransformTo(nameof(BorderThickness), 8.5f, duration, Easing.OutElasticHalf); - } - else - { - main.ResizeWidthTo(0.75f, duration, Easing.OutQuint); - main.TransformTo(nameof(BorderThickness), border_width, duration, Easing.OutQuint); - } - } } } diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs new file mode 100644 index 0000000000..7830381d10 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -0,0 +1,162 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Overlays; +using osuTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public abstract partial class Nub : Container, IHasCurrentValue, IHasAccentColour + { + protected const float BORDER_WIDTH = 3; + + private readonly Box fill; + private readonly Container main; + + protected abstract Container CreateNubContainer(); + + protected Nub() + { + InternalChild = main = CreateNubContainer(); + + main.Add(fill = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }); + } + + [BackgroundDependencyLoader(true)] + private void load(OverlayColourProvider? colourProvider, OsuColour colours) + { + AccentColour = colourProvider?.Highlight1 ?? colours.Pink; + GlowingAccentColour = colourProvider?.Highlight1.Lighten(0.2f) ?? colours.PinkLighter; + GlowColour = colourProvider?.Highlight1 ?? colours.PinkLighter; + + main.EdgeEffect = new EdgeEffectParameters + { + Colour = GlowColour.Opacity(0), + Type = EdgeEffectType.Glow, + Radius = 8, + Roundness = 4, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(onCurrentValueChanged, true); + } + + private bool glowing; + + public bool Glowing + { + get => glowing; + set + { + glowing = value; + + if (value) + { + main.FadeColour(GlowingAccentColour.Lighten(0.5f), 40, Easing.OutQuint) + .Then() + .FadeColour(GlowingAccentColour, 800, Easing.OutQuint); + + main.FadeEdgeEffectTo(Color4.White.Opacity(0.1f), 40, Easing.OutQuint) + .Then() + .FadeEdgeEffectTo(GlowColour.Opacity(0.1f), 800, Easing.OutQuint); + } + else + { + main.FadeEdgeEffectTo(GlowColour.Opacity(0), 800, Easing.OutQuint); + main.FadeColour(AccentColour, 800, Easing.OutQuint); + } + } + } + + private readonly Bindable current = new Bindable(); + + public Bindable Current + { + get => current; + set + { + ArgumentNullException.ThrowIfNull(value); + + current.UnbindBindings(); + current.BindTo(value); + } + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + if (!Glowing) + main.Colour = value; + } + } + + private Color4 glowingAccentColour; + + public Color4 GlowingAccentColour + { + get => glowingAccentColour; + set + { + glowingAccentColour = value; + if (Glowing) + main.Colour = value; + } + } + + private Color4 glowColour; + + public Color4 GlowColour + { + get => glowColour; + set + { + glowColour = value; + + var effect = main.EdgeEffect; + effect.Colour = Glowing ? value : value.Opacity(0); + main.EdgeEffect = effect; + } + } + + private void onCurrentValueChanged(ValueChangedEvent filled) + { + const double duration = 200; + + fill.FadeTo(filled.NewValue ? 1 : 0, duration, Easing.OutQuint); + + if (filled.NewValue) + { + main.ResizeWidthTo(1, duration, Easing.OutElasticHalf); + main.TransformTo(nameof(BorderThickness), 8.5f, duration, Easing.OutElasticHalf); + } + else + { + main.ResizeWidthTo(0.75f, duration, Easing.OutQuint); + main.TransformTo(nameof(BorderThickness), BORDER_WIDTH, duration, Easing.OutQuint); + } + } + } +} From 6dfb9630d62c19c5330a4090fcb3a94115bce64d Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 13:53:17 +0100 Subject: [PATCH 031/154] Implement ShearedNub.cs as well as tweak the syntax in NormalNub.cs --- osu.Game/Graphics/UserInterface/NormalNub.cs | 6 ++--- osu.Game/Graphics/UserInterface/Nub.cs | 4 +++ osu.Game/Graphics/UserInterface/ShearedNub.cs | 27 +++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/ShearedNub.cs diff --git a/osu.Game/Graphics/UserInterface/NormalNub.cs b/osu.Game/Graphics/UserInterface/NormalNub.cs index 1fe87da7a8..e6939d060b 100644 --- a/osu.Game/Graphics/UserInterface/NormalNub.cs +++ b/osu.Game/Graphics/UserInterface/NormalNub.cs @@ -18,9 +18,8 @@ namespace osu.Game.Graphics.UserInterface Size = new Vector2(EXPANDED_SIZE, HEIGHT); } - protected override Container CreateNubContainer() - { - return new CircularContainer + protected override Container CreateNubContainer() => + new CircularContainer { BorderColour = Colour4.White, BorderThickness = BORDER_WIDTH, @@ -29,6 +28,5 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }; - } } } diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 7830381d10..6f875e8594 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -22,6 +22,10 @@ namespace osu.Game.Graphics.UserInterface private readonly Box fill; private readonly Container main; + /// + /// Implements the shape for the nub, allowing for any type of container to be used. + /// + /// protected abstract Container CreateNubContainer(); protected Nub() diff --git a/osu.Game/Graphics/UserInterface/ShearedNub.cs b/osu.Game/Graphics/UserInterface/ShearedNub.cs new file mode 100644 index 0000000000..6c3fbaf7e6 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ShearedNub.cs @@ -0,0 +1,27 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + public partial class ShearedNub : Nub + { + public static readonly Vector2 SHEAR = new Vector2(0.15f, 0); + + protected override Container CreateNubContainer() => + new Container + { + Shear = SHEAR, + BorderColour = Colour4.White, + BorderThickness = BORDER_WIDTH, + Masking = true, + CornerRadius = 5, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }; + } +} From 2f90ffccfc19fad4cc8bc0e03f3a6d50d71cdab0 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 14:39:11 +0100 Subject: [PATCH 032/154] Implement ShearedSliderBar.cs and corresponding TestSceneShearedSliderBar.cs --- .../TestSceneShearedSliderBar.cs | 37 ++++ osu.Game/Graphics/UserInterface/ShearedNub.cs | 8 + .../UserInterface/ShearedSliderBar.cs | 170 ++++++++++++++++++ 3 files changed, 215 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneShearedSliderBar.cs create mode 100644 osu.Game/Graphics/UserInterface/ShearedSliderBar.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSliderBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSliderBar.cs new file mode 100644 index 0000000000..c2d0de95e0 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSliderBar.cs @@ -0,0 +1,37 @@ +// 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.Game.Graphics.UserInterface; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public partial class TestSceneShearedSlider : OsuTestScene + { + [Cached] + private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Purple); + + private readonly BindableDouble current = new BindableDouble(5) + { + Precision = 0.1f, + MinValue = 0, + MaxValue = 15 + }; + + [BackgroundDependencyLoader] + private void load() + { + Child = new ShearedSliderBar + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = current, + RelativeSizeAxes = Axes.X, + Width = 0.4f + }; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ShearedNub.cs b/osu.Game/Graphics/UserInterface/ShearedNub.cs index 6c3fbaf7e6..6bee4fc3b7 100644 --- a/osu.Game/Graphics/UserInterface/ShearedNub.cs +++ b/osu.Game/Graphics/UserInterface/ShearedNub.cs @@ -9,8 +9,16 @@ namespace osu.Game.Graphics.UserInterface { public partial class ShearedNub : Nub { + public const int HEIGHT = 30; + public const float EXPANDED_SIZE = 50; + public static readonly Vector2 SHEAR = new Vector2(0.15f, 0); + public ShearedNub() + { + Size = new Vector2(EXPANDED_SIZE, HEIGHT); + } + protected override Container CreateNubContainer() => new Container { diff --git a/osu.Game/Graphics/UserInterface/ShearedSliderBar.cs b/osu.Game/Graphics/UserInterface/ShearedSliderBar.cs new file mode 100644 index 0000000000..08d5fd8992 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ShearedSliderBar.cs @@ -0,0 +1,170 @@ +// 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 osuTK; +using osuTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Overlays; +using static osu.Game.Graphics.UserInterface.ShearedNub; + +namespace osu.Game.Graphics.UserInterface +{ + public partial class ShearedSliderBar : OsuSliderBar + where T : struct, IEquatable, IComparable, IConvertible + { + protected readonly ShearedNub Nub; + protected readonly Box LeftBox; + protected readonly Box RightBox; + private readonly Container nubContainer; + + private readonly HoverClickSounds hoverClickSounds; + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + LeftBox.Colour = value; + } + } + + private Colour4 backgroundColour; + + public Color4 BackgroundColour + { + get => backgroundColour; + set + { + backgroundColour = value; + RightBox.Colour = value; + } + } + + public ShearedSliderBar() + { + Shear = SHEAR; + Height = HEIGHT; + RangePadding = EXPANDED_SIZE / 2; + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Padding = new MarginPadding { Horizontal = 2 }, + Child = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Masking = true, + CornerRadius = 5, + Children = new Drawable[] + { + LeftBox = new Box + { + EdgeSmoothness = new Vector2(0, 0.5f), + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + RightBox = new Box + { + EdgeSmoothness = new Vector2(0, 0.5f), + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + }, + }, + }, + }, + nubContainer = new Container + { + Shear = -SHEAR, + RelativeSizeAxes = Axes.Both, + Child = Nub = new ShearedNub + { + X = -SHEAR.X * HEIGHT / 2f, + Origin = Anchor.TopCentre, + RelativePositionAxes = Axes.X, + Current = { Value = true } + }, + }, + hoverClickSounds = new HoverClickSounds() + }; + } + + [BackgroundDependencyLoader(true)] + private void load(OverlayColourProvider? colourProvider, OsuColour colours) + { + AccentColour = colourProvider?.Highlight1 ?? colours.Pink; + BackgroundColour = colourProvider?.Background5 ?? colours.PinkDarker.Darken(1); + } + + protected override void Update() + { + base.Update(); + + nubContainer.Padding = new MarginPadding { Horizontal = RangePadding }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindDisabledChanged(disabled => + { + Alpha = disabled ? 0.3f : 1; + hoverClickSounds.Enabled.Value = !disabled; + }, true); + } + + protected override bool OnHover(HoverEvent e) + { + updateGlow(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateGlow(); + base.OnHoverLost(e); + } + + protected override bool ShouldHandleAsRelativeDrag(MouseDownEvent e) + => Nub.ReceivePositionalInputAt(e.ScreenSpaceMouseDownPosition); + + protected override void OnDragEnd(DragEndEvent e) + { + updateGlow(); + base.OnDragEnd(e); + } + + private void updateGlow() + { + Nub.Glowing = !Current.Disabled && (IsHovered || IsDragged); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + LeftBox.Scale = new Vector2(Math.Clamp(RangePadding + Nub.DrawPosition.X - Nub.DrawWidth / 2.1f, 0, Math.Max(0, DrawWidth)), 1); + RightBox.Scale = new Vector2(Math.Clamp(DrawWidth - Nub.DrawPosition.X - RangePadding - Nub.DrawWidth / 2.1f, 0, Math.Max(0, DrawWidth)), 1); + } + + protected override void UpdateValue(float value) + { + Nub.MoveToX(value, 250, Easing.OutQuint); + } + } +} From 88406946748daa7f64cb815f6679c58952a6ca43 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 15:00:48 +0100 Subject: [PATCH 033/154] Adjust some padding details on ShearedSliderBar.cs as well as colouration tweaks. --- osu.Game/Graphics/UserInterface/ShearedSliderBar.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSliderBar.cs b/osu.Game/Graphics/UserInterface/ShearedSliderBar.cs index 08d5fd8992..a18a6a259c 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSliderBar.cs @@ -33,7 +33,10 @@ namespace osu.Game.Graphics.UserInterface set { accentColour = value; - LeftBox.Colour = value; + + // We want to slightly darken the colour for the box because the sheared slider has the boxes at the same height as the nub, + // making the nub invisible when not hovered. + LeftBox.Colour = value.Darken(0.1f); } } @@ -158,8 +161,8 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - LeftBox.Scale = new Vector2(Math.Clamp(RangePadding + Nub.DrawPosition.X - Nub.DrawWidth / 2.1f, 0, Math.Max(0, DrawWidth)), 1); - RightBox.Scale = new Vector2(Math.Clamp(DrawWidth - Nub.DrawPosition.X - RangePadding - Nub.DrawWidth / 2.1f, 0, Math.Max(0, DrawWidth)), 1); + LeftBox.Scale = new Vector2(Math.Clamp(RangePadding + Nub.DrawPosition.X - Nub.DrawWidth / 2.15f, 0, Math.Max(0, DrawWidth)), 1); + RightBox.Scale = new Vector2(Math.Clamp(DrawWidth - Nub.DrawPosition.X - RangePadding - Nub.DrawWidth / 2.15f, 0, Math.Max(0, DrawWidth)), 1); } protected override void UpdateValue(float value) From a630f1113ff51fa615cd1048e8e2f5b3436364e1 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 15:01:27 +0100 Subject: [PATCH 034/154] Rename nub object in NormalSliderBar.cs class --- .../Graphics/UserInterface/NormalSliderBar.cs | 14 +++++++------- osu.Game/Graphics/UserInterface/RangeSlider.cs | 16 ++++++++-------- .../Play/PlayerSettings/PlayerSliderBar.cs | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs index bc27c9af4c..3a3603e1de 100644 --- a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs @@ -17,7 +17,7 @@ namespace osu.Game.Graphics.UserInterface public partial class NormalSliderBar : OsuSliderBar where T : struct, IEquatable, IComparable, IConvertible { - protected readonly NormalNub NormalNub; + protected readonly NormalNub Nub; protected readonly Box LeftBox; protected readonly Box RightBox; private readonly Container nubContainer; @@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface nubContainer = new Container { RelativeSizeAxes = Axes.Both, - Child = NormalNub = new NormalNub + Child = Nub = new NormalNub { Origin = Anchor.TopCentre, RelativePositionAxes = Axes.X, @@ -142,7 +142,7 @@ namespace osu.Game.Graphics.UserInterface } protected override bool ShouldHandleAsRelativeDrag(MouseDownEvent e) - => NormalNub.ReceivePositionalInputAt(e.ScreenSpaceMouseDownPosition); + => Nub.ReceivePositionalInputAt(e.ScreenSpaceMouseDownPosition); protected override void OnDragEnd(DragEndEvent e) { @@ -152,19 +152,19 @@ namespace osu.Game.Graphics.UserInterface private void updateGlow() { - NormalNub.Glowing = !Current.Disabled && (IsHovered || IsDragged); + Nub.Glowing = !Current.Disabled && (IsHovered || IsDragged); } protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - LeftBox.Scale = new Vector2(Math.Clamp(RangePadding + NormalNub.DrawPosition.X - NormalNub.DrawWidth / 2, 0, Math.Max(0, DrawWidth)), 1); - RightBox.Scale = new Vector2(Math.Clamp(DrawWidth - NormalNub.DrawPosition.X - RangePadding - NormalNub.DrawWidth / 2, 0, Math.Max(0, DrawWidth)), 1); + LeftBox.Scale = new Vector2(Math.Clamp(RangePadding + Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, Math.Max(0, DrawWidth)), 1); + RightBox.Scale = new Vector2(Math.Clamp(DrawWidth - Nub.DrawPosition.X - RangePadding - Nub.DrawWidth / 2, 0, Math.Max(0, DrawWidth)), 1); } protected override void UpdateValue(float value) { - NormalNub.MoveToX(value, 250, Easing.OutQuint); + Nub.MoveToX(value, 250, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/RangeSlider.cs b/osu.Game/Graphics/UserInterface/RangeSlider.cs index 963c859198..806209d548 100644 --- a/osu.Game/Graphics/UserInterface/RangeSlider.cs +++ b/osu.Game/Graphics/UserInterface/RangeSlider.cs @@ -141,7 +141,7 @@ namespace osu.Game.Graphics.UserInterface public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) - && screenSpacePos.X <= NormalNub.ScreenSpaceDrawQuad.TopRight.X; + && screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X; } private partial class UpperBoundSlider : BoundSlider @@ -155,7 +155,7 @@ namespace osu.Game.Graphics.UserInterface public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) - && screenSpacePos.X >= NormalNub.ScreenSpaceDrawQuad.TopLeft.X; + && screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X; } protected partial class BoundSlider : NormalSliderBar @@ -177,12 +177,12 @@ namespace osu.Game.Graphics.UserInterface protected override void LoadComplete() { base.LoadComplete(); - NormalNub.Width = NubWidth; - RangePadding = NormalNub.Width / 2; + Nub.Width = NubWidth; + RangePadding = Nub.Width / 2; OsuSpriteText currentDisplay; - NormalNub.Add(currentDisplay = new OsuSpriteText + Nub.Add(currentDisplay = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -203,9 +203,9 @@ namespace osu.Game.Graphics.UserInterface if (colourProvider == null) return; AccentColour = colourProvider.Background2; - NormalNub.AccentColour = colourProvider.Background2; - NormalNub.GlowingAccentColour = colourProvider.Background1; - NormalNub.GlowColour = colourProvider.Background2; + Nub.AccentColour = colourProvider.Background2; + Nub.GlowingAccentColour = colourProvider.Background1; + Nub.GlowColour = colourProvider.Background2; } } } diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index b54207886e..985a414bc0 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -30,9 +30,9 @@ namespace osu.Game.Screens.Play.PlayerSettings private void load(OsuColour colours) { AccentColour = colours.Yellow; - NormalNub.AccentColour = colours.Yellow; - NormalNub.GlowingAccentColour = colours.YellowLighter; - NormalNub.GlowColour = colours.YellowDark; + Nub.AccentColour = colours.Yellow; + Nub.GlowingAccentColour = colours.YellowLighter; + Nub.GlowColour = colours.YellowDark; } } } From 1de0bed83d0b8889900ef3b1ebcac52f178ef4a7 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Thu, 26 Jan 2023 11:09:16 -0300 Subject: [PATCH 035/154] fix comment --- osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs index 4feb25e60b..ce1b0db76d 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -52,8 +52,8 @@ namespace osu.Game.Overlays.Profile.Header.Components new Box { RelativeSizeAxes = Axes.Both, - // Normal background color is 0.75 opacity, probationary doesn't have this cause they are a bit transparent already Colour = colourProvider?.Background6 ?? Colour4.Black, + // Normal badges background opacity is 75%, probationary is full opacity as the whole badge gets a bit transparent Alpha = group.IsProbationary ? 1 : 0.75f, }, innerContainer = new FillFlowContainer From 76146b5c5372d2146aa557e09aabe882e1646209 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 15:12:52 +0100 Subject: [PATCH 036/154] Address naming discrepancy in TestSceneShearedSliderBar.cs --- .../Visual/UserInterface/TestSceneShearedSliderBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSliderBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSliderBar.cs index c2d0de95e0..766f22d867 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSliderBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSliderBar.cs @@ -9,7 +9,7 @@ using osu.Game.Overlays; namespace osu.Game.Tests.Visual.UserInterface { - public partial class TestSceneShearedSlider : OsuTestScene + public partial class TestSceneShearedSliderBar : OsuTestScene { [Cached] private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Purple); From 091cc155d33ba19b4f99f7c2243c683773f38065 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 26 Jan 2023 16:10:02 +0100 Subject: [PATCH 037/154] Fix nub naming in OsuCheckbox.cs and associated classes --- .../Graphics/UserInterface/OsuCheckbox.cs | 24 +++++++++---------- .../OsuDirectorySelectorHiddenToggle.cs | 6 ++--- osu.Game/Overlays/Mods/ModColumn.cs | 6 ++--- .../Play/PlayerSettings/PlayerCheckbox.cs | 6 ++--- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 982706f87b..877493dd5c 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface } } - protected readonly NormalNub NormalNub; + protected readonly NormalNub Nub; protected readonly OsuTextFlowContainer LabelTextFlowContainer; private Sample sampleChecked; @@ -61,28 +61,28 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, }, - NormalNub = new NormalNub(), + Nub = new NormalNub(), new HoverSounds() }; if (nubOnRight) { - NormalNub.Anchor = Anchor.CentreRight; - NormalNub.Origin = Anchor.CentreRight; - NormalNub.Margin = new MarginPadding { Right = nub_padding }; + Nub.Anchor = Anchor.CentreRight; + Nub.Origin = Anchor.CentreRight; + Nub.Margin = new MarginPadding { Right = nub_padding }; LabelTextFlowContainer.Padding = new MarginPadding { Right = NormalNub.EXPANDED_SIZE + nub_padding * 2 }; } else { - NormalNub.Anchor = Anchor.CentreLeft; - NormalNub.Origin = Anchor.CentreLeft; - NormalNub.Margin = new MarginPadding { Left = nub_padding }; + Nub.Anchor = Anchor.CentreLeft; + Nub.Origin = Anchor.CentreLeft; + Nub.Margin = new MarginPadding { Left = nub_padding }; LabelTextFlowContainer.Padding = new MarginPadding { Left = NormalNub.EXPANDED_SIZE + nub_padding * 2 }; } - NormalNub.Current.BindTo(Current); + Nub.Current.BindTo(Current); - Current.DisabledChanged += disabled => LabelTextFlowContainer.Alpha = NormalNub.Alpha = disabled ? 0.3f : 1; + Current.DisabledChanged += disabled => LabelTextFlowContainer.Alpha = Nub.Alpha = disabled ? 0.3f : 1; } /// @@ -101,13 +101,13 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { - NormalNub.Glowing = true; + Nub.Glowing = true; return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - NormalNub.Glowing = false; + Nub.Glowing = false; base.OnHoverLost(e); } diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs index 79f72495c8..7665ed507f 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorHiddenToggle.cs @@ -30,9 +30,9 @@ namespace osu.Game.Graphics.UserInterfaceV2 if (overlayColourProvider != null) return; - NormalNub.AccentColour = colours.GreySeaFoamLighter; - NormalNub.GlowingAccentColour = Color4.White; - NormalNub.GlowColour = Color4.White; + Nub.AccentColour = colours.GreySeaFoamLighter; + Nub.GlowingAccentColour = Color4.White; + Nub.GlowColour = Color4.White; } } } diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 97a766259a..5d9f616e5f 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -267,9 +267,9 @@ namespace osu.Game.Overlays.Mods private void updateState() { - NormalNub.AccentColour = AccentColour; - NormalNub.GlowingAccentColour = AccentHoverColour; - NormalNub.GlowColour = AccentHoverColour.Opacity(0.2f); + Nub.AccentColour = AccentColour; + Nub.GlowingAccentColour = AccentHoverColour; + Nub.GlowColour = AccentHoverColour.Opacity(0.2f); } protected override void OnUserChange(bool value) diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs index 960904282d..49c9cbf385 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs @@ -18,9 +18,9 @@ namespace osu.Game.Screens.Play.PlayerSettings [BackgroundDependencyLoader] private void load(OsuColour colours) { - NormalNub.AccentColour = colours.Yellow; - NormalNub.GlowingAccentColour = colours.YellowLighter; - NormalNub.GlowColour = colours.YellowDark; + Nub.AccentColour = colours.Yellow; + Nub.GlowingAccentColour = colours.YellowLighter; + Nub.GlowColour = colours.YellowDark; } } } From 41f5e5143af134be4a018f0830c68a90c479c2fa Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 30 Jan 2023 12:56:39 +0100 Subject: [PATCH 038/154] Remove ```onclick``` and ```mousedown``` override --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 33bf062abb..a4cdf8b71b 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -80,11 +80,10 @@ namespace osu.Game.Screens.Select.FooterV2 Size = new Vector2(button_width, button_height); Masking = true; CornerRadius = corner_radius; - InternalChildren = new Drawable[] + Children = new Drawable[] { backgroundBox = new Box { - Colour = colourProvider.Background3, RelativeSizeAxes = Axes.Both }, @@ -142,6 +141,9 @@ namespace osu.Game.Screens.Select.FooterV2 { base.LoadComplete(); + // We want the first colour assignment for the background to be instantaneous + backgroundBox.Colour = Enabled.Value ? colourProvider.Background3 : colourProvider.Background3.Darken(0.3f); + Enabled.BindValueChanged(_ => updateDisplay(), true); OverlayState.BindValueChanged(_ => updateDisplay()); } @@ -156,9 +158,6 @@ namespace osu.Game.Screens.Select.FooterV2 protected override void OnHoverLost(HoverLostEvent e) => updateDisplay(); - protected override bool OnMouseDown(MouseDownEvent e) => !Enabled.Value || base.OnMouseDown(e); - protected override bool OnClick(ClickEvent e) => !Enabled.Value || base.OnClick(e); - public virtual bool OnPressed(KeyBindingPressEvent e) { if (e.Action != Hotkey || e.Repeat) return false; From f5d579144b0aa390cabc5321483841418db6674f Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 30 Jan 2023 12:57:24 +0100 Subject: [PATCH 039/154] Remove free mods button --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 1 - .../Select/FooterV2/FooterButtonFreeModsV2.cs | 21 ------------------- 2 files changed, 22 deletions(-) delete mode 100644 osu.Game/Screens/Select/FooterV2/FooterButtonFreeModsV2.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index 534bd0ad28..a1ba8daf8e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -50,7 +50,6 @@ namespace osu.Game.Tests.Visual.SongSelect PreviousRandom = () => previousRandomCalled = true }); footer.AddButton(new FooterButtonOptionsV2()); - footer.AddButton(new FooterButtonFreeModsV2()); InputManager.MoveMouseTo(Vector2.Zero); diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonFreeModsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonFreeModsV2.cs deleted file mode 100644 index 523a2afa36..0000000000 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonFreeModsV2.cs +++ /dev/null @@ -1,21 +0,0 @@ -// 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.Graphics.Sprites; -using osu.Game.Graphics; - -namespace osu.Game.Screens.Select.FooterV2 -{ - public partial class FooterButtonFreeModsV2 : FooterButtonV2 - { - [BackgroundDependencyLoader] - private void load(OsuColour colour) - { - //No design exists for this button! - Icon = FontAwesome.Solid.ExpandArrowsAlt; - Text = "Freemods"; - AccentColour = colour.Yellow; - } - } -} From 7c5a65bdb7a328fea885de5d5494107f606869ce Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 2 Feb 2023 17:23:09 +0100 Subject: [PATCH 040/154] Rename NormalNub.cs to RoundedNub.cs --- .../Visual/UserInterface/TestSceneRangeSlider.cs | 2 +- osu.Game/Graphics/UserInterface/NormalSliderBar.cs | 8 ++++---- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 8 ++++---- osu.Game/Graphics/UserInterface/RangeSlider.cs | 2 +- .../UserInterface/{NormalNub.cs => RoundedNub.cs} | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) rename osu.Game/Graphics/UserInterface/{NormalNub.cs => RoundedNub.cs} (92%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs index 0100b2a1a0..1b91459615 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.UserInterface LowerBound = customStart, UpperBound = customEnd, TooltipSuffix = "suffix", - NubWidth = NormalNub.HEIGHT * 2, + NubWidth = RoundedNub.HEIGHT * 2, DefaultStringLowerBound = "Start", DefaultStringUpperBound = "End", MinRange = 10 diff --git a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs index 3a3603e1de..573aa5e40d 100644 --- a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/NormalSliderBar.cs @@ -17,7 +17,7 @@ namespace osu.Game.Graphics.UserInterface public partial class NormalSliderBar : OsuSliderBar where T : struct, IEquatable, IComparable, IConvertible { - protected readonly NormalNub Nub; + protected readonly RoundedNub Nub; protected readonly Box LeftBox; protected readonly Box RightBox; private readonly Container nubContainer; @@ -50,8 +50,8 @@ namespace osu.Game.Graphics.UserInterface public NormalSliderBar() { - Height = NormalNub.HEIGHT; - RangePadding = NormalNub.EXPANDED_SIZE / 2; + Height = RoundedNub.HEIGHT; + RangePadding = RoundedNub.EXPANDED_SIZE / 2; Children = new Drawable[] { new Container @@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface nubContainer = new Container { RelativeSizeAxes = Axes.Both, - Child = Nub = new NormalNub + Child = Nub = new RoundedNub { Origin = Anchor.TopCentre, RelativePositionAxes = Axes.X, diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 877493dd5c..2fae4e2cb5 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface } } - protected readonly NormalNub Nub; + protected readonly RoundedNub Nub; protected readonly OsuTextFlowContainer LabelTextFlowContainer; private Sample sampleChecked; @@ -61,7 +61,7 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, }, - Nub = new NormalNub(), + Nub = new RoundedNub(), new HoverSounds() }; @@ -70,14 +70,14 @@ namespace osu.Game.Graphics.UserInterface Nub.Anchor = Anchor.CentreRight; Nub.Origin = Anchor.CentreRight; Nub.Margin = new MarginPadding { Right = nub_padding }; - LabelTextFlowContainer.Padding = new MarginPadding { Right = NormalNub.EXPANDED_SIZE + nub_padding * 2 }; + LabelTextFlowContainer.Padding = new MarginPadding { Right = RoundedNub.EXPANDED_SIZE + nub_padding * 2 }; } else { Nub.Anchor = Anchor.CentreLeft; Nub.Origin = Anchor.CentreLeft; Nub.Margin = new MarginPadding { Left = nub_padding }; - LabelTextFlowContainer.Padding = new MarginPadding { Left = NormalNub.EXPANDED_SIZE + nub_padding * 2 }; + LabelTextFlowContainer.Padding = new MarginPadding { Left = RoundedNub.EXPANDED_SIZE + nub_padding * 2 }; } Nub.Current.BindTo(Current); diff --git a/osu.Game/Graphics/UserInterface/RangeSlider.cs b/osu.Game/Graphics/UserInterface/RangeSlider.cs index 806209d548..76096f7ed0 100644 --- a/osu.Game/Graphics/UserInterface/RangeSlider.cs +++ b/osu.Game/Graphics/UserInterface/RangeSlider.cs @@ -163,7 +163,7 @@ namespace osu.Game.Graphics.UserInterface public string? DefaultString; public LocalisableString? DefaultTooltip; public string? TooltipSuffix; - public float NubWidth { get; set; } = NormalNub.HEIGHT; + public float NubWidth { get; set; } = RoundedNub.HEIGHT; public override LocalisableString TooltipText => (Current.IsDefault ? DefaultTooltip : Current.Value.ToString($@"0.## {TooltipSuffix}")) ?? Current.Value.ToString($@"0.## {TooltipSuffix}"); diff --git a/osu.Game/Graphics/UserInterface/NormalNub.cs b/osu.Game/Graphics/UserInterface/RoundedNub.cs similarity index 92% rename from osu.Game/Graphics/UserInterface/NormalNub.cs rename to osu.Game/Graphics/UserInterface/RoundedNub.cs index e6939d060b..3bdfadfe22 100644 --- a/osu.Game/Graphics/UserInterface/NormalNub.cs +++ b/osu.Game/Graphics/UserInterface/RoundedNub.cs @@ -7,13 +7,13 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public partial class NormalNub : Nub + public partial class RoundedNub : Nub { public const float HEIGHT = 15; public const float EXPANDED_SIZE = 50; - public NormalNub() + public RoundedNub() { Size = new Vector2(EXPANDED_SIZE, HEIGHT); } From 3f0ce75bf5f937565f13b022059e5e10c97f331f Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 2 Feb 2023 17:24:45 +0100 Subject: [PATCH 041/154] Rename NormalSliderBar.cs to RoundedSliderBar.cs --- osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs | 2 +- osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs | 8 ++++---- .../UserInterface/TestSceneModDifficultyAdjustSettings.cs | 4 ++-- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 2 +- osu.Game/Graphics/UserInterface/ExpandableSlider.cs | 4 ++-- osu.Game/Graphics/UserInterface/RangeSlider.cs | 2 +- .../{NormalSliderBar.cs => RoundedSliderBar.cs} | 4 ++-- osu.Game/Graphics/UserInterface/TimeSlider.cs | 2 +- osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs | 2 +- .../Overlays/Settings/Sections/Audio/VolumeSettings.cs | 2 +- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- .../Overlays/Settings/Sections/Input/MouseSettings.cs | 2 +- osu.Game/Overlays/Settings/Sections/SizeSlider.cs | 2 +- osu.Game/Overlays/Settings/SettingsSlider.cs | 4 ++-- osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs | 2 +- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 2 +- osu.Game/Rulesets/Mods/ModMuted.cs | 2 +- osu.Game/Rulesets/Mods/ModNoScope.cs | 2 +- osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs | 4 ++-- 19 files changed, 27 insertions(+), 27 deletions(-) rename osu.Game/Graphics/UserInterface/{NormalSliderBar.cs => RoundedSliderBar.cs} (98%) diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index 5642fb4bdb..fc0b4a9ed9 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Mania }; } - private partial class ManiaScrollSlider : NormalSliderBar + private partial class ManiaScrollSlider : RoundedSliderBar { public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip(Current.Value, (int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / Current.Value)); } diff --git a/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs b/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs index 791a5651b6..d96c19a13e 100644 --- a/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs +++ b/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs @@ -31,8 +31,8 @@ namespace osu.Game.Tests.Visual.Audio private WaveformTestBeatmap beatmap; - private NormalSliderBar lowPassSlider; - private NormalSliderBar highPassSlider; + private RoundedSliderBar lowPassSlider; + private RoundedSliderBar highPassSlider; [BackgroundDependencyLoader] private void load(AudioManager audio) @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Audio Text = $"Low Pass: {lowPassFilter.Cutoff}hz", Font = new FontUsage(size: 40) }, - lowPassSlider = new NormalSliderBar + lowPassSlider = new RoundedSliderBar { Width = 500, Height = 50, @@ -69,7 +69,7 @@ namespace osu.Game.Tests.Visual.Audio Text = $"High Pass: {highPassFilter.Cutoff}hz", Font = new FontUsage(size: 40) }, - highPassSlider = new NormalSliderBar + highPassSlider = new RoundedSliderBar { Width = 500, Height = 50, diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs index 5e2b5ca4ff..307f436f84 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs @@ -261,7 +261,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep($"Set {name} slider to {value}", () => this.ChildrenOfType().First(c => c.LabelText == name) - .ChildrenOfType>().First().Current.Value = value); + .ChildrenOfType>().First().Current.Value = value); } private void checkBindableAtValue(string name, float? expectedValue) @@ -275,7 +275,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddAssert($"Slider {name} at {expectedValue}", () => this.ChildrenOfType().First(c => c.LabelText == name) - .ChildrenOfType>().First().Current.Value == expectedValue); + .ChildrenOfType>().First().Current.Value == expectedValue); } private void setBeatmapWithDifficultyParameters(float value) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 1cbb798981..5ccaebd721 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -270,7 +270,7 @@ namespace osu.Game.Tests.Visual.UserInterface createScreen(); AddStep("select difficulty adjust via panel", () => getPanelForMod(typeof(OsuModDifficultyAdjust)).TriggerClick()); - AddStep("set setting", () => modSelectOverlay.ChildrenOfType>().First().Current.Value = 8); + AddStep("set setting", () => modSelectOverlay.ChildrenOfType>().First().Current.Value = 8); AddAssert("ensure setting is propagated", () => SelectedMods.Value.OfType().Single().CircleSize.Value == 8); diff --git a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs index e960f55501..5bc17303d8 100644 --- a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs +++ b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs @@ -21,7 +21,7 @@ namespace osu.Game.Graphics.UserInterface /// public partial class ExpandableSlider : CompositeDrawable, IExpandable, IHasCurrentValue where T : struct, IEquatable, IComparable, IConvertible - where TSlider : NormalSliderBar, new() + where TSlider : RoundedSliderBar, new() { private readonly OsuSpriteText label; private readonly TSlider slider; @@ -130,7 +130,7 @@ namespace osu.Game.Graphics.UserInterface /// /// An implementation for the UI slider bar control. /// - public partial class ExpandableSlider : ExpandableSlider> + public partial class ExpandableSlider : ExpandableSlider> where T : struct, IEquatable, IComparable, IConvertible { } diff --git a/osu.Game/Graphics/UserInterface/RangeSlider.cs b/osu.Game/Graphics/UserInterface/RangeSlider.cs index 76096f7ed0..575327b50b 100644 --- a/osu.Game/Graphics/UserInterface/RangeSlider.cs +++ b/osu.Game/Graphics/UserInterface/RangeSlider.cs @@ -158,7 +158,7 @@ namespace osu.Game.Graphics.UserInterface && screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X; } - protected partial class BoundSlider : NormalSliderBar + protected partial class BoundSlider : RoundedSliderBar { public string? DefaultString; public LocalisableString? DefaultTooltip; diff --git a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs b/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs similarity index 98% rename from osu.Game/Graphics/UserInterface/NormalSliderBar.cs rename to osu.Game/Graphics/UserInterface/RoundedSliderBar.cs index 573aa5e40d..765e1d5105 100644 --- a/osu.Game/Graphics/UserInterface/NormalSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterface { - public partial class NormalSliderBar : OsuSliderBar + public partial class RoundedSliderBar : OsuSliderBar where T : struct, IEquatable, IComparable, IConvertible { protected readonly RoundedNub Nub; @@ -48,7 +48,7 @@ namespace osu.Game.Graphics.UserInterface } } - public NormalSliderBar() + public RoundedSliderBar() { Height = RoundedNub.HEIGHT; RangePadding = RoundedNub.EXPANDED_SIZE / 2; diff --git a/osu.Game/Graphics/UserInterface/TimeSlider.cs b/osu.Game/Graphics/UserInterface/TimeSlider.cs index 15fc0a465b..e4058827f3 100644 --- a/osu.Game/Graphics/UserInterface/TimeSlider.cs +++ b/osu.Game/Graphics/UserInterface/TimeSlider.cs @@ -10,7 +10,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A slider bar which displays a millisecond time value. /// - public partial class TimeSlider : NormalSliderBar + public partial class TimeSlider : RoundedSliderBar { public override LocalisableString TooltipText => $"{Current.Value:N0} ms"; } diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs b/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs index 75aedc298e..e3cd2ae36c 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.FirstRunSetup public override bool? AllowTrackAdjustments => false; } - private partial class UIScaleSlider : NormalSliderBar + private partial class UIScaleSlider : RoundedSliderBar { public override LocalisableString TooltipText => base.TooltipText + "x"; } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 0c62cb169f..7066be4f92 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override Drawable CreateControl() { - var sliderBar = (NormalSliderBar)base.CreateControl(); + var sliderBar = (RoundedSliderBar)base.CreateControl(); sliderBar.PlaySamplesOnAdjust = false; return sliderBar; } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 805cf4ca0b..6465d62ef0 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -329,7 +329,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } - private partial class UIScaleSlider : NormalSliderBar + private partial class UIScaleSlider : RoundedSliderBar { public override LocalisableString TooltipText => base.TooltipText + "x"; } diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index f403012793..dfaeafbf5d 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - public partial class SensitivitySlider : NormalSliderBar + public partial class SensitivitySlider : RoundedSliderBar { public override LocalisableString TooltipText => Current.Disabled ? MouseSettingsStrings.EnableHighPrecisionForSensitivityAdjust : $"{base.TooltipText}x"; } diff --git a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs index b596212007..20d77bef0d 100644 --- a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs +++ b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections /// /// A slider intended to show a "size" multiplier number, where 1x is 1.0. /// - public partial class SizeSlider : NormalSliderBar + public partial class SizeSlider : RoundedSliderBar where T : struct, IEquatable, IComparable, IConvertible, IFormattable { public override LocalisableString TooltipText => Current.Value.ToString(@"0.##x", NumberFormatInfo.CurrentInfo); diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index a7305b4e03..e1483d4202 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -10,14 +10,14 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public partial class SettingsSlider : SettingsSlider> + public partial class SettingsSlider : SettingsSlider> where T : struct, IEquatable, IComparable, IConvertible { } public partial class SettingsSlider : SettingsItem where TValue : struct, IEquatable, IComparable, IConvertible - where TSlider : NormalSliderBar, new() + where TSlider : RoundedSliderBar, new() { protected override Drawable CreateControl() => new TSlider { diff --git a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs index 58810fc127..a941c0a1db 100644 --- a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs +++ b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Mods { InternalChildren = new Drawable[] { - new NormalSliderBar + new RoundedSliderBar { RelativeSizeAxes = Axes.X, Current = currentNumber, diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index a7b00ac88b..dc7594f469 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Mods } } - public partial class PercentSlider : NormalSliderBar + public partial class PercentSlider : RoundedSliderBar { public PercentSlider() { diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index d2d8284083..367ceeb446 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Mods public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } - public partial class MuteComboSlider : NormalSliderBar + public partial class MuteComboSlider : RoundedSliderBar { public override LocalisableString TooltipText => Current.Value == 0 ? "always muted" : base.TooltipText; } diff --git a/osu.Game/Rulesets/Mods/ModNoScope.cs b/osu.Game/Rulesets/Mods/ModNoScope.cs index 3736eca780..5b9dfc0430 100644 --- a/osu.Game/Rulesets/Mods/ModNoScope.cs +++ b/osu.Game/Rulesets/Mods/ModNoScope.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Mods } } - public partial class HiddenComboSlider : NormalSliderBar + public partial class HiddenComboSlider : RoundedSliderBar { public override LocalisableString TooltipText => Current.Value == 0 ? "always hidden" : base.TooltipText; } diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index 985a414bc0..45009684a6 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -15,11 +15,11 @@ namespace osu.Game.Screens.Play.PlayerSettings public partial class PlayerSliderBar : SettingsSlider where T : struct, IEquatable, IComparable, IConvertible { - public NormalSliderBar Bar => (NormalSliderBar)Control; + public RoundedSliderBar Bar => (RoundedSliderBar)Control; protected override Drawable CreateControl() => new SliderBar(); - protected partial class SliderBar : NormalSliderBar + protected partial class SliderBar : RoundedSliderBar { public SliderBar() { From 80fd1a0bc7d85e8dae00089cea00bf14a762c7c7 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 2 Feb 2023 18:29:12 +0100 Subject: [PATCH 042/154] Remove leftover comment regarding X axis offsets --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index a4cdf8b71b..94b21666ac 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -120,8 +120,6 @@ namespace osu.Game.Screens.Select.FooterV2 }, new Container { - // The X offset has to multiplied as such to account for the fact that we only want to offset by the distance from the CenterLeft point of the container - // not the whole shear width Shear = -SHEAR, Anchor = Anchor.BottomCentre, Origin = Anchor.Centre, From a1200b8fe87fb5c56e34469dcc21e9d2470f4584 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Feb 2023 16:24:19 +0900 Subject: [PATCH 043/154] Adjust footer button colour handling to read better and take into account mouse down --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 5 +-- .../Screens/Select/FooterV2/FooterButtonV2.cs | 45 +++++++++++++------ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index a1ba8daf8e..773d067c15 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -10,7 +10,6 @@ using osu.Framework.Testing; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Screens.Select.FooterV2; -using osuTK; using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect @@ -51,15 +50,13 @@ namespace osu.Game.Tests.Visual.SongSelect }); footer.AddButton(new FooterButtonOptionsV2()); - InputManager.MoveMouseTo(Vector2.Zero); - overlay.Hide(); }); [Test] public void TestState() { - AddRepeatStep("toggle options state", () => this.ChildrenOfType().Last().Enabled.Toggle(), 20); + AddToggleStep("set options enabled state", state => this.ChildrenOfType().Last().Enabled.Value = state); } [Test] diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 94b21666ac..123ec51bd4 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -18,6 +18,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Select.FooterV2 { @@ -148,12 +149,28 @@ namespace osu.Game.Screens.Select.FooterV2 public GlobalAction? Hotkey; + private bool handlingMouse; + protected override bool OnHover(HoverEvent e) { updateDisplay(); return true; } + protected override bool OnMouseDown(MouseDownEvent e) + { + handlingMouse = true; + updateDisplay(); + return base.OnMouseDown(e); + } + + protected override void OnMouseUp(MouseUpEvent e) + { + handlingMouse = false; + updateDisplay(); + base.OnMouseUp(e); + } + protected override void OnHoverLost(HoverLostEvent e) => updateDisplay(); public virtual bool OnPressed(KeyBindingPressEvent e) @@ -168,25 +185,27 @@ namespace osu.Game.Screens.Select.FooterV2 private void updateDisplay() { + Color4 backgroundColour = colourProvider.Background3; + if (!Enabled.Value) { - backgroundBox.FadeColour(colourProvider.Background3.Darken(0.3f), transition_length, Easing.OutQuint); - return; + backgroundColour = colourProvider.Background3.Darken(0.4f); } - - if (OverlayState.Value == Visibility.Visible) + else { - backgroundBox.FadeColour(buttonAccentColour.Darken(0.5f), transition_length, Easing.OutQuint); - return; + if (OverlayState.Value == Visibility.Visible) + backgroundColour = buttonAccentColour.Darken(0.5f); + + if (IsHovered) + { + backgroundColour = backgroundColour.Lighten(0.3f); + + if (handlingMouse) + backgroundColour = backgroundColour.Lighten(0.3f); + } } - if (IsHovered) - { - backgroundBox.FadeColour(colourProvider.Background3.Lighten(0.3f), transition_length, Easing.OutQuint); - return; - } - - backgroundBox.FadeColour(colourProvider.Background3, transition_length, Easing.OutQuint); + backgroundBox.FadeColour(backgroundColour, transition_length, Easing.OutQuint); } } } From 4248453616387e1507ba1fd42969d730de113ec6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Feb 2023 16:25:54 +0900 Subject: [PATCH 044/154] Use `FinishTransforms` rather than manual duplication of background colour logic --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 123ec51bd4..eee2e50b25 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -140,11 +140,10 @@ namespace osu.Game.Screens.Select.FooterV2 { base.LoadComplete(); - // We want the first colour assignment for the background to be instantaneous - backgroundBox.Colour = Enabled.Value ? colourProvider.Background3 : colourProvider.Background3.Darken(0.3f); - - Enabled.BindValueChanged(_ => updateDisplay(), true); OverlayState.BindValueChanged(_ => updateDisplay()); + Enabled.BindValueChanged(_ => updateDisplay(), true); + + FinishTransforms(true); } public GlobalAction? Hotkey; From 48f7e0163c14fe4a491c5959d0387303456b3cbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Feb 2023 16:26:54 +0900 Subject: [PATCH 045/154] Adjust comments and formatting of comments --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index eee2e50b25..409d9daaae 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Select.FooterV2 private const int corner_radius = 10; private const int transition_length = 500; - //Accounts for corner radius margin on bottom, would be 12 + // This should be 12 by design, but an extra allowance is added due to the corner radius specification. public const float SHEAR_WIDTH = 13.5f; public Bindable OverlayState = new Bindable(); @@ -88,7 +88,7 @@ namespace osu.Game.Screens.Select.FooterV2 RelativeSizeAxes = Axes.Both }, - //For elements that should not be sheared. + // For elements that should not be sheared. new Container { Anchor = Anchor.CentreLeft, @@ -105,7 +105,7 @@ namespace osu.Game.Screens.Select.FooterV2 AutoSizeAxes = Axes.Both, Child = text = new OsuSpriteText { - //figma design says the size is 16, but due to the issues with font sizes 19 matches better + // figma design says the size is 16, but due to the issues with font sizes 19 matches better Font = OsuFont.TorusAlternate.With(size: 19), AlwaysPresent = true } From 554f14151cf69d63379e38b0c301180ad687a2e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Feb 2023 17:13:24 +0900 Subject: [PATCH 046/154] Apply NRT to `EditorChangeHandler` --- osu.Game/Screens/Edit/EditorChangeHandler.cs | 4 +--- osu.Game/Screens/Edit/TransactionalCommitComponent.cs | 8 +++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorChangeHandler.cs b/osu.Game/Screens/Edit/EditorChangeHandler.cs index 964b86cad3..fd954b309c 100644 --- a/osu.Game/Screens/Edit/EditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/EditorChangeHandler.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.IO; @@ -23,7 +21,7 @@ namespace osu.Game.Screens.Edit public readonly Bindable CanUndo = new Bindable(); public readonly Bindable CanRedo = new Bindable(); - public event Action OnStateChange; + public event Action? OnStateChange; private readonly LegacyEditorBeatmapPatcher patcher; private readonly List savedStates = new List(); diff --git a/osu.Game/Screens/Edit/TransactionalCommitComponent.cs b/osu.Game/Screens/Edit/TransactionalCommitComponent.cs index 55c9cf86c3..f8362523f1 100644 --- a/osu.Game/Screens/Edit/TransactionalCommitComponent.cs +++ b/osu.Game/Screens/Edit/TransactionalCommitComponent.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Graphics; @@ -16,17 +14,17 @@ namespace osu.Game.Screens.Edit /// /// Fires whenever a transaction begins. Will not fire on nested transactions. /// - public event Action TransactionBegan; + public event Action? TransactionBegan; /// /// Fires when the last transaction completes. /// - public event Action TransactionEnded; + public event Action? TransactionEnded; /// /// Fires when is called and results in a non-transactional state save. /// - public event Action SaveStateTriggered; + public event Action? SaveStateTriggered; public bool TransactionActive => bulkChangesStarted > 0; From 94d2799b906a80f7131623f8478bd01dc60aba4b Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 3 Feb 2023 00:47:10 -0800 Subject: [PATCH 047/154] Fix comments having too much padding at the bottom --- osu.Game/Overlays/Comments/DrawableComment.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 4cc189f3a2..52a207afcd 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -76,6 +76,7 @@ namespace osu.Game.Overlays.Comments private GridContainer content = null!; private VotePill votePill = null!; private Container replyEditorContainer = null!; + private Container repliesButtonContainer = null!; [Resolved] private IDialogOverlay? dialogOverlay { get; set; } @@ -239,10 +240,12 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Padding = new MarginPadding { Top = 10 }, + Alpha = 0, }, - new Container + repliesButtonContainer = new Container { AutoSizeAxes = Axes.Both, + Alpha = 0, Children = new Drawable[] { showRepliesButton = new ShowRepliesButton(Comment.RepliesCount) @@ -449,6 +452,7 @@ namespace osu.Game.Overlays.Comments { if (replyEditorContainer.Count == 0) { + replyEditorContainer.Show(); replyEditorContainer.Add(new ReplyCommentEditor(Comment) { OnPost = comments => @@ -462,6 +466,7 @@ namespace osu.Game.Overlays.Comments else { replyEditorContainer.Clear(true); + replyEditorContainer.Hide(); } } @@ -513,9 +518,11 @@ namespace osu.Game.Overlays.Comments int loadedRepliesCount = loadedReplies.Count; bool hasUnloadedReplies = loadedRepliesCount != Comment.RepliesCount; - loadRepliesButton.FadeTo(hasUnloadedReplies && loadedRepliesCount == 0 ? 1 : 0); - showMoreButton.FadeTo(hasUnloadedReplies && loadedRepliesCount > 0 ? 1 : 0); showRepliesButton.FadeTo(loadedRepliesCount != 0 ? 1 : 0); + loadRepliesButton.FadeTo(hasUnloadedReplies && loadedRepliesCount == 0 ? 1 : 0); + repliesButtonContainer.FadeTo(showRepliesButton.IsPresent || loadRepliesButton.IsPresent ? 1 : 0); + + showMoreButton.FadeTo(hasUnloadedReplies && loadedRepliesCount > 0 ? 1 : 0); if (Comment.IsTopLevel) chevronButton.FadeTo(loadedRepliesCount != 0 ? 1 : 0); From 3345e345441db6f089682b1bbb07b1be791fd384 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Feb 2023 17:53:54 +0900 Subject: [PATCH 048/154] Move beatmap specific logic out of `EditorChangeHandler` --- ...t.cs => BeatmapEditorChangeHandlerTest.cs} | 6 +-- .../Edit/BeatmapEditorChangeHandler.cs | 43 +++++++++++++++++++ osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/EditorChangeHandler.cs | 36 ++++------------ 4 files changed, 54 insertions(+), 33 deletions(-) rename osu.Game.Tests/Editing/{EditorChangeHandlerTest.cs => BeatmapEditorChangeHandlerTest.cs} (97%) create mode 100644 osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs diff --git a/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs b/osu.Game.Tests/Editing/BeatmapEditorChangeHandlerTest.cs similarity index 97% rename from osu.Game.Tests/Editing/EditorChangeHandlerTest.cs rename to osu.Game.Tests/Editing/BeatmapEditorChangeHandlerTest.cs index e1accd5b5f..4746f84fa0 100644 --- a/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs +++ b/osu.Game.Tests/Editing/BeatmapEditorChangeHandlerTest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Beatmaps; @@ -12,7 +10,7 @@ using osu.Game.Screens.Edit; namespace osu.Game.Tests.Editing { [TestFixture] - public class EditorChangeHandlerTest + public class BeatmapEditorChangeHandlerTest { private int stateChangedFired; @@ -169,7 +167,7 @@ namespace osu.Game.Tests.Editing }, }); - var changeHandler = new EditorChangeHandler(beatmap); + var changeHandler = new BeatmapEditorChangeHandler(beatmap); changeHandler.OnStateChange += () => stateChangedFired++; return (changeHandler, beatmap); diff --git a/osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs b/osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs new file mode 100644 index 0000000000..b9349a31af --- /dev/null +++ b/osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs @@ -0,0 +1,43 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using System.Text; +using osu.Game.Beatmaps.Formats; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Screens.Edit +{ + public partial class BeatmapEditorChangeHandler : EditorChangeHandler + { + private readonly LegacyEditorBeatmapPatcher patcher; + private readonly EditorBeatmap editorBeatmap; + + /// + /// Creates a new . + /// + /// The to track the s of. + public BeatmapEditorChangeHandler(EditorBeatmap editorBeatmap) + { + this.editorBeatmap = editorBeatmap; + + editorBeatmap.TransactionBegan += BeginChange; + editorBeatmap.TransactionEnded += EndChange; + editorBeatmap.SaveStateTriggered += SaveState; + + patcher = new LegacyEditorBeatmapPatcher(editorBeatmap); + + // Initial state. + SaveState(); + } + + protected override void WriteCurrentStateToStream(MemoryStream stream) + { + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + new LegacyBeatmapEncoder(editorBeatmap, editorBeatmap.BeatmapSkin).Encode(sw); + } + + protected override void ApplyStateChange(byte[] previousState, byte[] newState) => + patcher.Patch(previousState, newState); + } +} diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 74ea933255..0622cbebae 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -240,7 +240,7 @@ namespace osu.Game.Screens.Edit if (canSave) { - changeHandler = new EditorChangeHandler(editorBeatmap); + changeHandler = new BeatmapEditorChangeHandler(editorBeatmap); dependencies.CacheAs(changeHandler); } diff --git a/osu.Game/Screens/Edit/EditorChangeHandler.cs b/osu.Game/Screens/Edit/EditorChangeHandler.cs index fd954b309c..0391da6d86 100644 --- a/osu.Game/Screens/Edit/EditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/EditorChangeHandler.cs @@ -5,25 +5,21 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Game.Beatmaps.Formats; -using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Edit { /// /// Tracks changes to the . /// - public partial class EditorChangeHandler : TransactionalCommitComponent, IEditorChangeHandler + public abstract partial class EditorChangeHandler : TransactionalCommitComponent, IEditorChangeHandler { public readonly Bindable CanUndo = new Bindable(); public readonly Bindable CanRedo = new Bindable(); public event Action? OnStateChange; - private readonly LegacyEditorBeatmapPatcher patcher; private readonly List savedStates = new List(); private int currentState = -1; @@ -40,29 +36,10 @@ namespace osu.Game.Screens.Edit } } - private readonly EditorBeatmap editorBeatmap; private bool isRestoring; public const int MAX_SAVED_STATES = 50; - /// - /// Creates a new . - /// - /// The to track the s of. - public EditorChangeHandler(EditorBeatmap editorBeatmap) - { - this.editorBeatmap = editorBeatmap; - - editorBeatmap.TransactionBegan += BeginChange; - editorBeatmap.TransactionEnded += EndChange; - editorBeatmap.SaveStateTriggered += SaveState; - - patcher = new LegacyEditorBeatmapPatcher(editorBeatmap); - - // Initial state. - SaveState(); - } - protected override void UpdateState() { if (isRestoring) @@ -70,9 +47,7 @@ namespace osu.Game.Screens.Edit using (var stream = new MemoryStream()) { - using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) - new LegacyBeatmapEncoder(editorBeatmap, editorBeatmap.BeatmapSkin).Encode(sw); - + WriteCurrentStateToStream(stream); byte[] newState = stream.ToArray(); // if the previous state is binary equal we don't need to push a new one, unless this is the initial state. @@ -111,7 +86,8 @@ namespace osu.Game.Screens.Edit isRestoring = true; - patcher.Patch(savedStates[currentState], savedStates[newState]); + ApplyStateChange(savedStates[currentState], savedStates[newState]); + currentState = newState; isRestoring = false; @@ -120,6 +96,10 @@ namespace osu.Game.Screens.Edit updateBindables(); } + protected abstract void WriteCurrentStateToStream(MemoryStream stream); + + protected abstract void ApplyStateChange(byte[] previousState, byte[] newState); + private void updateBindables() { CanUndo.Value = savedStates.Count > 0 && currentState > 0; From 2f30306ea204dfe8809ff0cb26effe6284a0d41a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Feb 2023 18:53:09 +0900 Subject: [PATCH 049/154] Expose a method to reload a `SkinnableTargetContainer` from provided info --- osu.Game/Skinning/ISkinnableTarget.cs | 5 ++++ osu.Game/Skinning/SkinnableTargetContainer.cs | 27 +++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/osu.Game/Skinning/ISkinnableTarget.cs b/osu.Game/Skinning/ISkinnableTarget.cs index 57c78bfe1c..70b80f3fed 100644 --- a/osu.Game/Skinning/ISkinnableTarget.cs +++ b/osu.Game/Skinning/ISkinnableTarget.cs @@ -36,6 +36,11 @@ namespace osu.Game.Skinning /// void Reload(); + /// + /// Reload this target from the provided skinnable information. + /// + public void Reload(SkinnableInfo[] skinnableInfo); + /// /// Add a new skinnable component to this target. /// diff --git a/osu.Game/Skinning/SkinnableTargetContainer.cs b/osu.Game/Skinning/SkinnableTargetContainer.cs index 794a12da82..df5299d427 100644 --- a/osu.Game/Skinning/SkinnableTargetContainer.cs +++ b/osu.Game/Skinning/SkinnableTargetContainer.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Screens.Play.HUD; namespace osu.Game.Skinning { @@ -30,16 +32,31 @@ namespace osu.Game.Skinning Target = target; } - /// - /// Reload all components in this container from the current skin. - /// - public void Reload() + public void Reload(SkinnableInfo[] skinnableInfo) + { + var drawables = new List(); + + foreach (var i in skinnableInfo) + drawables.Add(i.CreateInstance()); + + Reload(new SkinnableTargetComponentsContainer + { + Children = drawables, + }); + } + + public void Reload() => Reload(CurrentSkin.GetDrawableComponent(new GlobalSkinComponentLookup(Target)) as SkinnableTargetComponentsContainer); + + public void Reload(SkinnableTargetComponentsContainer? componentsContainer) { ClearInternal(); components.Clear(); ComponentsLoaded = false; - content = CurrentSkin.GetDrawableComponent(new GlobalSkinComponentLookup(Target)) as SkinnableTargetComponentsContainer; + if (componentsContainer == null) + return; + + content = componentsContainer; cancellationSource?.Cancel(); cancellationSource = null; From 2cda277c091b05f20f4774b5b7eb48f5f0a778f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Feb 2023 18:53:22 +0900 Subject: [PATCH 050/154] Add a basic change handler to the skin editor --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 52 ++++++++++++- .../SkinEditor/SkinEditorChangeHandler.cs | 73 +++++++++++++++++++ osu.Game/Screens/Edit/IEditorChangeHandler.cs | 6 +- 3 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 275cbd18d7..51cca96f4a 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -24,6 +24,7 @@ using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Overlays.OSD; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Skinning; @@ -31,7 +32,7 @@ using osu.Game.Skinning; namespace osu.Game.Overlays.SkinEditor { [Cached(typeof(SkinEditor))] - public partial class SkinEditor : VisibilityContainer, ICanAcceptFiles, IKeyBindingHandler + public partial class SkinEditor : VisibilityContainer, ICanAcceptFiles, IKeyBindingHandler, IEditorChangeHandler { public const double TRANSITION_DURATION = 300; @@ -72,6 +73,11 @@ namespace osu.Game.Overlays.SkinEditor private EditorSidebar componentsSidebar = null!; private EditorSidebar settingsSidebar = null!; + private SkinEditorChangeHandler? changeHandler; + + private EditorMenuItem undoMenuItem = null!; + private EditorMenuItem redoMenuItem = null!; + [Resolved] private OnScreenDisplay? onScreenDisplay { get; set; } @@ -131,6 +137,14 @@ namespace osu.Game.Overlays.SkinEditor new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, () => skinEditorOverlay?.Hide()), }, }, + new MenuItem(CommonStrings.MenuBarEdit) + { + Items = new[] + { + undoMenuItem = new EditorMenuItem(CommonStrings.Undo, MenuItemType.Standard, Undo), + redoMenuItem = new EditorMenuItem(CommonStrings.Redo, MenuItemType.Standard, Redo), + } + }, } }, headerText = new OsuTextFlowContainer @@ -210,6 +224,14 @@ namespace osu.Game.Overlays.SkinEditor { switch (e.Action) { + case PlatformAction.Undo: + Undo(); + return true; + + case PlatformAction.Redo: + Redo(); + return true; + case PlatformAction.Save: if (e.Repeat) return false; @@ -229,6 +251,8 @@ namespace osu.Game.Overlays.SkinEditor { this.targetScreen = targetScreen; + changeHandler?.Dispose(); + SelectedComponents.Clear(); // Immediately clear the previous blueprint container to ensure it doesn't try to interact with the old target. @@ -241,6 +265,10 @@ namespace osu.Game.Overlays.SkinEditor { Debug.Assert(content != null); + changeHandler = new SkinEditorChangeHandler(targetScreen); + changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true); + changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true); + content.Child = new SkinBlueprintContainer(targetScreen); componentsSidebar.Child = new SkinComponentToolbox(getFirstTarget() as CompositeDrawable) @@ -301,6 +329,8 @@ namespace osu.Game.Overlays.SkinEditor SelectedComponents.Clear(); SelectedComponents.Add(component); + + changeHandler?.SaveState(); } private void populateSettings() @@ -333,6 +363,10 @@ namespace osu.Game.Overlays.SkinEditor } } + protected void Undo() => changeHandler?.RestoreState(-1); + + protected void Redo() => changeHandler?.RestoreState(1); + public void Save() { if (!hasBegunMutating) @@ -371,6 +405,8 @@ namespace osu.Game.Overlays.SkinEditor { foreach (var item in items) availableTargets.FirstOrDefault(t => t.Components.Contains(item))?.Remove(item); + + changeHandler?.SaveState(); } #region Drag & drop import handling @@ -435,5 +471,19 @@ namespace osu.Game.Overlays.SkinEditor { } } + + #region Delegation of IEditorChangeHandler + + public event Action? OnStateChange + { + add => changeHandler!.OnStateChange += value; + remove => changeHandler!.OnStateChange -= value; + } + + public void BeginChange() => changeHandler?.BeginChange(); + public void EndChange() => changeHandler?.EndChange(); + public void SaveState() => changeHandler?.SaveState(); + + #endregion } } diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs new file mode 100644 index 0000000000..95b24bbd6f --- /dev/null +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -0,0 +1,73 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Newtonsoft.Json; +using osu.Framework.Graphics; +using osu.Framework.Testing; +using osu.Game.Extensions; +using osu.Game.Screens.Edit; +using osu.Game.Screens.Play.HUD; +using osu.Game.Skinning; + +namespace osu.Game.Overlays.SkinEditor +{ + public partial class SkinEditorChangeHandler : EditorChangeHandler + { + private readonly Drawable targetScreen; + + private ISkinnableTarget? firstTarget => targetScreen.ChildrenOfType().FirstOrDefault(); + + public SkinEditorChangeHandler(Drawable targetScreen) + { + // To keep things simple, we are currently only handling the current target screen for undo / redo. + // In the future we'll want this to cover all changes, even to skin's `InstantiationInfo`. + // We'll also need to consider cases where multiple targets are on screen at the same time. + + this.targetScreen = targetScreen; + + // Save initial state. + SaveState(); + } + + protected override void WriteCurrentStateToStream(MemoryStream stream) + { + if (firstTarget == null) + return; + + var skinnableInfos = firstTarget.CreateSkinnableInfo().ToArray(); + string json = JsonConvert.SerializeObject(skinnableInfos, new JsonSerializerSettings { Formatting = Formatting.Indented }); + stream.Write(Encoding.UTF8.GetBytes(json)); + } + + protected override void ApplyStateChange(byte[] previousState, byte[] newState) + { + if (firstTarget == null) + return; + + var deserializedContent = JsonConvert.DeserializeObject>(Encoding.UTF8.GetString(newState)); + + if (deserializedContent == null) + return; + + SkinnableInfo[] skinnableInfo = deserializedContent.ToArray(); + Drawable[] targetComponents = firstTarget.Components.OfType().ToArray(); + + if (!skinnableInfo.Select(s => s.Type).SequenceEqual(targetComponents.Select(d => d.GetType()))) + { + // Perform a naive full reload for now. + firstTarget.Reload(skinnableInfo); + } + else + { + int i = 0; + + foreach (var drawable in targetComponents) + drawable.ApplySkinnableInfo(skinnableInfo[i++]); + } + } + } +} diff --git a/osu.Game/Screens/Edit/IEditorChangeHandler.cs b/osu.Game/Screens/Edit/IEditorChangeHandler.cs index e7abc1c43d..9fe40ba1b1 100644 --- a/osu.Game/Screens/Edit/IEditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/IEditorChangeHandler.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; +using osu.Framework.Allocation; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Edit @@ -11,12 +10,13 @@ namespace osu.Game.Screens.Edit /// /// Interface for a component that manages changes in the . /// + [Cached] public interface IEditorChangeHandler { /// /// Fired whenever a state change occurs. /// - event Action OnStateChange; + event Action? OnStateChange; /// /// Begins a bulk state change event. should be invoked soon after. From 461b5c537571d29f1046215030a43fe1907c9705 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 3 Feb 2023 00:48:32 -0800 Subject: [PATCH 051/154] Fix comment cancel button not behaving the same as reply text toggle - Removed the fading animation as it is awkward right now (needs resizing) --- osu.Game/Overlays/Comments/DrawableComment.cs | 3 ++- osu.Game/Overlays/Comments/ReplyCommentEditor.cs | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 52a207afcd..869ed61a9c 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -460,7 +460,8 @@ namespace osu.Game.Overlays.Comments Comment.RepliesCount += comments.Length; showRepliesButton.Count = Comment.RepliesCount; Replies.AddRange(comments); - } + }, + OnCancel = toggleReply }); } else diff --git a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs index e738e6e7ec..8aca183dee 100644 --- a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs +++ b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Online.API; @@ -33,7 +32,6 @@ namespace osu.Game.Overlays.Comments public ReplyCommentEditor(Comment parent) { parentComment = parent; - OnCancel = () => this.FadeOut(200).Expire(); } protected override void LoadComplete() From 8c11e8e6f4994342f466ab1b5228c3d923b50d94 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Fri, 3 Feb 2023 11:58:10 +0100 Subject: [PATCH 052/154] Extract ShearedNub.cs implementation into its own entirely independent implementation --- osu.Game/Graphics/UserInterface/ShearedNub.cs | 155 +++++++++++++++++- 1 file changed, 150 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedNub.cs b/osu.Game/Graphics/UserInterface/ShearedNub.cs index 6bee4fc3b7..390d6ff9be 100644 --- a/osu.Game/Graphics/UserInterface/ShearedNub.cs +++ b/osu.Game/Graphics/UserInterface/ShearedNub.cs @@ -1,26 +1,41 @@ // 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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Overlays; using osuTK; +using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public partial class ShearedNub : Nub + public partial class ShearedNub : Container, IHasCurrentValue, IHasAccentColour { + protected const float BORDER_WIDTH = 3; + public const int HEIGHT = 30; public const float EXPANDED_SIZE = 50; public static readonly Vector2 SHEAR = new Vector2(0.15f, 0); + private readonly Box fill; + private readonly Container main; + + /// + /// Implements the shape for the nub, allowing for any type of container to be used. + /// + /// public ShearedNub() { Size = new Vector2(EXPANDED_SIZE, HEIGHT); - } - - protected override Container CreateNubContainer() => - new Container + InternalChild = main = new Container { Shear = SHEAR, BorderColour = Colour4.White, @@ -30,6 +45,136 @@ namespace osu.Game.Graphics.UserInterface RelativeSizeAxes = Axes.Both, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Child = fill = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + } }; + } + + [BackgroundDependencyLoader(true)] + private void load(OverlayColourProvider? colourProvider, OsuColour colours) + { + AccentColour = colourProvider?.Highlight1 ?? colours.Pink; + GlowingAccentColour = colourProvider?.Highlight1.Lighten(0.2f) ?? colours.PinkLighter; + GlowColour = colourProvider?.Highlight1 ?? colours.PinkLighter; + + main.EdgeEffect = new EdgeEffectParameters + { + Colour = GlowColour.Opacity(0), + Type = EdgeEffectType.Glow, + Radius = 8, + Roundness = 4, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(onCurrentValueChanged, true); + } + + private bool glowing; + + public bool Glowing + { + get => glowing; + set + { + glowing = value; + + if (value) + { + main.FadeColour(GlowingAccentColour.Lighten(0.5f), 40, Easing.OutQuint) + .Then() + .FadeColour(GlowingAccentColour, 800, Easing.OutQuint); + + main.FadeEdgeEffectTo(Color4.White.Opacity(0.1f), 40, Easing.OutQuint) + .Then() + .FadeEdgeEffectTo(GlowColour.Opacity(0.1f), 800, Easing.OutQuint); + } + else + { + main.FadeEdgeEffectTo(GlowColour.Opacity(0), 800, Easing.OutQuint); + main.FadeColour(AccentColour, 800, Easing.OutQuint); + } + } + } + + private readonly Bindable current = new Bindable(); + + public Bindable Current + { + get => current; + set + { + ArgumentNullException.ThrowIfNull(value); + + current.UnbindBindings(); + current.BindTo(value); + } + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + if (!Glowing) + main.Colour = value; + } + } + + private Color4 glowingAccentColour; + + public Color4 GlowingAccentColour + { + get => glowingAccentColour; + set + { + glowingAccentColour = value; + if (Glowing) + main.Colour = value; + } + } + + private Color4 glowColour; + + public Color4 GlowColour + { + get => glowColour; + set + { + glowColour = value; + + var effect = main.EdgeEffect; + effect.Colour = Glowing ? value : value.Opacity(0); + main.EdgeEffect = effect; + } + } + + private void onCurrentValueChanged(ValueChangedEvent filled) + { + const double duration = 200; + + fill.FadeTo(filled.NewValue ? 1 : 0, duration, Easing.OutQuint); + + if (filled.NewValue) + { + main.ResizeWidthTo(1, duration, Easing.OutElasticHalf); + main.TransformTo(nameof(BorderThickness), 8.5f, duration, Easing.OutElasticHalf); + } + else + { + main.ResizeWidthTo(0.75f, duration, Easing.OutQuint); + main.TransformTo(nameof(BorderThickness), BORDER_WIDTH, duration, Easing.OutQuint); + } + } } } From e1af5e110aa20f823daa29c959e2159ae15a4443 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Fri, 3 Feb 2023 12:19:09 +0100 Subject: [PATCH 053/154] Remove ```RoundedNub.cs``` and make ```Nub.cs``` non abstract again --- .../UserInterface/TestSceneRangeSlider.cs | 2 +- osu.Game/Graphics/UserInterface/Nub.cs | 48 ++++++++++++------- .../Graphics/UserInterface/OsuCheckbox.cs | 8 ++-- .../Graphics/UserInterface/RangeSlider.cs | 2 +- osu.Game/Graphics/UserInterface/RoundedNub.cs | 32 ------------- .../UserInterface/RoundedSliderBar.cs | 8 ++-- 6 files changed, 41 insertions(+), 59 deletions(-) delete mode 100644 osu.Game/Graphics/UserInterface/RoundedNub.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs index 1b91459615..b780764e7f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.UserInterface LowerBound = customStart, UpperBound = customEnd, TooltipSuffix = "suffix", - NubWidth = RoundedNub.HEIGHT * 2, + NubWidth = Nub.HEIGHT * 2, DefaultStringLowerBound = "Start", DefaultStringUpperBound = "End", MinRange = 10 diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 6f875e8594..28a2eb40c3 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osuTK; +using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -11,33 +13,45 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Overlays; -using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public abstract partial class Nub : Container, IHasCurrentValue, IHasAccentColour + public partial class Nub : Container, IHasCurrentValue, IHasAccentColour { - protected const float BORDER_WIDTH = 3; + public const float HEIGHT = 15; + + public const float EXPANDED_SIZE = 50; + + private const float border_width = 3; private readonly Box fill; private readonly Container main; - /// - /// Implements the shape for the nub, allowing for any type of container to be used. - /// - /// - protected abstract Container CreateNubContainer(); - - protected Nub() + public Nub() { - InternalChild = main = CreateNubContainer(); + Size = new Vector2(EXPANDED_SIZE, HEIGHT); - main.Add(fill = new Box + InternalChildren = new[] { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - }); + main = new CircularContainer + { + BorderColour = Color4.White, + BorderThickness = border_width, + Masking = true, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Children = new Drawable[] + { + fill = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }, + } + }, + }; } [BackgroundDependencyLoader(true)] @@ -159,7 +173,7 @@ namespace osu.Game.Graphics.UserInterface else { main.ResizeWidthTo(0.75f, duration, Easing.OutQuint); - main.TransformTo(nameof(BorderThickness), BORDER_WIDTH, duration, Easing.OutQuint); + main.TransformTo(nameof(BorderThickness), border_width, duration, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 2fae4e2cb5..160105af1a 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface } } - protected readonly RoundedNub Nub; + protected readonly Nub Nub; protected readonly OsuTextFlowContainer LabelTextFlowContainer; private Sample sampleChecked; @@ -61,7 +61,7 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, }, - Nub = new RoundedNub(), + Nub = new Nub(), new HoverSounds() }; @@ -70,14 +70,14 @@ namespace osu.Game.Graphics.UserInterface Nub.Anchor = Anchor.CentreRight; Nub.Origin = Anchor.CentreRight; Nub.Margin = new MarginPadding { Right = nub_padding }; - LabelTextFlowContainer.Padding = new MarginPadding { Right = RoundedNub.EXPANDED_SIZE + nub_padding * 2 }; + LabelTextFlowContainer.Padding = new MarginPadding { Right = Nub.EXPANDED_SIZE + nub_padding * 2 }; } else { Nub.Anchor = Anchor.CentreLeft; Nub.Origin = Anchor.CentreLeft; Nub.Margin = new MarginPadding { Left = nub_padding }; - LabelTextFlowContainer.Padding = new MarginPadding { Left = RoundedNub.EXPANDED_SIZE + nub_padding * 2 }; + LabelTextFlowContainer.Padding = new MarginPadding { Left = Nub.EXPANDED_SIZE + nub_padding * 2 }; } Nub.Current.BindTo(Current); diff --git a/osu.Game/Graphics/UserInterface/RangeSlider.cs b/osu.Game/Graphics/UserInterface/RangeSlider.cs index 575327b50b..f83dff6295 100644 --- a/osu.Game/Graphics/UserInterface/RangeSlider.cs +++ b/osu.Game/Graphics/UserInterface/RangeSlider.cs @@ -163,7 +163,7 @@ namespace osu.Game.Graphics.UserInterface public string? DefaultString; public LocalisableString? DefaultTooltip; public string? TooltipSuffix; - public float NubWidth { get; set; } = RoundedNub.HEIGHT; + public float NubWidth { get; set; } = Nub.HEIGHT; public override LocalisableString TooltipText => (Current.IsDefault ? DefaultTooltip : Current.Value.ToString($@"0.## {TooltipSuffix}")) ?? Current.Value.ToString($@"0.## {TooltipSuffix}"); diff --git a/osu.Game/Graphics/UserInterface/RoundedNub.cs b/osu.Game/Graphics/UserInterface/RoundedNub.cs deleted file mode 100644 index 3bdfadfe22..0000000000 --- a/osu.Game/Graphics/UserInterface/RoundedNub.cs +++ /dev/null @@ -1,32 +0,0 @@ -// 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.Graphics; -using osu.Framework.Graphics.Containers; -using osuTK; - -namespace osu.Game.Graphics.UserInterface -{ - public partial class RoundedNub : Nub - { - public const float HEIGHT = 15; - - public const float EXPANDED_SIZE = 50; - - public RoundedNub() - { - Size = new Vector2(EXPANDED_SIZE, HEIGHT); - } - - protected override Container CreateNubContainer() => - new CircularContainer - { - BorderColour = Colour4.White, - BorderThickness = BORDER_WIDTH, - Masking = true, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }; - } -} diff --git a/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs b/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs index 765e1d5105..a666b83c05 100644 --- a/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/RoundedSliderBar.cs @@ -17,7 +17,7 @@ namespace osu.Game.Graphics.UserInterface public partial class RoundedSliderBar : OsuSliderBar where T : struct, IEquatable, IComparable, IConvertible { - protected readonly RoundedNub Nub; + protected readonly Nub Nub; protected readonly Box LeftBox; protected readonly Box RightBox; private readonly Container nubContainer; @@ -50,8 +50,8 @@ namespace osu.Game.Graphics.UserInterface public RoundedSliderBar() { - Height = RoundedNub.HEIGHT; - RangePadding = RoundedNub.EXPANDED_SIZE / 2; + Height = Nub.HEIGHT; + RangePadding = Nub.EXPANDED_SIZE / 2; Children = new Drawable[] { new Container @@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface nubContainer = new Container { RelativeSizeAxes = Axes.Both, - Child = Nub = new RoundedNub + Child = Nub = new Nub { Origin = Anchor.TopCentre, RelativePositionAxes = Axes.X, From f9809c948120ddccb36bd6e790e223b1503abe44 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Fri, 3 Feb 2023 11:48:11 -0300 Subject: [PATCH 054/154] the comment --- osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs index ce1b0db76d..4e17627e04 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadge.cs @@ -54,6 +54,8 @@ namespace osu.Game.Overlays.Profile.Header.Components RelativeSizeAxes = Axes.Both, Colour = colourProvider?.Background6 ?? Colour4.Black, // Normal badges background opacity is 75%, probationary is full opacity as the whole badge gets a bit transparent + // Goal is to match osu-web so this is the most accurate it can be, its a bit scuffed but it is what it is + // Source: https://github.com/ppy/osu-web/blob/master/resources/css/bem/user-group-badge.less#L50 Alpha = group.IsProbationary ? 1 : 0.75f, }, innerContainer = new FillFlowContainer From cb8458cceb6e79ad4fc6920d580e4168df607000 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 4 Feb 2023 20:11:29 -0800 Subject: [PATCH 055/154] Use linq and alpha instead MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 869ed61a9c..c9eb80f676 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -521,7 +521,7 @@ namespace osu.Game.Overlays.Comments showRepliesButton.FadeTo(loadedRepliesCount != 0 ? 1 : 0); loadRepliesButton.FadeTo(hasUnloadedReplies && loadedRepliesCount == 0 ? 1 : 0); - repliesButtonContainer.FadeTo(showRepliesButton.IsPresent || loadRepliesButton.IsPresent ? 1 : 0); + repliesButtonContainer.FadeTo(repliesButtonContainer.Any(child => child.Alpha > 0) ? 1 : 0); showMoreButton.FadeTo(hasUnloadedReplies && loadedRepliesCount > 0 ? 1 : 0); From d5b2d9ce9722c3127d4252e4b6b92388f758ba03 Mon Sep 17 00:00:00 2001 From: tsrk Date: Sun, 5 Feb 2023 23:58:08 +0000 Subject: [PATCH 056/154] feat: add support for spectating status --- osu.Game/Screens/Play/SoloSpectatorPlayer.cs | 3 +++ osu.Game/Users/UserActivity.cs | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index 240fbcf662..bd9e3917a5 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Online.Spectator; using osu.Game.Scoring; +using osu.Game.Users; namespace osu.Game.Screens.Play { @@ -14,6 +15,8 @@ namespace osu.Game.Screens.Play { private readonly Score score; + protected override UserActivity InitialActivity => new UserActivity.Spectating(score.ScoreInfo.User); + public SoloSpectatorPlayer(Score score, PlayerConfiguration configuration = null) : base(score, configuration) { diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 6de797ca3a..950c486f22 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -5,6 +5,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osuTK.Graphics; @@ -92,7 +93,14 @@ namespace osu.Game.Users public class Spectating : UserActivity { - public override string Status => @"Spectating a game"; + private readonly APIUser user; + + public Spectating(APIUser user) + { + this.user = user; + } + + public override string Status => @$"Spectating {user.Username}"; } public class SearchingForLobby : UserActivity From bf273597ea726ef7d493b8db17889b9f0c93561c Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Feb 2023 00:41:10 +0000 Subject: [PATCH 057/154] feat: actually support status also for Replays --- osu.Game/Screens/Play/ReplayPlayer.cs | 3 +++ osu.Game/Screens/Play/SoloSpectatorPlayer.cs | 2 +- osu.Game/Users/UserActivity.cs | 16 ++++++++-------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index c5ef6b1585..e2b8ad7011 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Ranking; +using osu.Game.Users; namespace osu.Game.Screens.Play { @@ -24,6 +25,8 @@ namespace osu.Game.Screens.Play private readonly bool replayIsFailedScore; + protected override UserActivity InitialActivity => new UserActivity.Watching(); + // Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108) protected override bool CheckModsAllowFailure() { diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index bd9e3917a5..65b66166c0 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Play { private readonly Score score; - protected override UserActivity InitialActivity => new UserActivity.Spectating(score.ScoreInfo.User); + protected override UserActivity InitialActivity => new UserActivity.Spectating(); public SoloSpectatorPlayer(Score score, PlayerConfiguration configuration = null) : base(score, configuration) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 950c486f22..d652730621 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -5,7 +5,6 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osuTK.Graphics; @@ -91,16 +90,17 @@ namespace osu.Game.Users public override string Status => @"Editing a beatmap"; } - public class Spectating : UserActivity + public class Watching : UserActivity { - private readonly APIUser user; + protected virtual string Verb => @"Watching"; - public Spectating(APIUser user) - { - this.user = user; - } + public override string Status => @$"{Verb} a game"; + } - public override string Status => @$"Spectating {user.Username}"; + public class Spectating : Watching + { + protected override string Verb => @"Spectating"; + public override string Status => @$"{Verb} a game"; } public class SearchingForLobby : UserActivity From e878bb42a4670796186cd5c926cea35cf1b36039 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Feb 2023 00:53:56 +0000 Subject: [PATCH 058/154] test: add test for watching activity --- osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 4c1df850b2..eaf2ca5ac0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -107,6 +107,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("set online status", () => status.Value = new UserStatusOnline()); AddStep("idle", () => activity.Value = null); + AddStep("watching", () => activity.Value = new UserActivity.Watching()); AddStep("spectating", () => activity.Value = new UserActivity.Spectating()); AddStep("solo (osu!)", () => activity.Value = soloGameStatusForRuleset(0)); AddStep("solo (osu!taiko)", () => activity.Value = soloGameStatusForRuleset(1)); From b3f38b0f4c463c147dc3a646fe02f6270e597283 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Feb 2023 00:56:11 +0000 Subject: [PATCH 059/154] quality: remove redundant `Status` override --- osu.Game/Users/UserActivity.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index d652730621..37b5a2bf1e 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -100,7 +100,6 @@ namespace osu.Game.Users public class Spectating : Watching { protected override string Verb => @"Spectating"; - public override string Status => @$"{Verb} a game"; } public class SearchingForLobby : UserActivity From 701d21c26fd8cc2d9c14a35de25027a7a003caca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 13:52:25 +0900 Subject: [PATCH 060/154] Apply single inspection from newer inspectcode verisons As found in rider EAPs. Appears as a warning and is annoying me occasionally. --- osu.Game/Overlays/ChatOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index c539cdc5ec..b44c7c48f5 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -315,10 +315,10 @@ namespace osu.Game.Overlays channelListing.Hide(); textBar.ShowSearch.Value = false; - if (loadedChannels.ContainsKey(newChannel)) + if (loadedChannels.TryGetValue(newChannel, out var loadedChannel)) { currentChannelContainer.Clear(false); - currentChannelContainer.Add(loadedChannels[newChannel]); + currentChannelContainer.Add(loadedChannel); } else { From e4b17588f52361048a05fea72203e69d97c653ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 14:11:40 +0900 Subject: [PATCH 061/154] Add missing xmldoc to new methods in `EditorChangeHandler` --- osu.Game/Screens/Edit/EditorChangeHandler.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Screens/Edit/EditorChangeHandler.cs b/osu.Game/Screens/Edit/EditorChangeHandler.cs index 0391da6d86..4511b654b6 100644 --- a/osu.Game/Screens/Edit/EditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/EditorChangeHandler.cs @@ -96,8 +96,18 @@ namespace osu.Game.Screens.Edit updateBindables(); } + /// + /// Write a serialised copy of the currently tracked state to the provided stream. + /// This will be stored as a state which can be restored in the future. + /// + /// The stream which the state should be written to. protected abstract void WriteCurrentStateToStream(MemoryStream stream); + /// + /// Given a previous and new state, apply any changes required to bring the current state in line with the new state. + /// + /// The previous (current before this call) serialised state. + /// The new state to be applied. protected abstract void ApplyStateChange(byte[] previousState, byte[] newState); private void updateBindables() From e5f62b0d2e7caa676d983736e496eb0ac377abf0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 14:19:25 +0900 Subject: [PATCH 062/154] Remove `public` access modifier from interface methods --- osu.Game/Skinning/ISkinnableTarget.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/ISkinnableTarget.cs b/osu.Game/Skinning/ISkinnableTarget.cs index 70b80f3fed..3f116f8f76 100644 --- a/osu.Game/Skinning/ISkinnableTarget.cs +++ b/osu.Game/Skinning/ISkinnableTarget.cs @@ -39,7 +39,7 @@ namespace osu.Game.Skinning /// /// Reload this target from the provided skinnable information. /// - public void Reload(SkinnableInfo[] skinnableInfo); + void Reload(SkinnableInfo[] skinnableInfo); /// /// Add a new skinnable component to this target. @@ -51,6 +51,6 @@ namespace osu.Game.Skinning /// Remove an existing skinnable component from this target. /// /// The component to remove. - public void Remove(ISkinnableDrawable component); + void Remove(ISkinnableDrawable component); } } From 7445814fc63ad88964fb9dcaefff3e60069143dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 14:42:59 +0900 Subject: [PATCH 063/154] Handle changes to `SettingSource` skin element settings --- .../SkinEditor/SkinSettingsToolbox.cs | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinSettingsToolbox.cs b/osu.Game/Overlays/SkinEditor/SkinSettingsToolbox.cs index 5a48dee973..a2b9db2665 100644 --- a/osu.Game/Overlays/SkinEditor/SkinSettingsToolbox.cs +++ b/osu.Game/Overlays/SkinEditor/SkinSettingsToolbox.cs @@ -2,10 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Localisation; +using osu.Game.Overlays.Settings; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components; using osuTK; @@ -13,19 +16,41 @@ namespace osu.Game.Overlays.SkinEditor { internal partial class SkinSettingsToolbox : EditorSidebarSection { + [Resolved] + private IEditorChangeHandler? changeHandler { get; set; } + protected override Container Content { get; } + private readonly Drawable component; + public SkinSettingsToolbox(Drawable component) : base(SkinEditorStrings.Settings(component.GetType().Name)) { + this.component = component; + base.Content.Add(Content = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Spacing = new Vector2(10), - Children = component.CreateSettingsControls().ToArray() }); } + + [BackgroundDependencyLoader] + private void load() + { + var controls = component.CreateSettingsControls().ToArray(); + + Content.AddRange(controls); + + // track any changes to update undo states. + foreach (var c in controls.OfType()) + { + // TODO: SettingChanged is called too often for cases like SettingsTextBox and SettingsSlider. + // We will want to expose a SettingCommitted or similar to make this work better. + c.SettingChanged += () => changeHandler?.SaveState(); + } + } } } From 778b8a9bf7f10f2457f39b9d8ea062bfc0fd3a70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 15:00:42 +0900 Subject: [PATCH 064/154] Fix default settings not being serialised / state tracked correctly --- osu.Game/Extensions/DrawableExtensions.cs | 12 +++++++++--- osu.Game/Screens/Play/HUD/SkinnableInfo.cs | 3 +-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Extensions/DrawableExtensions.cs b/osu.Game/Extensions/DrawableExtensions.cs index 65b9e46764..375960305c 100644 --- a/osu.Game/Extensions/DrawableExtensions.cs +++ b/osu.Game/Extensions/DrawableExtensions.cs @@ -66,10 +66,16 @@ namespace osu.Game.Extensions foreach (var (_, property) in component.GetSettingsSourceProperties()) { - if (!info.Settings.TryGetValue(property.Name.ToSnakeCase(), out object? settingValue)) - continue; + var bindable = ((IBindable)property.GetValue(component)!); - skinnable.CopyAdjustedSetting(((IBindable)property.GetValue(component)!), settingValue); + if (!info.Settings.TryGetValue(property.Name.ToSnakeCase(), out object? settingValue)) + { + // TODO: We probably want to restore default if not included in serialisation information. + // This is not simple to do as SetDefault() is only found in the typed Bindable interface right now. + continue; + } + + skinnable.CopyAdjustedSetting(bindable, settingValue); } } diff --git a/osu.Game/Screens/Play/HUD/SkinnableInfo.cs b/osu.Game/Screens/Play/HUD/SkinnableInfo.cs index da759b4329..9fdae50615 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableInfo.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableInfo.cs @@ -69,8 +69,7 @@ namespace osu.Game.Screens.Play.HUD { var bindable = (IBindable)property.GetValue(component)!; - if (!bindable.IsDefault) - Settings.Add(property.Name.ToSnakeCase(), bindable.GetUnderlyingSettingValue()); + Settings.Add(property.Name.ToSnakeCase(), bindable.GetUnderlyingSettingValue()); } if (component is Container container) From 4c868372a2c7fa5259977f015efcbbbc7e73f0d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 15:05:05 +0900 Subject: [PATCH 065/154] Correctly handle anchor/origin changes as undo states --- osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs b/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs index 129b9c1b44..86fcd35e03 100644 --- a/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs @@ -241,6 +241,8 @@ namespace osu.Game.Overlays.SkinEditor private void applyOrigins(Anchor origin) { + OnOperationBegan(); + foreach (var item in SelectedItems) { var drawable = (Drawable)item; @@ -255,6 +257,8 @@ namespace osu.Game.Overlays.SkinEditor ApplyClosestAnchor(drawable); } + + OnOperationEnded(); } /// @@ -266,6 +270,8 @@ namespace osu.Game.Overlays.SkinEditor private void applyFixedAnchors(Anchor anchor) { + OnOperationBegan(); + foreach (var item in SelectedItems) { var drawable = (Drawable)item; @@ -273,15 +279,21 @@ namespace osu.Game.Overlays.SkinEditor item.UsesFixedAnchor = true; applyAnchor(drawable, anchor); } + + OnOperationEnded(); } private void applyClosestAnchors() { + OnOperationBegan(); + foreach (var item in SelectedItems) { item.UsesFixedAnchor = false; ApplyClosestAnchor((Drawable)item); } + + OnOperationEnded(); } private static Anchor getClosestAnchor(Drawable drawable) From 679ec986d5912818dd523ed690c7f14ff9311b52 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 16:39:44 +0900 Subject: [PATCH 066/154] Fix storyboard outro time potentially running too long --- .../Beatmaps/Formats/LegacyStoryboardDecoderTest.cs | 4 +++- osu.Game/Storyboards/CommandLoop.cs | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index d9e80fa111..281ea4e4ff 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -214,7 +214,9 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.That(oneTime.EndTime, Is.EqualTo(4000 + loop_duration)); StoryboardSprite manyTimes = background.Elements.OfType().Single(s => s.Path == "many-times.png"); - Assert.That(manyTimes.EndTime, Is.EqualTo(9000 + 40 * loop_duration)); + // It is intentional that we don't consider the loop count (40) as part of the end time calculation to match stable's handling. + // If we were to include the loop count, storyboards which loop for stupid long loop counts would continue playing the outro forever. + Assert.That(manyTimes.EndTime, Is.EqualTo(9000 + loop_duration)); } } } diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index 0f26ed2c66..29e034d86c 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -18,7 +18,12 @@ namespace osu.Game.Storyboards public readonly int TotalIterations; public override double StartTime => LoopStartTime + CommandsStartTime; - public override double EndTime => StartTime + CommandsDuration * TotalIterations; + + public override double EndTime => + // In an ideal world, we would multiply the command duration by TotalIterations here. + // Unfortunately this would clash with how stable handled end times, and results in some storyboards playing outro + // sequences for minutes or hours. + StartTime + CommandsDuration; /// /// Construct a new command loop. From eabd1a0cc1553fb00df7ae9ff92ad66663916c5f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 16:42:39 +0900 Subject: [PATCH 067/154] Remove unused `Duration` property to avoid any misunderstandings --- osu.Game/Storyboards/CommandTimelineGroup.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index de5da3118a..d198ed68bd 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -84,9 +84,6 @@ namespace osu.Game.Storyboards [JsonIgnore] public virtual double EndTime => CommandsEndTime; - [JsonIgnore] - public double Duration => EndTime - StartTime; - [JsonIgnore] public bool HasCommands { From b83c8443ea2e5fc52213045d5701a55d0ee30b73 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 18:22:51 +0900 Subject: [PATCH 068/154] Ensure pause sample loop is stopped on exiting player --- osu.Game/Screens/Play/PauseOverlay.cs | 8 ++++++++ osu.Game/Screens/Play/Player.cs | 3 +++ 2 files changed, 11 insertions(+) diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index d9c60519ad..db42998c45 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -44,6 +44,14 @@ namespace osu.Game.Screens.Play }); } + public void StopAllSamples() + { + if (!IsLoaded) + return; + + pauseLoop.Stop(); + } + protected override void PopIn() { base.PopIn(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index bf7f38cdd3..37b3f906eb 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1073,7 +1073,10 @@ namespace osu.Game.Screens.Play public override bool OnExiting(ScreenExitEvent e) { screenSuspension?.RemoveAndDisposeImmediately(); + + // Eagerly clean these up as disposal of child components is asynchronous and may leave sounds playing beyond user expectations. failAnimationLayer?.Stop(); + PauseOverlay.StopAllSamples(); if (LoadedBeatmapSuccessfully) { From aaf3ad805c18e1e34cf51c4485d33b05882241e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 19:31:45 +0900 Subject: [PATCH 069/154] Fix potential nullref in tests --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 37b3f906eb..6dc4854e80 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1076,7 +1076,7 @@ namespace osu.Game.Screens.Play // Eagerly clean these up as disposal of child components is asynchronous and may leave sounds playing beyond user expectations. failAnimationLayer?.Stop(); - PauseOverlay.StopAllSamples(); + PauseOverlay?.StopAllSamples(); if (LoadedBeatmapSuccessfully) { From bc89f8dc5b9d40aa92bcc88249e7165e4b72f9fc Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Feb 2023 12:44:00 +0000 Subject: [PATCH 070/154] feat: add name and rulset verb display support --- osu.Desktop/DiscordRichPresence.cs | 5 +++- .../Visual/Online/TestSceneUserPanel.cs | 14 ++++++++-- osu.Game/Screens/Play/ReplayPlayer.cs | 2 +- osu.Game/Screens/Play/SoloSpectatorPlayer.cs | 2 +- osu.Game/Users/UserActivity.cs | 28 ++++++++++++++++++- 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 2c4577f239..6ca86c64c4 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -98,7 +98,7 @@ namespace osu.Desktop if (status.Value is UserStatusOnline && activity.Value != null) { - presence.State = truncate(activity.Value.Status); + presence.State = truncate(privacyMode.Value == DiscordRichPresenceMode.Limited ? activity.Value.LimitedStatus : activity.Value.Status); presence.Details = truncate(getDetails(activity.Value)); if (getBeatmap(activity.Value) is IBeatmapInfo beatmap && beatmap.OnlineID > 0) @@ -186,6 +186,9 @@ namespace osu.Desktop case UserActivity.Editing edit: return edit.BeatmapInfo.ToString() ?? string.Empty; + case UserActivity.Watching watching: + return watching.BeatmapInfo.ToString(); + case UserActivity.InLobby lobby: return privacyMode.Value == DiscordRichPresenceMode.Limited ? string.Empty : lobby.Room.Name.Value; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index eaf2ca5ac0..64a42ee6ce 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -11,6 +11,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; +using osu.Game.Scoring; +using osu.Game.Tests.Beatmaps; using osu.Game.Users; using osuTK; @@ -107,8 +109,8 @@ namespace osu.Game.Tests.Visual.Online AddStep("set online status", () => status.Value = new UserStatusOnline()); AddStep("idle", () => activity.Value = null); - AddStep("watching", () => activity.Value = new UserActivity.Watching()); - AddStep("spectating", () => activity.Value = new UserActivity.Spectating()); + AddStep("watching", () => activity.Value = new UserActivity.Watching(createScore(@"nats"))); + AddStep("spectating", () => activity.Value = new UserActivity.Spectating(createScore(@"mrekk"))); AddStep("solo (osu!)", () => activity.Value = soloGameStatusForRuleset(0)); AddStep("solo (osu!taiko)", () => activity.Value = soloGameStatusForRuleset(1)); AddStep("solo (osu!catch)", () => activity.Value = soloGameStatusForRuleset(2)); @@ -133,6 +135,14 @@ namespace osu.Game.Tests.Visual.Online private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.InSoloGame(null, rulesetStore.GetRuleset(rulesetId)); + private ScoreInfo createScore(string name) => new ScoreInfo(new TestBeatmap(Ruleset.Value).BeatmapInfo) + { + User = new APIUser + { + Username = name, + } + }; + private partial class TestUserListPanel : UserListPanel { public TestUserListPanel(APIUser user) diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index e2b8ad7011..9e87969687 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play private readonly bool replayIsFailedScore; - protected override UserActivity InitialActivity => new UserActivity.Watching(); + protected override UserActivity InitialActivity => new UserActivity.Watching(Score.ScoreInfo); // Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108) protected override bool CheckModsAllowFailure() diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index 65b66166c0..8a9cda2af7 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Play { private readonly Score score; - protected override UserActivity InitialActivity => new UserActivity.Spectating(); + protected override UserActivity InitialActivity => new UserActivity.Spectating(Score.ScoreInfo); public SoloSpectatorPlayer(Score score, PlayerConfiguration configuration = null) : base(score, configuration) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 37b5a2bf1e..99d68e7564 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -4,9 +4,11 @@ #nullable disable using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Online.Rooms; using osu.Game.Rulesets; +using osu.Game.Scoring; using osuTK.Graphics; namespace osu.Game.Users @@ -14,6 +16,12 @@ namespace osu.Game.Users public abstract class UserActivity { public abstract string Status { get; } + + /// + /// This property is used when the is + /// + public virtual string LimitedStatus => Status; + public virtual Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; public class Modding : UserActivity @@ -92,14 +100,32 @@ namespace osu.Game.Users public class Watching : UserActivity { + private readonly ScoreInfo score; + + private string username => score.User.Username; + private string playingVerb => score.BeatmapInfo.Ruleset.CreateInstance().PlayingVerb; + + public BeatmapInfo BeatmapInfo => score.BeatmapInfo; + + public Watching(ScoreInfo score) + { + this.score = score; + } + protected virtual string Verb => @"Watching"; - public override string Status => @$"{Verb} a game"; + public override string Status => @$"{Verb} {username} {playingVerb.ToLowerInvariant()}"; + public override string LimitedStatus => $@"{Verb} a game"; } public class Spectating : Watching { protected override string Verb => @"Spectating"; + + public Spectating(ScoreInfo score) + : base(score) + { + } } public class SearchingForLobby : UserActivity From 1baaae35a9748c913a744c1c6fbdb4f90d7bdb08 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Feb 2023 20:07:16 +0000 Subject: [PATCH 071/154] quality: Simplify string --- osu.Game/Users/UserActivity.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 99d68e7564..b62cd7edd5 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -102,8 +102,7 @@ namespace osu.Game.Users { private readonly ScoreInfo score; - private string username => score.User.Username; - private string playingVerb => score.BeatmapInfo.Ruleset.CreateInstance().PlayingVerb; + protected string Username => score.User.Username; public BeatmapInfo BeatmapInfo => score.BeatmapInfo; @@ -112,15 +111,12 @@ namespace osu.Game.Users this.score = score; } - protected virtual string Verb => @"Watching"; - - public override string Status => @$"{Verb} {username} {playingVerb.ToLowerInvariant()}"; - public override string LimitedStatus => $@"{Verb} a game"; + public override string Status => $@"Watching {Username}"; } public class Spectating : Watching { - protected override string Verb => @"Spectating"; + public override string Status => $@"Spectating {Username}"; public Spectating(ScoreInfo score) : base(score) From da10166628e01a3cd607a9337edc8546c80cbdb8 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Feb 2023 21:30:55 +0000 Subject: [PATCH 072/154] quality: convert getter property to method so that sensible information can be hidden via an argument --- osu.Desktop/DiscordRichPresence.cs | 2 +- osu.Game/Users/ExtendedUserPanel.cs | 2 +- osu.Game/Users/UserActivity.cs | 28 +++++++++++----------------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 6ca86c64c4..e24fe1a1ec 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -98,7 +98,7 @@ namespace osu.Desktop if (status.Value is UserStatusOnline && activity.Value != null) { - presence.State = truncate(privacyMode.Value == DiscordRichPresenceMode.Limited ? activity.Value.LimitedStatus : activity.Value.Status); + presence.State = truncate(activity.Value.GetStatus(privacyMode.Value == DiscordRichPresenceMode.Limited)); presence.Details = truncate(getDetails(activity.Value)); if (getBeatmap(activity.Value) is IBeatmapInfo beatmap && beatmap.OnlineID > 0) diff --git a/osu.Game/Users/ExtendedUserPanel.cs b/osu.Game/Users/ExtendedUserPanel.cs index 4ea3c036c1..3c1b68f9ef 100644 --- a/osu.Game/Users/ExtendedUserPanel.cs +++ b/osu.Game/Users/ExtendedUserPanel.cs @@ -106,7 +106,7 @@ namespace osu.Game.Users // Set status message based on activity (if we have one) and status is not offline if (activity != null && !(status is UserStatusOffline)) { - statusMessage.Text = activity.Status; + statusMessage.Text = activity.GetStatus(); statusIcon.FadeColour(activity.GetAppropriateColour(Colours), 500, Easing.OutQuint); return; } diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index b62cd7edd5..0e6e3ca5f2 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -4,7 +4,6 @@ #nullable disable using osu.Game.Beatmaps; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Online.Rooms; using osu.Game.Rulesets; @@ -15,24 +14,19 @@ namespace osu.Game.Users { public abstract class UserActivity { - public abstract string Status { get; } - - /// - /// This property is used when the is - /// - public virtual string LimitedStatus => Status; + public abstract string GetStatus(bool hideIdentifiableInformation = false); public virtual Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; public class Modding : UserActivity { - public override string Status => "Modding a map"; + public override string GetStatus(bool hideIdentifiableInformation = false) => "Modding a map"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; } public class ChoosingBeatmap : UserActivity { - public override string Status => "Choosing a beatmap"; + public override string GetStatus(bool hideIdentifiableInformation = false) => "Choosing a beatmap"; } public abstract class InGame : UserActivity @@ -47,7 +41,7 @@ namespace osu.Game.Users Ruleset = ruleset; } - public override string Status => Ruleset.CreateInstance().PlayingVerb; + public override string GetStatus(bool hideIdentifiableInformation = false) => Ruleset.CreateInstance().PlayingVerb; } public class InMultiplayerGame : InGame @@ -57,7 +51,7 @@ namespace osu.Game.Users { } - public override string Status => $@"{base.Status} with others"; + public override string GetStatus(bool hideIdentifiableInformation = false) => $@"{base.GetStatus(hideIdentifiableInformation)} with others"; } public class SpectatingMultiplayerGame : InGame @@ -67,7 +61,7 @@ namespace osu.Game.Users { } - public override string Status => $"Watching others {base.Status.ToLowerInvariant()}"; + public override string GetStatus(bool hideIdentifiableInformation = false) => $"Watching others {base.GetStatus(hideIdentifiableInformation).ToLowerInvariant()}"; } public class InPlaylistGame : InGame @@ -95,7 +89,7 @@ namespace osu.Game.Users BeatmapInfo = info; } - public override string Status => @"Editing a beatmap"; + public override string GetStatus(bool hideIdentifiableInformation = false) => @"Editing a beatmap"; } public class Watching : UserActivity @@ -111,12 +105,12 @@ namespace osu.Game.Users this.score = score; } - public override string Status => $@"Watching {Username}"; + public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Watching a game" : $@"Watching {Username}"; } public class Spectating : Watching { - public override string Status => $@"Spectating {Username}"; + public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Spectating a game" : $@"Spectating {Username}"; public Spectating(ScoreInfo score) : base(score) @@ -126,12 +120,12 @@ namespace osu.Game.Users public class SearchingForLobby : UserActivity { - public override string Status => @"Looking for a lobby"; + public override string GetStatus(bool hideIdentifiableInformation = false) => @"Looking for a lobby"; } public class InLobby : UserActivity { - public override string Status => @"In a lobby"; + public override string GetStatus(bool hideIdentifiableInformation = false) => @"In a lobby"; public readonly Room Room; From 71eef238c4a530d4ef59606feff1c66c862baa4e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Feb 2023 16:04:31 +0900 Subject: [PATCH 073/154] Make `OnStateChange` non-implemented rather than wrong --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 3a10e58707..ad031d2c7e 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -477,8 +477,8 @@ namespace osu.Game.Overlays.SkinEditor public event Action? OnStateChange { - add => changeHandler!.OnStateChange += value; - remove => changeHandler!.OnStateChange -= value; + add => throw new NotImplementedException(); + remove => throw new NotImplementedException(); } public void BeginChange() => changeHandler?.BeginChange(); From dad348111d2be5c53d73b8694a378bb81f6be9c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Feb 2023 16:07:33 +0900 Subject: [PATCH 074/154] Fix holding a selection while changing screens causing a crash --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index ad031d2c7e..0716505f26 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -481,8 +481,16 @@ namespace osu.Game.Overlays.SkinEditor remove => throw new NotImplementedException(); } - public void BeginChange() => changeHandler?.BeginChange(); - public void EndChange() => changeHandler?.EndChange(); + private IEditorChangeHandler? beginChangeHandler; + + public void BeginChange() + { + // Change handler may change between begin and end, which can cause unbalanced operations. + // Let's track the one that was used when beginning the change so we can call EndChange on it specifically. + (beginChangeHandler = changeHandler)?.BeginChange(); + } + + public void EndChange() => beginChangeHandler?.EndChange(); public void SaveState() => changeHandler?.SaveState(); #endregion From e162fd56da39f5bcf67ef3a21af13ea08c6cf8ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Feb 2023 16:22:51 +0900 Subject: [PATCH 075/154] Change the way initial state saving works in `EditorChangeHandler` to be closer to first change --- .../Screens/Edit/BeatmapEditorChangeHandler.cs | 3 --- osu.Game/Screens/Edit/EditorChangeHandler.cs | 15 +++++++++++++++ .../Screens/Edit/TransactionalCommitComponent.cs | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs b/osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs index b9349a31af..3c19994a8a 100644 --- a/osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/BeatmapEditorChangeHandler.cs @@ -26,9 +26,6 @@ namespace osu.Game.Screens.Edit editorBeatmap.SaveStateTriggered += SaveState; patcher = new LegacyEditorBeatmapPatcher(editorBeatmap); - - // Initial state. - SaveState(); } protected override void WriteCurrentStateToStream(MemoryStream stream) diff --git a/osu.Game/Screens/Edit/EditorChangeHandler.cs b/osu.Game/Screens/Edit/EditorChangeHandler.cs index 4511b654b6..0bb17e4c5d 100644 --- a/osu.Game/Screens/Edit/EditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/EditorChangeHandler.cs @@ -31,6 +31,8 @@ namespace osu.Game.Screens.Edit { get { + ensureStateSaved(); + using (var stream = new MemoryStream(savedStates[currentState])) return stream.ComputeSHA2Hash(); } @@ -40,6 +42,19 @@ namespace osu.Game.Screens.Edit public const int MAX_SAVED_STATES = 50; + public override void BeginChange() + { + ensureStateSaved(); + + base.BeginChange(); + } + + private void ensureStateSaved() + { + if (savedStates.Count == 0) + SaveState(); + } + protected override void UpdateState() { if (isRestoring) diff --git a/osu.Game/Screens/Edit/TransactionalCommitComponent.cs b/osu.Game/Screens/Edit/TransactionalCommitComponent.cs index f8362523f1..92f1e19e6f 100644 --- a/osu.Game/Screens/Edit/TransactionalCommitComponent.cs +++ b/osu.Game/Screens/Edit/TransactionalCommitComponent.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Edit /// /// Signal the beginning of a change. /// - public void BeginChange() + public virtual void BeginChange() { if (bulkChangesStarted++ == 0) TransactionBegan?.Invoke(); From 0320ba770f1824b32fbb1e7d57366e7cf4b41481 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Feb 2023 16:23:24 +0900 Subject: [PATCH 076/154] Handle component changes via `ISkinnableTarget.Components` rather than inside `SkinEditor` directly Seems saner? Maybe? --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 4 ---- .../SkinEditor/SkinEditorChangeHandler.cs | 15 ++++++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 0716505f26..866de7e621 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -329,8 +329,6 @@ namespace osu.Game.Overlays.SkinEditor SelectedComponents.Clear(); SelectedComponents.Add(component); - - changeHandler?.SaveState(); } private void populateSettings() @@ -406,8 +404,6 @@ namespace osu.Game.Overlays.SkinEditor { foreach (var item in items) availableTargets.FirstOrDefault(t => t.Components.Contains(item))?.Remove(item); - - changeHandler?.SaveState(); } #region Drag & drop import handling diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index 95b24bbd6f..dfbd48a285 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Text; using Newtonsoft.Json; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Extensions; @@ -17,9 +18,10 @@ namespace osu.Game.Overlays.SkinEditor { public partial class SkinEditorChangeHandler : EditorChangeHandler { - private readonly Drawable targetScreen; + private readonly ISkinnableTarget? firstTarget; - private ISkinnableTarget? firstTarget => targetScreen.ChildrenOfType().FirstOrDefault(); + // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable + private readonly BindableList? components; public SkinEditorChangeHandler(Drawable targetScreen) { @@ -27,10 +29,13 @@ namespace osu.Game.Overlays.SkinEditor // In the future we'll want this to cover all changes, even to skin's `InstantiationInfo`. // We'll also need to consider cases where multiple targets are on screen at the same time. - this.targetScreen = targetScreen; + firstTarget = targetScreen?.ChildrenOfType().FirstOrDefault(); - // Save initial state. - SaveState(); + if (firstTarget == null) + return; + + components = new BindableList { BindTarget = firstTarget.Components }; + components.BindCollectionChanged((_, _) => SaveState()); } protected override void WriteCurrentStateToStream(MemoryStream stream) From 277f71d36a2609386453a1b2aae38189f4e8f7ec Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 7 Feb 2023 15:15:51 -0800 Subject: [PATCH 077/154] Expire reply editor instead of clearing container --- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index c9eb80f676..397dd46cdc 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -466,7 +466,7 @@ namespace osu.Game.Overlays.Comments } else { - replyEditorContainer.Clear(true); + replyEditorContainer.ForEach(e => e.Expire()); replyEditorContainer.Hide(); } } From ee65c658937f3ff845c229bbf5edd97d8e73af17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 11:31:28 +0900 Subject: [PATCH 078/154] Attempt to fix channel join / leave loop I don't have a solid way to repro the issue, but this should hopefully help in resolving it. Either way, I think this change brings more correct behaviour (if a websocket message comes through that we have left the channel, I don't believe we should be sending a request to leave that channel again). --- osu.Game/Online/Chat/ChannelManager.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 7ab678775f..701a1cd040 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -95,7 +95,7 @@ namespace osu.Game.Online.Chat { connector.ChannelJoined += ch => Schedule(() => joinChannel(ch)); - connector.ChannelParted += ch => Schedule(() => LeaveChannel(getChannel(ch))); + connector.ChannelParted += ch => Schedule(() => leaveChannel(getChannel(ch), false)); connector.NewMessages += msgs => Schedule(() => addMessages(msgs)); @@ -558,7 +558,9 @@ namespace osu.Game.Online.Chat /// Leave the specified channel. Can be called from any thread. /// /// The channel to leave. - public void LeaveChannel(Channel channel) => Schedule(() => + public void LeaveChannel(Channel channel) => Schedule(() => leaveChannel(channel, true)); + + private void leaveChannel(Channel channel, bool sendLeaveRequest) { if (channel == null) return; @@ -584,7 +586,7 @@ namespace osu.Game.Online.Chat api.Queue(new LeaveChannelRequest(channel)); channel.Joined.Value = false; } - }); + } /// /// Opens the most recently closed channel that has not already been reopened, From cec1f77e6cbbc7d61e3a71dc54dbfd052b0f9e56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 13:59:09 +0900 Subject: [PATCH 079/154] Fix glow flash occurring after releasing mouse and adjust transition slightly --- osu.Game/Graphics/UserInterface/ShearedNub.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedNub.cs b/osu.Game/Graphics/UserInterface/ShearedNub.cs index 390d6ff9be..3a09fd7445 100644 --- a/osu.Game/Graphics/UserInterface/ShearedNub.cs +++ b/osu.Game/Graphics/UserInterface/ShearedNub.cs @@ -58,7 +58,7 @@ namespace osu.Game.Graphics.UserInterface private void load(OverlayColourProvider? colourProvider, OsuColour colours) { AccentColour = colourProvider?.Highlight1 ?? colours.Pink; - GlowingAccentColour = colourProvider?.Highlight1.Lighten(0.2f) ?? colours.PinkLighter; + GlowingAccentColour = colourProvider?.Highlight1.Lighten(0.4f) ?? colours.PinkLighter; GlowColour = colourProvider?.Highlight1 ?? colours.PinkLighter; main.EdgeEffect = new EdgeEffectParameters @@ -84,11 +84,14 @@ namespace osu.Game.Graphics.UserInterface get => glowing; set { + if (glowing == value) + return; + glowing = value; if (value) { - main.FadeColour(GlowingAccentColour.Lighten(0.5f), 40, Easing.OutQuint) + main.FadeColour(GlowingAccentColour.Lighten(0.1f), 40, Easing.OutQuint) .Then() .FadeColour(GlowingAccentColour, 800, Easing.OutQuint); From 5cd111e6f13ab9e7a0335b19dee25800b16cb42b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 14:00:45 +0900 Subject: [PATCH 080/154] Fix ordering of methods in `OsuSliderBar` --- .../Graphics/UserInterface/OsuSliderBar.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index ee1f75c419..0c36d73085 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -17,18 +17,12 @@ namespace osu.Game.Graphics.UserInterface public abstract partial class OsuSliderBar : SliderBar, IHasTooltip where T : struct, IEquatable, IComparable, IConvertible { - private Sample sample = null!; - - private double lastSampleTime; - private T lastSampleValue; - public bool PlaySamplesOnAdjust { get; set; } = true; - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - sample = audio.Samples.Get(@"UI/notch-tick"); - } + /// + /// Whether to format the tooltip as a percentage or the actual value. + /// + public bool DisplayAsPercentage { get; set; } public virtual LocalisableString TooltipText { get; private set; } @@ -37,10 +31,16 @@ namespace osu.Game.Graphics.UserInterface /// private const int max_decimal_digits = 5; - /// - /// Whether to format the tooltip as a percentage or the actual value. - /// - public bool DisplayAsPercentage { get; set; } + private Sample sample = null!; + + private double lastSampleTime; + private T lastSampleValue; + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sample = audio.Samples.Get(@"UI/notch-tick"); + } protected override void LoadComplete() { From 17ca26ebee29560f507a4556df3b75236f6464a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:44:24 +0900 Subject: [PATCH 081/154] Remove unnecessary null check on `targetScreen` --- osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index dfbd48a285..c8f66f3e56 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.SkinEditor // In the future we'll want this to cover all changes, even to skin's `InstantiationInfo`. // We'll also need to consider cases where multiple targets are on screen at the same time. - firstTarget = targetScreen?.ChildrenOfType().FirstOrDefault(); + firstTarget = targetScreen.ChildrenOfType().FirstOrDefault(); if (firstTarget == null) return; From b0131db1dc5fd09a6cc7a10671b317a69fe9fe01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:55:17 +0900 Subject: [PATCH 082/154] Update test assertions in line with new state saving logic --- .../Editing/BeatmapEditorChangeHandlerTest.cs | 63 ++++++++++++++++--- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Editing/BeatmapEditorChangeHandlerTest.cs b/osu.Game.Tests/Editing/BeatmapEditorChangeHandlerTest.cs index 4746f84fa0..80237fe6c8 100644 --- a/osu.Game.Tests/Editing/BeatmapEditorChangeHandlerTest.cs +++ b/osu.Game.Tests/Editing/BeatmapEditorChangeHandlerTest.cs @@ -21,18 +21,23 @@ namespace osu.Game.Tests.Editing } [Test] - public void TestSaveRestoreState() + public void TestSaveRestoreStateUsingTransaction() { var (handler, beatmap) = createChangeHandler(); Assert.That(handler.CanUndo.Value, Is.False); Assert.That(handler.CanRedo.Value, Is.False); - addArbitraryChange(beatmap); - handler.SaveState(); + handler.BeginChange(); + // Initial state will be saved on BeginChange Assert.That(stateChangedFired, Is.EqualTo(1)); + addArbitraryChange(beatmap); + handler.EndChange(); + + Assert.That(stateChangedFired, Is.EqualTo(2)); + Assert.That(handler.CanUndo.Value, Is.True); Assert.That(handler.CanRedo.Value, Is.False); @@ -41,7 +46,35 @@ namespace osu.Game.Tests.Editing Assert.That(handler.CanUndo.Value, Is.False); Assert.That(handler.CanRedo.Value, Is.True); + Assert.That(stateChangedFired, Is.EqualTo(3)); + } + + [Test] + public void TestSaveRestoreState() + { + var (handler, beatmap) = createChangeHandler(); + + Assert.That(handler.CanUndo.Value, Is.False); + Assert.That(handler.CanRedo.Value, Is.False); + + // Save initial state + handler.SaveState(); + Assert.That(stateChangedFired, Is.EqualTo(1)); + + addArbitraryChange(beatmap); + handler.SaveState(); + Assert.That(stateChangedFired, Is.EqualTo(2)); + + Assert.That(handler.CanUndo.Value, Is.True); + Assert.That(handler.CanRedo.Value, Is.False); + + handler.RestoreState(-1); + + Assert.That(handler.CanUndo.Value, Is.False); + Assert.That(handler.CanRedo.Value, Is.True); + + Assert.That(stateChangedFired, Is.EqualTo(3)); } [Test] @@ -52,6 +85,10 @@ namespace osu.Game.Tests.Editing Assert.That(handler.CanUndo.Value, Is.False); Assert.That(handler.CanRedo.Value, Is.False); + // Save initial state + handler.SaveState(); + Assert.That(stateChangedFired, Is.EqualTo(1)); + string originalHash = handler.CurrentStateHash; addArbitraryChange(beatmap); @@ -59,7 +96,7 @@ namespace osu.Game.Tests.Editing Assert.That(handler.CanUndo.Value, Is.True); Assert.That(handler.CanRedo.Value, Is.False); - Assert.That(stateChangedFired, Is.EqualTo(1)); + Assert.That(stateChangedFired, Is.EqualTo(2)); string hash = handler.CurrentStateHash; @@ -67,7 +104,7 @@ namespace osu.Game.Tests.Editing handler.RestoreState(-1); Assert.That(originalHash, Is.EqualTo(handler.CurrentStateHash)); - Assert.That(stateChangedFired, Is.EqualTo(2)); + Assert.That(stateChangedFired, Is.EqualTo(3)); addArbitraryChange(beatmap); handler.SaveState(); @@ -82,12 +119,16 @@ namespace osu.Game.Tests.Editing Assert.That(handler.CanUndo.Value, Is.False); Assert.That(handler.CanRedo.Value, Is.False); + // Save initial state + handler.SaveState(); + Assert.That(stateChangedFired, Is.EqualTo(1)); + addArbitraryChange(beatmap); handler.SaveState(); Assert.That(handler.CanUndo.Value, Is.True); Assert.That(handler.CanRedo.Value, Is.False); - Assert.That(stateChangedFired, Is.EqualTo(1)); + Assert.That(stateChangedFired, Is.EqualTo(2)); string hash = handler.CurrentStateHash; @@ -95,7 +136,7 @@ namespace osu.Game.Tests.Editing handler.SaveState(); Assert.That(hash, Is.EqualTo(handler.CurrentStateHash)); - Assert.That(stateChangedFired, Is.EqualTo(1)); + Assert.That(stateChangedFired, Is.EqualTo(2)); handler.RestoreState(-1); @@ -104,7 +145,7 @@ namespace osu.Game.Tests.Editing // we should only be able to restore once even though we saved twice. Assert.That(handler.CanUndo.Value, Is.False); Assert.That(handler.CanRedo.Value, Is.True); - Assert.That(stateChangedFired, Is.EqualTo(2)); + Assert.That(stateChangedFired, Is.EqualTo(3)); } [Test] @@ -112,11 +153,15 @@ namespace osu.Game.Tests.Editing { var (handler, beatmap) = createChangeHandler(); + // Save initial state + handler.SaveState(); + Assert.That(stateChangedFired, Is.EqualTo(1)); + Assert.That(handler.CanUndo.Value, Is.False); for (int i = 0; i < EditorChangeHandler.MAX_SAVED_STATES; i++) { - Assert.That(stateChangedFired, Is.EqualTo(i)); + Assert.That(stateChangedFired, Is.EqualTo(i + 1)); addArbitraryChange(beatmap); handler.SaveState(); From 0156ff732ffa40431940a7cb01e6ba0ffada95a8 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 7 Feb 2023 21:55:01 -0800 Subject: [PATCH 083/154] Fix beatmap cards not showing context menu on user profile --- .../Profile/Header/TopHeaderContainer.cs | 120 ++++++++---------- osu.Game/Overlays/UserProfileOverlay.cs | 22 ++-- 2 files changed, 70 insertions(+), 72 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 652ebcec26..2f4f49788f 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays.Profile.Header.Components; @@ -104,76 +103,69 @@ namespace osu.Game.Overlays.Profile.Header Colour = Colour4.Black.Opacity(0.25f), } }, - new OsuContextMenuContainer + new FillFlowContainer { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Child = new FillFlowContainer + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Children = new Drawable[] + new FillFlowContainer { - new FillFlowContainer + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Children = new Drawable[] + usernameText = new OsuSpriteText { - usernameText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 24, weight: FontWeight.Regular) - }, - supporterTag = new SupporterIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Height = 15, - }, - openUserExternally = new ExternalLinkButton - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - groupBadgeFlow = new GroupBadgeFlow - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - } - }, - titleText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 16, weight: FontWeight.Regular), - Margin = new MarginPadding { Bottom = 5 } - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new Drawable[] + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Regular) + }, + supporterTag = new SupporterIcon { - userFlag = new UpdateableFlag - { - Size = new Vector2(28, 20), - ShowPlaceholderOnUnknown = false, - }, - userCountryText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), - Margin = new MarginPadding { Left = 5 }, - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Height = 15, + }, + openUserExternally = new ExternalLinkButton + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + groupBadgeFlow = new GroupBadgeFlow + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + } + }, + titleText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 16, weight: FontWeight.Regular), + Margin = new MarginPadding { Bottom = 5 } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + userFlag = new UpdateableFlag + { + Size = new Vector2(28, 20), + ShowPlaceholderOnUnknown = false, + }, + userCountryText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), + Margin = new MarginPadding { Left = 5 }, + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, } - }, - } - }, + } + }, + } }, } }, diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 8849c674dc..c5f8a820ea 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -14,6 +14,7 @@ using osu.Framework.Input.Events; using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online; @@ -100,17 +101,22 @@ namespace osu.Game.Overlays Origin = Anchor.TopCentre, }; - Add(sectionsContainer = new ProfileSectionsContainer + Add(new OsuContextMenuContainer { - ExpandableHeader = Header, - FixedHeader = tabs, - HeaderBackground = new Box + RelativeSizeAxes = Axes.Both, + Child = sectionsContainer = new ProfileSectionsContainer { - // this is only visible as the ProfileTabControl background - Colour = ColourProvider.Background5, - RelativeSizeAxes = Axes.Both - }, + ExpandableHeader = Header, + FixedHeader = tabs, + HeaderBackground = new Box + { + // this is only visible as the ProfileTabControl background + Colour = ColourProvider.Background5, + RelativeSizeAxes = Axes.Both + }, + } }); + sectionsContainer.SelectedSection.ValueChanged += section => { if (lastSection != section.NewValue) From df1355ea4be54fac4a7c306892d35111fbe3960f Mon Sep 17 00:00:00 2001 From: OpenSauce Date: Mon, 6 Feb 2023 13:34:54 +0000 Subject: [PATCH 084/154] Taiko hit objects now snap to hit target --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index ff4edf35fa..ef87522eea 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -207,6 +207,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables const float gravity_time = 300; const float gravity_travel_height = 200; + MainPiece.MoveToX(-X); // Visually snap hit object to hit target + this.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad); this.MoveToY(-gravity_travel_height, gravity_time, Easing.Out) From 6ace6bfee17fbf0ffcb4d8f3c88a23d22acf2332 Mon Sep 17 00:00:00 2001 From: Walavouchey <36758269+Walavouchey@users.noreply.github.com> Date: Tue, 7 Feb 2023 11:16:36 +0100 Subject: [PATCH 085/154] ensure `AccuracyCircle` doesn't land in gaps created by `RankNotch`es --- .../Visual/Ranking/TestSceneAccuracyCircle.cs | 9 +++++ .../Expanded/Accuracy/AccuracyCircle.cs | 34 ++++++++++++++++++- .../Ranking/Expanded/Accuracy/RankNotch.cs | 2 +- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs index 0145a1dfef..314e275ca3 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs @@ -24,11 +24,20 @@ namespace osu.Game.Tests.Visual.Ranking { public partial class TestSceneAccuracyCircle : OsuTestScene { + [TestCase(0, ScoreRank.D)] [TestCase(0.2, ScoreRank.D)] [TestCase(0.5, ScoreRank.D)] + [TestCase(0.699, ScoreRank.D)] + [TestCase(0.7, ScoreRank.C)] [TestCase(0.75, ScoreRank.C)] + [TestCase(0.799, ScoreRank.C)] + [TestCase(0.80, ScoreRank.B)] [TestCase(0.85, ScoreRank.B)] + [TestCase(0.899, ScoreRank.B)] + [TestCase(0.9, ScoreRank.A)] [TestCase(0.925, ScoreRank.A)] + [TestCase(0.949, ScoreRank.A)] + [TestCase(0.95, ScoreRank.S)] [TestCase(0.975, ScoreRank.S)] [TestCase(0.9999, ScoreRank.S)] [TestCase(1, ScoreRank.X)] diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 8e04bb68fb..3cb09734c5 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -73,6 +73,11 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// private const double virtual_ss_percentage = 0.01; + /// + /// The width of a in terms of accuracy. + /// + public const double NOTCH_WIDTH_PERCENTAGE = 0.002; + /// /// The easing for the circle filling transforms. /// @@ -263,7 +268,34 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY)) { - double targetAccuracy = score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH ? 1 : Math.Min(1 - virtual_ss_percentage, score.Accuracy); + double targetAccuracy = score.Accuracy; + + // Ensure the gauge overshoots or undershoots a bit so it doesn't land in the gaps of the inner graded circle (caused by `RankNotch`es), + // to prevent ambiguity on what grade it's pointing at. + double[] notchPercentages = { 0.7, 0.8, 0.9, 0.95 }; + + foreach (double p in notchPercentages) + { + if (targetAccuracy > p - NOTCH_WIDTH_PERCENTAGE / 2 && targetAccuracy < p + NOTCH_WIDTH_PERCENTAGE / 2) + { + int tippingDirection = targetAccuracy - p >= 0 ? 1 : -1; // We "round up" here to match rank criteria + targetAccuracy = p + tippingDirection * (NOTCH_WIDTH_PERCENTAGE / 2); + break; + } + } + + // The final gap between 99.999...% (S) and 100% (SS) is exaggerated by `virtual_ss_percentage`. We don't want to land there either. + if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH) + targetAccuracy = 1; + else + targetAccuracy = Math.Min(1 - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy); + + // The accuracy circle gauge visually fills up a bit too much. + // This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases. + const double visual_alignment_offset = 0.001; + + if (targetAccuracy < 1 && targetAccuracy >= visual_alignment_offset) + targetAccuracy -= visual_alignment_offset; accuracyCircle.FillTo(targetAccuracy, ACCURACY_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING); diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs index 7e73767318..32f2eb2fa5 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Y, Height = AccuracyCircle.RANK_CIRCLE_RADIUS, - Width = 1f, + Width = (float)AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 360f, Colour = OsuColour.Gray(0.3f), EdgeSmoothness = new Vector2(1f) } From 0531c010ebeb17037059d34b21aa948849ca67d2 Mon Sep 17 00:00:00 2001 From: Walavouchey <36758269+Walavouchey@users.noreply.github.com> Date: Tue, 7 Feb 2023 12:08:37 +0100 Subject: [PATCH 086/154] display `RankBadge`s on on their sector centres the D `RankBadge` does this anyway. the A and S badges are slightly off centre to prevent overlap with the SS badge --- .../Ranking/Expanded/Accuracy/AccuracyCircle.cs | 12 ++++++------ .../Screens/Ranking/Expanded/Accuracy/RankBadge.cs | 11 +++++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 3cb09734c5..9ee63b40dd 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -220,12 +220,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Padding = new MarginPadding { Vertical = -15, Horizontal = -20 }, Children = new[] { - new RankBadge(1, getRank(ScoreRank.X)), - new RankBadge(0.95, getRank(ScoreRank.S)), - new RankBadge(0.9, getRank(ScoreRank.A)), - new RankBadge(0.8, getRank(ScoreRank.B)), - new RankBadge(0.7, getRank(ScoreRank.C)), - new RankBadge(0.35, getRank(ScoreRank.D)), + new RankBadge(1, 1, getRank(ScoreRank.X)), + new RankBadge(0.95, 0.95 + (0.025 - virtual_ss_percentage) / 2, getRank(ScoreRank.S)), + new RankBadge(0.9, 0.9125, getRank(ScoreRank.A)), + new RankBadge(0.8, 0.85, getRank(ScoreRank.B)), + new RankBadge(0.7, 0.75, getRank(ScoreRank.C)), + new RankBadge(0, 0.35, getRank(ScoreRank.D)), } }, rankText = new RankText(score.Rank) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs index 5432b4cbeb..7af327828e 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs @@ -27,6 +27,11 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// public readonly double Accuracy; + /// + /// The position around the to display this badge. + /// + private readonly double displayPosition; + private readonly ScoreRank rank; private Drawable rankContainer; @@ -36,10 +41,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// Creates a new . /// /// The accuracy value corresponding to . + /// The position around the to display this badge. /// The to be displayed in this . - public RankBadge(double accuracy, ScoreRank rank) + public RankBadge(double accuracy, double position, ScoreRank rank) { Accuracy = accuracy; + displayPosition = position; this.rank = rank; RelativeSizeAxes = Axes.Both; @@ -92,7 +99,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy base.Update(); // Starts at -90deg (top) and moves counter-clockwise by the accuracy - rankContainer.Position = circlePosition(-MathF.PI / 2 - (1 - (float)Accuracy) * MathF.PI * 2); + rankContainer.Position = circlePosition(-MathF.PI / 2 - (1 - (float)displayPosition) * MathF.PI * 2); } private Vector2 circlePosition(float t) From ee40444fd3c96b37b32d3defb8b7509267244b45 Mon Sep 17 00:00:00 2001 From: Walavouchey <36758269+Walavouchey@users.noreply.github.com> Date: Wed, 8 Feb 2023 23:59:19 +0100 Subject: [PATCH 087/154] use `Precision.AlmostEquals` for bounds check --- osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 9ee63b40dd..24daea21f3 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -276,7 +276,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy foreach (double p in notchPercentages) { - if (targetAccuracy > p - NOTCH_WIDTH_PERCENTAGE / 2 && targetAccuracy < p + NOTCH_WIDTH_PERCENTAGE / 2) + if (Precision.AlmostEquals(p, targetAccuracy, NOTCH_WIDTH_PERCENTAGE / 2)) { int tippingDirection = targetAccuracy - p >= 0 ? 1 : -1; // We "round up" here to match rank criteria targetAccuracy = p + tippingDirection * (NOTCH_WIDTH_PERCENTAGE / 2); From 9544a1d26d6cf819aa192c689fea10e78bb4ac11 Mon Sep 17 00:00:00 2001 From: Walavouchey <36758269+Walavouchey@users.noreply.github.com> Date: Thu, 9 Feb 2023 00:02:32 +0100 Subject: [PATCH 088/154] use values closer to the extremities for test cases --- .../Visual/Ranking/TestSceneAccuracyCircle.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs index 314e275ca3..f94cf9eb58 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs @@ -27,16 +27,16 @@ namespace osu.Game.Tests.Visual.Ranking [TestCase(0, ScoreRank.D)] [TestCase(0.2, ScoreRank.D)] [TestCase(0.5, ScoreRank.D)] - [TestCase(0.699, ScoreRank.D)] + [TestCase(0.6999, ScoreRank.D)] [TestCase(0.7, ScoreRank.C)] [TestCase(0.75, ScoreRank.C)] - [TestCase(0.799, ScoreRank.C)] - [TestCase(0.80, ScoreRank.B)] + [TestCase(0.7999, ScoreRank.C)] + [TestCase(0.8, ScoreRank.B)] [TestCase(0.85, ScoreRank.B)] - [TestCase(0.899, ScoreRank.B)] + [TestCase(0.8999, ScoreRank.B)] [TestCase(0.9, ScoreRank.A)] [TestCase(0.925, ScoreRank.A)] - [TestCase(0.949, ScoreRank.A)] + [TestCase(0.9499, ScoreRank.A)] [TestCase(0.95, ScoreRank.S)] [TestCase(0.975, ScoreRank.S)] [TestCase(0.9999, ScoreRank.S)] From fd93bd3f501de37fa7ca43e7e0a52efe2566cb5f Mon Sep 17 00:00:00 2001 From: Walavouchey <36758269+Walavouchey@users.noreply.github.com> Date: Thu, 9 Feb 2023 00:34:28 +0100 Subject: [PATCH 089/154] move rank accuracy requirements to class-local constants --- .../Expanded/Accuracy/AccuracyCircle.cs | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 24daea21f3..9606c2bf22 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -28,6 +28,18 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// public partial class AccuracyCircle : CompositeDrawable { + private const double accuracy_x = 1; + + private const double accuracy_s = 0.95; + + private const double accuracy_a = 0.9; + + private const double accuracy_b = 0.8; + + private const double accuracy_c = 0.7; + + private const double accuracy_d = 0; + /// /// Duration for the transforms causing this component to appear. /// @@ -150,49 +162,49 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.X), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = 1 } + Current = { Value = accuracy_x } }, new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.S), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = 1 - virtual_ss_percentage } + Current = { Value = accuracy_x - virtual_ss_percentage } }, new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.A), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = 0.95f } + Current = { Value = accuracy_s } }, new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.B), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = 0.9f } + Current = { Value = accuracy_a } }, new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.C), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = 0.8f } + Current = { Value = accuracy_b } }, new CircularProgress { RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.D), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = 0.7f } + Current = { Value = accuracy_c } }, - new RankNotch(0), - new RankNotch((float)(1 - virtual_ss_percentage)), - new RankNotch(0.95f), - new RankNotch(0.9f), - new RankNotch(0.8f), - new RankNotch(0.7f), + new RankNotch((float)accuracy_x), + new RankNotch((float)(accuracy_x - virtual_ss_percentage)), + new RankNotch((float)accuracy_s), + new RankNotch((float)accuracy_a), + new RankNotch((float)accuracy_b), + new RankNotch((float)accuracy_c), new BufferedContainer { Name = "Graded circle mask", @@ -220,12 +232,13 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Padding = new MarginPadding { Vertical = -15, Horizontal = -20 }, Children = new[] { - new RankBadge(1, 1, getRank(ScoreRank.X)), - new RankBadge(0.95, 0.95 + (0.025 - virtual_ss_percentage) / 2, getRank(ScoreRank.S)), - new RankBadge(0.9, 0.9125, getRank(ScoreRank.A)), - new RankBadge(0.8, 0.85, getRank(ScoreRank.B)), - new RankBadge(0.7, 0.75, getRank(ScoreRank.C)), - new RankBadge(0, 0.35, getRank(ScoreRank.D)), + // The S and A badges are moved down slightly to prevent collision with the SS badge. + new RankBadge(accuracy_x, accuracy_x, getRank(ScoreRank.X)), + new RankBadge(accuracy_s, Interpolation.Lerp(accuracy_s, (accuracy_x - virtual_ss_percentage), 0.25), getRank(ScoreRank.S)), + new RankBadge(accuracy_a, Interpolation.Lerp(accuracy_a, accuracy_s, 0.25), getRank(ScoreRank.A)), + new RankBadge(accuracy_b, Interpolation.Lerp(accuracy_b, accuracy_a, 0.5), getRank(ScoreRank.B)), + new RankBadge(accuracy_c, Interpolation.Lerp(accuracy_c, accuracy_b, 0.5), getRank(ScoreRank.C)), + new RankBadge(accuracy_d, Interpolation.Lerp(accuracy_d, accuracy_c, 0.5), getRank(ScoreRank.D)), } }, rankText = new RankText(score.Rank) @@ -269,11 +282,16 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY)) { double targetAccuracy = score.Accuracy; + double[] notchPercentages = + { + accuracy_s, + accuracy_a, + accuracy_b, + accuracy_c, + }; // Ensure the gauge overshoots or undershoots a bit so it doesn't land in the gaps of the inner graded circle (caused by `RankNotch`es), // to prevent ambiguity on what grade it's pointing at. - double[] notchPercentages = { 0.7, 0.8, 0.9, 0.95 }; - foreach (double p in notchPercentages) { if (Precision.AlmostEquals(p, targetAccuracy, NOTCH_WIDTH_PERCENTAGE / 2)) @@ -288,7 +306,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH) targetAccuracy = 1; else - targetAccuracy = Math.Min(1 - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy); + targetAccuracy = Math.Min(accuracy_x - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy); // The accuracy circle gauge visually fills up a bit too much. // This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases. @@ -325,7 +343,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy if (badge.Accuracy > score.Accuracy) continue; - using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(1 - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION)) + using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(accuracy_x - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION)) { badge.Appear(); From 3b5d573db1365dd07b335a2f8be5da60e7b9f67a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 31 Jan 2023 15:02:59 -0800 Subject: [PATCH 090/154] Display tournament banner on user profile --- .../Online/TestSceneUserProfileOverlay.cs | 6 ++ .../Online/API/Requests/Responses/APIUser.cs | 4 ++ .../Profile/Header/BannerHeaderContainer.cs | 63 +++++++++++++++++++ .../Components/DrawableTournamentBanner.cs | 46 ++++++++++++++ osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++ osu.Game/Users/TournamentBanner.cs | 23 +++++++ 6 files changed, 146 insertions(+) create mode 100644 osu.Game/Overlays/Profile/Header/BannerHeaderContainer.cs create mode 100644 osu.Game/Overlays/Profile/Header/Components/DrawableTournamentBanner.cs create mode 100644 osu.Game/Users/TournamentBanner.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 91928c1fd2..a97c8aff66 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -121,6 +121,12 @@ namespace osu.Game.Tests.Visual.Online Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray() }, }, + TournamentBanner = new TournamentBanner + { + Id = 13926, + TournamentId = 35, + ImageLowRes = "https://assets.ppy.sh/tournament-banners/official/owc2022/profile/winner_US.jpg", + }, Badges = new[] { new Badge diff --git a/osu.Game/Online/API/Requests/Responses/APIUser.cs b/osu.Game/Online/API/Requests/Responses/APIUser.cs index 0e62b03f1a..e63395fe26 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -234,6 +234,10 @@ namespace osu.Game.Online.API.Requests.Responses set => Statistics.RankHistory = value; } + [JsonProperty(@"active_tournament_banner")] + [CanBeNull] + public TournamentBanner TournamentBanner; + [JsonProperty("badges")] public Badge[] Badges; diff --git a/osu.Game/Overlays/Profile/Header/BannerHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BannerHeaderContainer.cs new file mode 100644 index 0000000000..8e6648dc4b --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/BannerHeaderContainer.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Profile.Header.Components; + +namespace osu.Game.Overlays.Profile.Header +{ + public partial class BannerHeaderContainer : CompositeDrawable + { + public readonly Bindable User = new Bindable(); + + [BackgroundDependencyLoader] + private void load() + { + Alpha = 0; + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fit; + FillAspectRatio = 1000 / 60f; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + User.BindValueChanged(u => updateDisplay(u.NewValue?.User), true); + } + + private CancellationTokenSource? cancellationTokenSource; + + private void updateDisplay(APIUser? user) + { + cancellationTokenSource?.Cancel(); + cancellationTokenSource = new CancellationTokenSource(); + + ClearInternal(); + + var banner = user?.TournamentBanner; + + if (banner != null) + { + Show(); + + LoadComponentAsync(new DrawableTournamentBanner(banner), AddInternal, cancellationTokenSource.Token); + } + else + { + Hide(); + } + } + + protected override void Dispose(bool isDisposing) + { + cancellationTokenSource?.Cancel(); + base.Dispose(isDisposing); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/Components/DrawableTournamentBanner.cs b/osu.Game/Overlays/Profile/Header/Components/DrawableTournamentBanner.cs new file mode 100644 index 0000000000..26d333ff95 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/Components/DrawableTournamentBanner.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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Localisation; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API; +using osu.Game.Users; + +namespace osu.Game.Overlays.Profile.Header.Components +{ + [LongRunningLoad] + public partial class DrawableTournamentBanner : OsuClickableContainer + { + private readonly TournamentBanner banner; + + public DrawableTournamentBanner(TournamentBanner banner) + { + this.banner = banner; + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures, OsuGame? game, IAPIProvider api) + { + Child = new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = textures.Get(banner.Image), + }; + + Action = () => game?.OpenUrlExternally($@"{api.WebsiteRootUrl}/community/tournaments/{banner.TournamentId}"); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + this.FadeInFromZero(200); + } + + public override LocalisableString TooltipText => "view in browser"; + } +} diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 5d753dea7d..363eb5d58e 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -47,6 +47,10 @@ namespace osu.Game.Overlays.Profile RelativeSizeAxes = Axes.X, User = { BindTarget = User }, }, + new BannerHeaderContainer + { + User = { BindTarget = User }, + }, new BadgeHeaderContainer { RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Users/TournamentBanner.cs b/osu.Game/Users/TournamentBanner.cs new file mode 100644 index 0000000000..62e1913412 --- /dev/null +++ b/osu.Game/Users/TournamentBanner.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using Newtonsoft.Json; + +namespace osu.Game.Users +{ + public class TournamentBanner + { + [JsonProperty("id")] + public int Id; + + [JsonProperty("tournament_id")] + public int TournamentId; + + [JsonProperty("image")] + public string ImageLowRes = null!; + + // TODO: remove when api returns @2x image link: https://github.com/ppy/osu-web/issues/9816 + public string Image => $@"{Path.ChangeExtension(ImageLowRes, null)}@2x{Path.GetExtension(ImageLowRes)}"; + } +} From 57312279f02049028fbc97f41f94be8192f323c0 Mon Sep 17 00:00:00 2001 From: Walavouchey <36758269+Walavouchey@users.noreply.github.com> Date: Thu, 9 Feb 2023 02:20:05 +0100 Subject: [PATCH 091/154] adjust `RankNotch` gap size to match original value --- osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 9606c2bf22..31ce3ddf95 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -88,7 +88,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// /// The width of a in terms of accuracy. /// - public const double NOTCH_WIDTH_PERCENTAGE = 0.002; + public const double NOTCH_WIDTH_PERCENTAGE = 1.0 / 360; /// /// The easing for the circle filling transforms. From f1decb667e431e1adc007d830e3cddd7b836dd75 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 8 Feb 2023 17:51:28 -0800 Subject: [PATCH 092/154] Address todos relating to init-only usages --- .../Profile/Header/Components/RankGraph.cs | 10 ++++++---- .../Sections/Historical/UserHistoryGraph.cs | 10 ++++++---- osu.Game/Overlays/Profile/UserGraph.cs | 14 +++----------- .../Tests/Visual/DependencyProvidingContainer.cs | 3 +-- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index fe1069eea1..4f3f1ac2c3 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -66,10 +66,12 @@ namespace osu.Game.Overlays.Profile.Header.Components { int days = ranked_days - index + 1; - return new UserGraphTooltipContent( - UsersStrings.ShowRankGlobalSimple, - rank.ToLocalisableString("\\##,##0"), - days == 0 ? "now" : $"{"day".ToQuantity(days)} ago"); + return new UserGraphTooltipContent + { + Name = UsersStrings.ShowRankGlobalSimple, + Count = rank.ToLocalisableString("\\##,##0"), + Time = days == 0 ? "now" : $"{"day".ToQuantity(days)} ago", + }; } } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs b/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs index 310607e757..0259231001 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs @@ -27,9 +27,11 @@ namespace osu.Game.Overlays.Profile.Sections.Historical protected override float GetDataPointHeight(long playCount) => playCount; protected override UserGraphTooltipContent GetTooltipContent(DateTime date, long playCount) => - new UserGraphTooltipContent( - tooltipCounterName, - playCount.ToLocalisableString("N0"), - date.ToLocalisableString("MMMM yyyy")); + new UserGraphTooltipContent + { + Name = tooltipCounterName, + Count = playCount.ToLocalisableString("N0"), + Time = date.ToLocalisableString("MMMM yyyy") + }; } } diff --git a/osu.Game/Overlays/Profile/UserGraph.cs b/osu.Game/Overlays/Profile/UserGraph.cs index 63cdbea5a4..0a5e6ca710 100644 --- a/osu.Game/Overlays/Profile/UserGraph.cs +++ b/osu.Game/Overlays/Profile/UserGraph.cs @@ -298,16 +298,8 @@ namespace osu.Game.Overlays.Profile public class UserGraphTooltipContent { - // todo: could use init-only properties on C# 9 which read better than a constructor. - public LocalisableString Name { get; } - public LocalisableString Count { get; } - public LocalisableString Time { get; } - - public UserGraphTooltipContent(LocalisableString name, LocalisableString count, LocalisableString time) - { - Name = name; - Count = count; - Time = time; - } + public LocalisableString Name { get; init; } + public LocalisableString Count { get; init; } + public LocalisableString Time { get; init; } } } diff --git a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs index ae0225d8df..acfff4cefe 100644 --- a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs +++ b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs @@ -20,8 +20,7 @@ namespace osu.Game.Tests.Visual /// /// The dependencies provided to the children. /// - // TODO: should be an init-only property when C# 9 - public (Type, object)[] CachedDependencies { get; set; } = Array.Empty<(Type, object)>(); + public (Type, object)[] CachedDependencies { get; init; } = Array.Empty<(Type, object)>(); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { From cf009432cc5af59b8a35e809468ece6472eb2561 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Feb 2023 15:41:45 +0900 Subject: [PATCH 093/154] Centralise accuracy cutoff constants and add lookup helper methods --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 93 +++++++++++++++---- .../Expanded/Accuracy/AccuracyCircle.cs | 18 ++-- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b5f42ec2cc..1e03a3ff80 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -7,21 +7,28 @@ using System.Diagnostics; using System.Diagnostics.Contracts; using System.Linq; using osu.Framework.Bindables; +using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Extensions; +using osu.Game.Localisation; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Replays; using osu.Game.Scoring; -using osu.Framework.Localisation; -using osu.Game.Localisation; namespace osu.Game.Rulesets.Scoring { public partial class ScoreProcessor : JudgementProcessor { + private const double accuracy_cutoff_x = 1; + private const double accuracy_cutoff_s = 0.95; + private const double accuracy_cutoff_a = 0.9; + private const double accuracy_cutoff_b = 0.8; + private const double accuracy_cutoff_c = 0.7; + private const double accuracy_cutoff_d = 0; + private const double max_score = 1000000; /// @@ -160,7 +167,7 @@ namespace osu.Game.Rulesets.Scoring Combo.ValueChanged += combo => HighestCombo.Value = Math.Max(HighestCombo.Value, combo.NewValue); Accuracy.ValueChanged += accuracy => { - Rank.Value = rankFrom(accuracy.NewValue); + Rank.Value = RankFromAccuracy(accuracy.NewValue); foreach (var mod in Mods.Value.OfType()) Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue); }; @@ -369,22 +376,6 @@ namespace osu.Game.Rulesets.Scoring } } - private ScoreRank rankFrom(double acc) - { - if (acc == 1) - return ScoreRank.X; - if (acc >= 0.95) - return ScoreRank.S; - if (acc >= 0.9) - return ScoreRank.A; - if (acc >= 0.8) - return ScoreRank.B; - if (acc >= 0.7) - return ScoreRank.C; - - return ScoreRank.D; - } - /// /// Resets this ScoreProcessor to a default state. /// @@ -583,6 +574,70 @@ namespace osu.Game.Rulesets.Scoring hitEvents.Clear(); } + #region Static helper methods + + /// + /// Given an accuracy (0..1), return the correct . + /// + public static ScoreRank RankFromAccuracy(double accuracy) + { + switch (accuracy) + { + case accuracy_cutoff_x: + return ScoreRank.X; + + case >= accuracy_cutoff_s: + return ScoreRank.S; + + case >= accuracy_cutoff_a: + return ScoreRank.A; + + case >= accuracy_cutoff_b: + return ScoreRank.B; + + case >= accuracy_cutoff_c: + return ScoreRank.C; + + default: + return ScoreRank.D; + } + } + + /// + /// Given a , return the cutoff accuracy (0..1). + /// Accuracy must be great or equal to the cutoff to qualify for the provided rank. + /// + public static double AccuracyCutoffFromRank(ScoreRank rank) + { + switch (rank) + { + case ScoreRank.X: + case ScoreRank.XH: + return accuracy_cutoff_x; + + case ScoreRank.S: + case ScoreRank.SH: + return accuracy_cutoff_s; + + case ScoreRank.A: + return accuracy_cutoff_a; + + case ScoreRank.B: + return accuracy_cutoff_b; + + case ScoreRank.C: + return accuracy_cutoff_c; + + case ScoreRank.D: + return accuracy_cutoff_d; + + default: + throw new ArgumentOutOfRangeException(nameof(rank), rank, null); + } + } + + #endregion + /// /// Stores the required scoring data that fulfils the minimum requirements for a to calculate score. /// diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 31ce3ddf95..2ec4270c3c 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -17,6 +17,7 @@ using osu.Framework.Utils; using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; using osuTK; @@ -28,17 +29,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// public partial class AccuracyCircle : CompositeDrawable { - private const double accuracy_x = 1; - - private const double accuracy_s = 0.95; - - private const double accuracy_a = 0.9; - - private const double accuracy_b = 0.8; - - private const double accuracy_c = 0.7; - - private const double accuracy_d = 0; + private static readonly double accuracy_x = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.X); + private static readonly double accuracy_s = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.S); + private static readonly double accuracy_a = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.A); + private static readonly double accuracy_b = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.B); + private static readonly double accuracy_c = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.C); + private static readonly double accuracy_d = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.D); /// /// Duration for the transforms causing this component to appear. From 92eb6b6717852dfeb7f3babcadc5a707af4423bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Feb 2023 15:41:55 +0900 Subject: [PATCH 094/154] Simplify `TestSceneAccuracyCircle` test specifications --- .../Visual/Ranking/TestSceneAccuracyCircle.cs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs index f94cf9eb58..bf18bd3e51 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs @@ -24,26 +24,26 @@ namespace osu.Game.Tests.Visual.Ranking { public partial class TestSceneAccuracyCircle : OsuTestScene { - [TestCase(0, ScoreRank.D)] - [TestCase(0.2, ScoreRank.D)] - [TestCase(0.5, ScoreRank.D)] - [TestCase(0.6999, ScoreRank.D)] - [TestCase(0.7, ScoreRank.C)] - [TestCase(0.75, ScoreRank.C)] - [TestCase(0.7999, ScoreRank.C)] - [TestCase(0.8, ScoreRank.B)] - [TestCase(0.85, ScoreRank.B)] - [TestCase(0.8999, ScoreRank.B)] - [TestCase(0.9, ScoreRank.A)] - [TestCase(0.925, ScoreRank.A)] - [TestCase(0.9499, ScoreRank.A)] - [TestCase(0.95, ScoreRank.S)] - [TestCase(0.975, ScoreRank.S)] - [TestCase(0.9999, ScoreRank.S)] - [TestCase(1, ScoreRank.X)] - public void TestRank(double accuracy, ScoreRank rank) + [TestCase(0)] + [TestCase(0.2)] + [TestCase(0.5)] + [TestCase(0.6999)] + [TestCase(0.7)] + [TestCase(0.75)] + [TestCase(0.7999)] + [TestCase(0.8)] + [TestCase(0.85)] + [TestCase(0.8999)] + [TestCase(0.9)] + [TestCase(0.925)] + [TestCase(0.9499)] + [TestCase(0.95)] + [TestCase(0.975)] + [TestCase(0.9999)] + [TestCase(1)] + public void TestRank(double accuracy) { - var score = createScore(accuracy, rank); + var score = createScore(accuracy, ScoreProcessor.RankFromAccuracy(accuracy)); addCircleStep(score); } From 34d1890f1c85089168b6e69f16532b0edfb09447 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Feb 2023 17:57:51 +0900 Subject: [PATCH 095/154] Change snapping to only apply to classic mod --- osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs | 10 +++++++++- .../Objects/Drawables/DrawableHit.cs | 3 ++- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs index 2ccdfd40e5..300c72a854 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs @@ -2,13 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Taiko.Mods { - public class TaikoModClassic : ModClassic, IApplicableToDrawableRuleset + public class TaikoModClassic : ModClassic, IApplicableToDrawableRuleset, IApplicableToDrawableHitObject { public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { @@ -18,5 +20,11 @@ namespace osu.Game.Rulesets.Taiko.Mods var playfield = (TaikoPlayfield)drawableRuleset.Playfield; playfield.ClassicHitTargetPosition.Value = true; } + + public void ApplyToDrawableHitObject(DrawableHitObject drawable) + { + if (drawable is DrawableHit) + drawable.SnapJudgementLocation = true; + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index ef87522eea..62c8457c58 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -207,7 +207,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables const float gravity_time = 300; const float gravity_travel_height = 200; - MainPiece.MoveToX(-X); // Visually snap hit object to hit target + if (SnapJudgementLocation) + MainPiece.MoveToX(-X); this.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 39f0888882..01550a113f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -662,6 +662,15 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual double MaximumJudgementOffset => HitObject.HitWindows?.WindowFor(HitResult.Miss) ?? 0; + /// + /// Whether the location of the hit should be snapped to the hit target before animating. + /// + /// + /// This is how osu-stable worked, but notably is not how TnT works. + /// It results in less visual feedback on hit accuracy. + /// + public bool SnapJudgementLocation { get; set; } + /// /// Applies the of this , notifying responders such as /// the of the . From 2c1154afc67966742980e498a89adca96698031f Mon Sep 17 00:00:00 2001 From: Ruki Date: Thu, 9 Feb 2023 17:15:30 +0000 Subject: [PATCH 096/154] refactor: improve wording Co-authored-by: Joseph Madamba --- osu.Game/Users/UserActivity.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 0e6e3ca5f2..b1c3fac382 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -105,12 +105,12 @@ namespace osu.Game.Users this.score = score; } - public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Watching a game" : $@"Watching {Username}"; + public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Watching a replay" : $@"Watching {Username}'s replay"; } public class Spectating : Watching { - public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Spectating a game" : $@"Spectating {Username}"; + public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Spectating a user" : $@"Spectating {Username}"; public Spectating(ScoreInfo score) : base(score) From 2e2ab4081bdb293e927e89412024d4ec49509fd3 Mon Sep 17 00:00:00 2001 From: sw1tchbl4d3 Date: Thu, 9 Feb 2023 21:22:34 +0100 Subject: [PATCH 097/154] Make `LargeBonus` a valid `HitResult` in taiko --- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 9944c0c6b7..4f435e73b3 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -209,9 +209,8 @@ namespace osu.Game.Rulesets.Taiko HitResult.Great, HitResult.Ok, - HitResult.SmallTickHit, - HitResult.SmallBonus, + HitResult.LargeBonus, }; } @@ -220,6 +219,9 @@ namespace osu.Game.Rulesets.Taiko switch (result) { case HitResult.SmallBonus: + return "drum tick"; + + case HitResult.LargeBonus: return "bonus"; } From 0b41dbf579564149ba596fdb03f639b109dc3cf2 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 9 Feb 2023 12:59:26 -0800 Subject: [PATCH 098/154] Remove code bloat from `ClickableAvatar` --- osu.Game/Users/Drawables/ClickableAvatar.cs | 46 +++----------------- osu.Game/Users/Drawables/UpdateableAvatar.cs | 1 - 2 files changed, 5 insertions(+), 42 deletions(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 5a3009dfcd..4f4c69be83 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -4,26 +4,17 @@ #nullable disable using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Users.Drawables { - public partial class ClickableAvatar : Container + public partial class ClickableAvatar : OsuClickableContainer { private const string default_tooltip_text = "view profile"; - /// - /// Whether to open the user's profile when clicked. - /// - public bool OpenOnClick - { - set => clickableArea.Enabled.Value = clickableArea.Action != null && value; - } + public override LocalisableString TooltipText { get; set; } = default_tooltip_text; /// /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. @@ -31,7 +22,7 @@ namespace osu.Game.Users.Drawables /// public bool ShowUsernameTooltip { - set => clickableArea.TooltipText = value ? (user?.Username ?? string.Empty) : default_tooltip_text; + set => TooltipText = value ? (user?.Username ?? string.Empty) : default_tooltip_text; } private readonly APIUser user; @@ -39,30 +30,22 @@ namespace osu.Game.Users.Drawables [Resolved(CanBeNull = true)] private OsuGame game { get; set; } - private readonly ClickableArea clickableArea; - /// /// A clickable avatar for the specified user, with UI sounds included. - /// If is true, clicking will open the user's profile. /// /// The user. A null value will get a placeholder avatar. public ClickableAvatar(APIUser user = null) { this.user = user; - Add(clickableArea = new ClickableArea - { - RelativeSizeAxes = Axes.Both, - }); - if (user?.Id != APIUser.SYSTEM_USER_ID) - clickableArea.Action = openProfile; + Action = openProfile; } [BackgroundDependencyLoader] private void load() { - LoadComponentAsync(new DrawableAvatar(user), clickableArea.Add); + LoadComponentAsync(new DrawableAvatar(user), Add); } private void openProfile() @@ -70,24 +53,5 @@ namespace osu.Game.Users.Drawables if (user?.Id > 1 || !string.IsNullOrEmpty(user?.Username)) game?.ShowUser(user); } - - private partial class ClickableArea : OsuClickableContainer - { - private LocalisableString tooltip = default_tooltip_text; - - public override LocalisableString TooltipText - { - get => Enabled.Value ? tooltip : default; - set => tooltip = value; - } - - protected override bool OnClick(ClickEvent e) - { - if (!Enabled.Value) - return false; - - return base.OnClick(e); - } - } } } diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 9c04eb5706..9611156624 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -76,7 +76,6 @@ namespace osu.Game.Users.Drawables { return new ClickableAvatar(user) { - OpenOnClick = true, ShowUsernameTooltip = showUsernameTooltip, RelativeSizeAxes = Axes.Both, }; From f0d11f44fc8191d6231056b1a5636757e8d0aef6 Mon Sep 17 00:00:00 2001 From: sw1tchbl4d3 Date: Thu, 9 Feb 2023 22:18:12 +0100 Subject: [PATCH 099/154] Always add to additions soundbank in `convertSoundType` --- .../Objects/Legacy/ConvertHitObjectParser.cs | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 930ee0448f..68ca6bc506 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -439,19 +439,20 @@ namespace osu.Game.Rulesets.Objects.Legacy private List convertSoundType(LegacyHitSoundType type, SampleBankInfo bankInfo) { - // Todo: This should return the normal SampleInfos if the specified sample file isn't found, but that's a pretty edge-case scenario - if (!string.IsNullOrEmpty(bankInfo.Filename)) - { - return new List { new FileHitSampleInfo(bankInfo.Filename, bankInfo.Volume) }; - } + var soundTypes = new List(); - var soundTypes = new List + if (string.IsNullOrEmpty(bankInfo.Filename)) { - new LegacyHitSampleInfo(HitSampleInfo.HIT_NORMAL, bankInfo.BankForNormal, bankInfo.Volume, bankInfo.CustomSampleBank, - // if the sound type doesn't have the Normal flag set, attach it anyway as a layered sample. - // None also counts as a normal non-layered sample: https://osu.ppy.sh/help/wiki/osu!_File_Formats/Osu_(file_format)#hitsounds - type != LegacyHitSoundType.None && !type.HasFlagFast(LegacyHitSoundType.Normal)) - }; + soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_NORMAL, bankInfo.BankForNormal, bankInfo.Volume, bankInfo.CustomSampleBank, + // if the sound type doesn't have the Normal flag set, attach it anyway as a layered sample. + // None also counts as a normal non-layered sample: https://osu.ppy.sh/help/wiki/osu!_File_Formats/Osu_(file_format)#hitsounds + type != LegacyHitSoundType.None && !type.HasFlagFast(LegacyHitSoundType.Normal))); + } + else + { + // Todo: This should set the normal SampleInfo if the specified sample file isn't found, but that's a pretty edge-case scenario + soundTypes.Add(new FileHitSampleInfo(bankInfo.Filename, bankInfo.Volume)); + } if (type.HasFlagFast(LegacyHitSoundType.Finish)) soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_FINISH, bankInfo.BankForAdditions, bankInfo.Volume, bankInfo.CustomSampleBank)); From 51816b92c6a2264653ec553c9509e575af5aa3f1 Mon Sep 17 00:00:00 2001 From: sw1tchbl4d3 Date: Thu, 9 Feb 2023 23:23:58 +0100 Subject: [PATCH 100/154] Add conversion tests --- .../TaikoBeatmapConversionTest.cs | 1 + .../file-hitsamples-expected-conversion.json | 1 + .../Testing/Beatmaps/file-hitsamples.osu | 22 +++++++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/file-hitsamples-expected-conversion.json create mode 100644 osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/file-hitsamples.osu diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 796f5721bb..781a686700 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Tests [TestCase("slider-conversion-v6")] [TestCase("slider-conversion-v14")] [TestCase("slider-generating-drumroll-2")] + [TestCase("file-hitsamples")] public void Test(string name) => base.Test(name); protected override IEnumerable CreateConvertValue(HitObject hitObject) diff --git a/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/file-hitsamples-expected-conversion.json b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/file-hitsamples-expected-conversion.json new file mode 100644 index 0000000000..70348a3871 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/file-hitsamples-expected-conversion.json @@ -0,0 +1 @@ +{"Mappings":[{"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"IsRim":false,"IsCentre":true,"IsDrumRoll":false,"IsSwell":false,"IsStrong":false}]},{"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"IsRim":true,"IsCentre":false,"IsDrumRoll":false,"IsSwell":false,"IsStrong":false}]},{"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"IsRim":true,"IsCentre":false,"IsDrumRoll":false,"IsSwell":false,"IsStrong":false}]},{"StartTime":2000.0,"Objects":[{"StartTime":2000.0,"EndTime":2000.0,"IsRim":true,"IsCentre":false,"IsDrumRoll":false,"IsSwell":false,"IsStrong":false}]},{"StartTime":2500.0,"Objects":[{"StartTime":2500.0,"EndTime":2500.0,"IsRim":false,"IsCentre":true,"IsDrumRoll":false,"IsSwell":false,"IsStrong":true}]},{"StartTime":3000.0,"Objects":[{"StartTime":3000.0,"EndTime":3000.0,"IsRim":true,"IsCentre":false,"IsDrumRoll":false,"IsSwell":false,"IsStrong":true}]},{"StartTime":3500.0,"Objects":[{"StartTime":3500.0,"EndTime":3500.0,"IsRim":true,"IsCentre":false,"IsDrumRoll":false,"IsSwell":false,"IsStrong":true}]},{"StartTime":4000.0,"Objects":[{"StartTime":4000.0,"EndTime":4000.0,"IsRim":true,"IsCentre":false,"IsDrumRoll":false,"IsSwell":false,"IsStrong":true}]}]} \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/file-hitsamples.osu b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/file-hitsamples.osu new file mode 100644 index 0000000000..5d4bcb52a1 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/file-hitsamples.osu @@ -0,0 +1,22 @@ +osu file format v14 + +[Difficulty] +HPDrainRate:5 +CircleSize:7 +OverallDifficulty:6.5 +ApproachRate:10 +SliderMultiplier:1.9 +SliderTickRate:1 + +[TimingPoints] +500,500,4,2,1,50,1,0 + +[HitObjects] +256,192,500,1,0,0:0:0:0:sample.ogg +256,192,1000,1,8,0:0:0:0:sample.ogg +256,192,1500,1,2,0:0:0:0:sample.ogg +256,192,2000,1,10,0:0:0:0:sample.ogg +256,192,2500,1,4,0:0:0:0:sample.ogg +256,192,3000,1,12,0:0:0:0:sample.ogg +256,192,3500,1,6,0:0:0:0:sample.ogg +256,192,4000,1,14,0:0:0:0:sample.ogg From 96c1832af407a9f8cf3d014ea6f4f17e609b02eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 10 Feb 2023 00:07:24 +0100 Subject: [PATCH 101/154] Fix grammar in xmldoc Co-authored-by: Walavouchey <36758269+Walavouchey@users.noreply.github.com> --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 1e03a3ff80..7fc8980cf5 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -605,7 +605,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Given a , return the cutoff accuracy (0..1). - /// Accuracy must be great or equal to the cutoff to qualify for the provided rank. + /// Accuracy must be greater than or equal to the cutoff to qualify for the provided rank. /// public static double AccuracyCutoffFromRank(ScoreRank rank) { From a86f06df96aec0d499585666127ce17a17e9920b Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 9 Feb 2023 16:09:38 -0800 Subject: [PATCH 102/154] Add back `Enabled` checks to `TooltipText` and `OnClick` to fix guest case --- osu.Game/Users/Drawables/ClickableAvatar.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 4f4c69be83..475d1c616e 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -4,6 +4,7 @@ #nullable disable using osu.Framework.Allocation; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; @@ -14,7 +15,13 @@ namespace osu.Game.Users.Drawables { private const string default_tooltip_text = "view profile"; - public override LocalisableString TooltipText { get; set; } = default_tooltip_text; + private LocalisableString tooltip = default_tooltip_text; + + public override LocalisableString TooltipText + { + get => Enabled.Value ? tooltip : default; + set => tooltip = value; + } /// /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. @@ -53,5 +60,13 @@ namespace osu.Game.Users.Drawables if (user?.Id > 1 || !string.IsNullOrEmpty(user?.Username)) game?.ShowUser(user); } + + protected override bool OnClick(ClickEvent e) + { + if (!Enabled.Value) + return false; + + return base.OnClick(e); + } } } From 68c37585e53b16203b2ec7b68e0cf58b4bf385f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 16:22:06 +0900 Subject: [PATCH 103/154] Use `string.Empty` instead of `default` --- osu.Game/Users/Drawables/ClickableAvatar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 475d1c616e..76adf49913 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -19,7 +19,7 @@ namespace osu.Game.Users.Drawables public override LocalisableString TooltipText { - get => Enabled.Value ? tooltip : default; + get => Enabled.Value ? tooltip : string.Empty; set => tooltip = value; } From 5866b67a5b53c6a7f0df477e8b0a1daa8d388d21 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 16:24:44 +0900 Subject: [PATCH 104/154] Simplify tooltip implementation --- osu.Game/Users/Drawables/ClickableAvatar.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 76adf49913..e13fb6a819 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Framework.Localisation; @@ -15,22 +16,23 @@ namespace osu.Game.Users.Drawables { private const string default_tooltip_text = "view profile"; - private LocalisableString tooltip = default_tooltip_text; - public override LocalisableString TooltipText { - get => Enabled.Value ? tooltip : string.Empty; - set => tooltip = value; + get + { + if (!Enabled.Value) + return string.Empty; + + return ShowUsernameTooltip ? (user?.Username ?? string.Empty) : default_tooltip_text; + } + set => throw new InvalidOperationException(); } /// /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. /// Setting this to true exposes the username via tooltip for special cases where this is not true. /// - public bool ShowUsernameTooltip - { - set => TooltipText = value ? (user?.Username ?? string.Empty) : default_tooltip_text; - } + public bool ShowUsernameTooltip { get; set; } private readonly APIUser user; From 199fb0fd8563e1baa242428fa75b9560b6dc3704 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 16:25:14 +0900 Subject: [PATCH 105/154] Apply NRT to `ClickableAvatar` and `UpdateableAvatar` --- osu.Game/Users/Drawables/ClickableAvatar.cs | 10 ++++------ osu.Game/Users/Drawables/UpdateableAvatar.cs | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index e13fb6a819..bb57958239 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Input.Events; @@ -34,16 +32,16 @@ namespace osu.Game.Users.Drawables /// public bool ShowUsernameTooltip { get; set; } - private readonly APIUser user; + private readonly APIUser? user; - [Resolved(CanBeNull = true)] - private OsuGame game { get; set; } + [Resolved] + private OsuGame? game { get; set; } /// /// A clickable avatar for the specified user, with UI sounds included. /// /// The user. A null value will get a placeholder avatar. - public ClickableAvatar(APIUser user = null) + public ClickableAvatar(APIUser? user = null) { this.user = user; diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 9611156624..c659685807 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; @@ -13,9 +11,9 @@ namespace osu.Game.Users.Drawables /// /// An avatar which can update to a new user when needed. /// - public partial class UpdateableAvatar : ModelBackedDrawable + public partial class UpdateableAvatar : ModelBackedDrawable { - public APIUser User + public APIUser? User { get => Model; set => Model = value; @@ -58,7 +56,7 @@ namespace osu.Game.Users.Drawables /// If set to true, hover/click sounds will play and clicking the avatar will open the user's profile. /// Whether to show the username rather than "view profile" on the tooltip. (note: this only applies if is also true) /// Whether to show a default guest representation on null user (as opposed to nothing). - public UpdateableAvatar(APIUser user = null, bool isInteractive = true, bool showUsernameTooltip = false, bool showGuestOnNull = true) + public UpdateableAvatar(APIUser? user = null, bool isInteractive = true, bool showUsernameTooltip = false, bool showGuestOnNull = true) { this.isInteractive = isInteractive; this.showUsernameTooltip = showUsernameTooltip; @@ -67,7 +65,7 @@ namespace osu.Game.Users.Drawables User = user; } - protected override Drawable CreateDrawable(APIUser user) + protected override Drawable? CreateDrawable(APIUser? user) { if (user == null && !showGuestOnNull) return null; From 1df6fc631104e0338eeced59f6b7fa91836ac9a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 17:03:27 +0900 Subject: [PATCH 106/154] Use `if` statements rather than conditional `case` --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 30 ++++++++------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 7fc8980cf5..96f6922224 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -581,26 +581,18 @@ namespace osu.Game.Rulesets.Scoring /// public static ScoreRank RankFromAccuracy(double accuracy) { - switch (accuracy) - { - case accuracy_cutoff_x: - return ScoreRank.X; + if (accuracy == accuracy_cutoff_x) + return ScoreRank.X; + if (accuracy >= accuracy_cutoff_s) + return ScoreRank.S; + if (accuracy >= accuracy_cutoff_a) + return ScoreRank.A; + if (accuracy >= accuracy_cutoff_b) + return ScoreRank.B; + if (accuracy >= accuracy_cutoff_c) + return ScoreRank.C; - case >= accuracy_cutoff_s: - return ScoreRank.S; - - case >= accuracy_cutoff_a: - return ScoreRank.A; - - case >= accuracy_cutoff_b: - return ScoreRank.B; - - case >= accuracy_cutoff_c: - return ScoreRank.C; - - default: - return ScoreRank.D; - } + return ScoreRank.D; } /// From 03e623d1d221ff30159f6940c60f3adc484afe23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 17:37:31 +0900 Subject: [PATCH 107/154] Move `ControlPointList` to own file --- .../Screens/Edit/Timing/ControlPointList.cs | 209 ++++++++++++++++++ osu.Game/Screens/Edit/Timing/TimingScreen.cs | 198 ----------------- 2 files changed, 209 insertions(+), 198 deletions(-) create mode 100644 osu.Game/Screens/Edit/Timing/ControlPointList.cs diff --git a/osu.Game/Screens/Edit/Timing/ControlPointList.cs b/osu.Game/Screens/Edit/Timing/ControlPointList.cs new file mode 100644 index 0000000000..555c36aac0 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/ControlPointList.cs @@ -0,0 +1,209 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays; +using osuTK; + +namespace osu.Game.Screens.Edit.Timing +{ + public partial class ControlPointList : CompositeDrawable + { + private OsuButton deleteButton = null!; + private ControlPointTable table = null!; + private OsuScrollContainer scroll = null!; + private RoundedButton addButton = null!; + + private readonly IBindableList controlPointGroups = new BindableList(); + + [Resolved] + private EditorClock clock { get; set; } = null!; + + [Resolved] + protected EditorBeatmap Beatmap { get; private set; } = null!; + + [Resolved] + private Bindable selectedGroup { get; set; } = null!; + + [Resolved] + private IEditorChangeHandler? changeHandler { get; set; } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colours) + { + RelativeSizeAxes = Axes.Both; + + const float margins = 10; + InternalChildren = new Drawable[] + { + new Box + { + Colour = colours.Background4, + RelativeSizeAxes = Axes.Both, + }, + new Box + { + Colour = colours.Background3, + RelativeSizeAxes = Axes.Y, + Width = ControlPointTable.TIMING_COLUMN_WIDTH + margins, + }, + scroll = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = table = new ControlPointTable(), + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding(margins), + Spacing = new Vector2(5), + Children = new Drawable[] + { + deleteButton = new RoundedButton + { + Text = "-", + Size = new Vector2(30, 30), + Action = delete, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + }, + addButton = new RoundedButton + { + Action = addNew, + Size = new Vector2(160, 30), + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + }, + } + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedGroup.BindValueChanged(selected => + { + deleteButton.Enabled.Value = selected.NewValue != null; + + addButton.Text = selected.NewValue != null + ? "+ Clone to current time" + : "+ Add at current time"; + }, true); + + controlPointGroups.BindTo(Beatmap.ControlPointInfo.Groups); + controlPointGroups.BindCollectionChanged((_, _) => + { + table.ControlGroups = controlPointGroups; + changeHandler?.SaveState(); + }, true); + + table.OnRowSelected += drawable => scroll.ScrollIntoView(drawable); + } + + protected override bool OnClick(ClickEvent e) + { + selectedGroup.Value = null; + return true; + } + + protected override void Update() + { + base.Update(); + + trackActivePoint(); + + addButton.Enabled.Value = clock.CurrentTimeAccurate != selectedGroup.Value?.Time; + } + + private Type? trackedType; + + /// + /// Given the user has selected a control point group, we want to track any group which is + /// active at the current point in time which matches the type the user has selected. + /// + /// So if the user is currently looking at a timing point and seeks into the future, a + /// future timing point would be automatically selected if it is now the new "current" point. + /// + private void trackActivePoint() + { + // For simplicity only match on the first type of the active control point. + if (selectedGroup.Value == null) + trackedType = null; + else + { + // If the selected group only has one control point, update the tracking type. + if (selectedGroup.Value.ControlPoints.Count == 1) + trackedType = selectedGroup.Value?.ControlPoints.Single().GetType(); + // If the selected group has more than one control point, choose the first as the tracking type + // if we don't already have a singular tracked type. + else if (trackedType == null) + trackedType = selectedGroup.Value?.ControlPoints.FirstOrDefault()?.GetType(); + } + + if (trackedType != null) + { + // We don't have an efficient way of looking up groups currently, only individual point types. + // To improve the efficiency of this in the future, we should reconsider the overall structure of ControlPointInfo. + + // Find the next group which has the same type as the selected one. + var found = Beatmap.ControlPointInfo.Groups + .Where(g => g.ControlPoints.Any(cp => cp.GetType() == trackedType)) + .LastOrDefault(g => g.Time <= clock.CurrentTimeAccurate); + + if (found != null) + selectedGroup.Value = found; + } + } + + private void delete() + { + if (selectedGroup.Value == null) + return; + + Beatmap.ControlPointInfo.RemoveGroup(selectedGroup.Value); + + selectedGroup.Value = Beatmap.ControlPointInfo.Groups.FirstOrDefault(g => g.Time >= clock.CurrentTime); + } + + private void addNew() + { + bool isFirstControlPoint = !Beatmap.ControlPointInfo.TimingPoints.Any(); + + var group = Beatmap.ControlPointInfo.GroupAt(clock.CurrentTime, true); + + if (isFirstControlPoint) + group.Add(new TimingControlPoint()); + else + { + // Try and create matching types from the currently selected control point. + var selected = selectedGroup.Value; + + if (selected != null && !ReferenceEquals(selected, group)) + { + foreach (var controlPoint in selected.ControlPoints) + { + group.Add(controlPoint.DeepClone()); + } + } + } + + selectedGroup.Value = group; + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 2450909929..a948da10cd 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,20 +1,11 @@ // 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 osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; -using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Overlays; -using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -45,194 +36,5 @@ namespace osu.Game.Screens.Edit.Timing }, } }; - - public partial class ControlPointList : CompositeDrawable - { - private OsuButton deleteButton = null!; - private ControlPointTable table = null!; - private OsuScrollContainer scroll = null!; - private RoundedButton addButton = null!; - - private readonly IBindableList controlPointGroups = new BindableList(); - - [Resolved] - private EditorClock clock { get; set; } = null!; - - [Resolved] - protected EditorBeatmap Beatmap { get; private set; } = null!; - - [Resolved] - private Bindable selectedGroup { get; set; } = null!; - - [Resolved] - private IEditorChangeHandler? changeHandler { get; set; } - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colours) - { - RelativeSizeAxes = Axes.Both; - - const float margins = 10; - InternalChildren = new Drawable[] - { - new Box - { - Colour = colours.Background4, - RelativeSizeAxes = Axes.Both, - }, - new Box - { - Colour = colours.Background3, - RelativeSizeAxes = Axes.Y, - Width = ControlPointTable.TIMING_COLUMN_WIDTH + margins, - }, - scroll = new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = table = new ControlPointTable(), - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Direction = FillDirection.Horizontal, - Margin = new MarginPadding(margins), - Spacing = new Vector2(5), - Children = new Drawable[] - { - deleteButton = new RoundedButton - { - Text = "-", - Size = new Vector2(30, 30), - Action = delete, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - }, - addButton = new RoundedButton - { - Action = addNew, - Size = new Vector2(160, 30), - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - }, - } - }, - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - selectedGroup.BindValueChanged(selected => - { - deleteButton.Enabled.Value = selected.NewValue != null; - - addButton.Text = selected.NewValue != null - ? "+ Clone to current time" - : "+ Add at current time"; - }, true); - - controlPointGroups.BindTo(Beatmap.ControlPointInfo.Groups); - controlPointGroups.BindCollectionChanged((_, _) => - { - table.ControlGroups = controlPointGroups; - changeHandler?.SaveState(); - }, true); - - table.OnRowSelected += drawable => scroll.ScrollIntoView(drawable); - } - - protected override bool OnClick(ClickEvent e) - { - selectedGroup.Value = null; - return true; - } - - protected override void Update() - { - base.Update(); - - trackActivePoint(); - - addButton.Enabled.Value = clock.CurrentTimeAccurate != selectedGroup.Value?.Time; - } - - private Type? trackedType; - - /// - /// Given the user has selected a control point group, we want to track any group which is - /// active at the current point in time which matches the type the user has selected. - /// - /// So if the user is currently looking at a timing point and seeks into the future, a - /// future timing point would be automatically selected if it is now the new "current" point. - /// - private void trackActivePoint() - { - // For simplicity only match on the first type of the active control point. - if (selectedGroup.Value == null) - trackedType = null; - else - { - // If the selected group only has one control point, update the tracking type. - if (selectedGroup.Value.ControlPoints.Count == 1) - trackedType = selectedGroup.Value?.ControlPoints.Single().GetType(); - // If the selected group has more than one control point, choose the first as the tracking type - // if we don't already have a singular tracked type. - else if (trackedType == null) - trackedType = selectedGroup.Value?.ControlPoints.FirstOrDefault()?.GetType(); - } - - if (trackedType != null) - { - // We don't have an efficient way of looking up groups currently, only individual point types. - // To improve the efficiency of this in the future, we should reconsider the overall structure of ControlPointInfo. - - // Find the next group which has the same type as the selected one. - var found = Beatmap.ControlPointInfo.Groups - .Where(g => g.ControlPoints.Any(cp => cp.GetType() == trackedType)) - .LastOrDefault(g => g.Time <= clock.CurrentTimeAccurate); - - if (found != null) - selectedGroup.Value = found; - } - } - - private void delete() - { - if (selectedGroup.Value == null) - return; - - Beatmap.ControlPointInfo.RemoveGroup(selectedGroup.Value); - - selectedGroup.Value = Beatmap.ControlPointInfo.Groups.FirstOrDefault(g => g.Time >= clock.CurrentTime); - } - - private void addNew() - { - bool isFirstControlPoint = !Beatmap.ControlPointInfo.TimingPoints.Any(); - - var group = Beatmap.ControlPointInfo.GroupAt(clock.CurrentTime, true); - - if (isFirstControlPoint) - group.Add(new TimingControlPoint()); - else - { - // Try and create matching types from the currently selected control point. - var selected = selectedGroup.Value; - - if (selected != null && !ReferenceEquals(selected, group)) - { - foreach (var controlPoint in selected.ControlPoints) - { - group.Add(controlPoint.DeepClone()); - } - } - } - - selectedGroup.Value = group; - } - } } } From 6d876fdb9af03782e74420c752cd40bed7394156 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 17:44:05 +0900 Subject: [PATCH 108/154] Automatically select the closest timing point on entering the timing screen --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index a948da10cd..5d75ae2db5 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -14,6 +14,9 @@ namespace osu.Game.Screens.Edit.Timing [Cached] public readonly Bindable SelectedGroup = new Bindable(); + [Resolved] + private EditorClock? editorClock { get; set; } + public TimingScreen() : base(EditorScreenMode.Timing) { @@ -36,5 +39,19 @@ namespace osu.Game.Screens.Edit.Timing }, } }; + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (editorClock != null) + { + // When entering the timing screen, let's choose to closest valid timing point. + // This will emulate the osu-stable behaviour where a metronome and timing information + // are presented on entering the screen. + var nearestTimingPoint = EditorBeatmap.ControlPointInfo.TimingPointAt(editorClock.CurrentTime); + SelectedGroup.Value = EditorBeatmap.ControlPointInfo.GroupAt(nearestTimingPoint.Time); + } + } } } From 4f7d26b776a15b38f8ed8a2534dc7b1f3d2a80eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 18:29:39 +0900 Subject: [PATCH 109/154] Actually apply new parameter --- osu.Game/Online/Chat/ChannelManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 701a1cd040..e95bc128c8 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -583,7 +583,8 @@ namespace osu.Game.Online.Chat if (channel.Joined.Value) { - api.Queue(new LeaveChannelRequest(channel)); + if (sendLeaveRequest) + api.Queue(new LeaveChannelRequest(channel)); channel.Joined.Value = false; } } From 96fbd04698655ad7bb68f6048a2eb2e432b5a02a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 18:56:00 +0900 Subject: [PATCH 110/154] Add failing test coverage of skip no longer working in replay playback --- .../Visual/Gameplay/TestSceneReplayPlayer.cs | 82 +++++++++++++++---- .../Visual/RateAdjustedBeatmapTestScene.cs | 2 - 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs index 334d01f915..3e415af86e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs @@ -1,32 +1,64 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - +using System.Linq; using NUnit.Framework; using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { public partial class TestSceneReplayPlayer : RateAdjustedBeatmapTestScene { - protected TestReplayPlayer Player; - - public override void SetUpSteps() - { - base.SetUpSteps(); - - AddStep("Initialise player", () => Player = CreatePlayer(new OsuRuleset())); - AddStep("Load player", () => LoadScreen(Player)); - AddUntilStep("player loaded", () => Player.IsLoaded); - } + protected TestReplayPlayer Player = null!; [Test] public void TestPauseViaSpace() { + loadPlayerWithBeatmap(); + + double? lastTime = null; + + AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0); + + AddStep("Pause playback with space", () => InputManager.Key(Key.Space)); + + AddAssert("player not exited", () => Player.IsCurrentScreen()); + + AddUntilStep("Time stopped progressing", () => + { + double current = Player.GameplayClockContainer.CurrentTime; + bool changed = lastTime != current; + lastTime = current; + + return !changed; + }); + + AddWaitStep("wait some", 10); + + AddAssert("Time still stopped", () => lastTime == Player.GameplayClockContainer.CurrentTime); + } + + [Test] + public void TestPauseViaSpaceWithSkip() + { + loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) + { + BeatmapInfo = { AudioLeadIn = 60000 } + }); + + AddUntilStep("wait for skip overlay", () => Player.ChildrenOfType().First().IsButtonVisible); + + AddStep("Skip with space", () => InputManager.Key(Key.Space)); + + AddAssert("Player not paused", () => !Player.DrawableRuleset.IsPaused.Value); + double? lastTime = null; AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0); @@ -52,6 +84,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestPauseViaMiddleMouse() { + loadPlayerWithBeatmap(); + double? lastTime = null; AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0); @@ -77,6 +111,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSeekBackwards() { + loadPlayerWithBeatmap(); + double? lastTime = null; AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0); @@ -93,6 +129,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSeekForwards() { + loadPlayerWithBeatmap(); + double? lastTime = null; AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0); @@ -106,12 +144,26 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("Jumped forwards", () => Player.GameplayClockContainer.CurrentTime - lastTime > 500); } - protected TestReplayPlayer CreatePlayer(Ruleset ruleset) + private void loadPlayerWithBeatmap(IBeatmap? beatmap = null) { - Beatmap.Value = CreateWorkingBeatmap(ruleset.RulesetInfo); + AddStep("create player", () => + { + CreatePlayer(new OsuRuleset(), beatmap); + }); + + AddStep("Load player", () => LoadScreen(Player)); + AddUntilStep("player loaded", () => Player.IsLoaded); + } + + protected void CreatePlayer(Ruleset ruleset, IBeatmap? beatmap = null) + { + Beatmap.Value = beatmap != null + ? CreateWorkingBeatmap(beatmap) + : CreateWorkingBeatmap(ruleset.RulesetInfo); + SelectedMods.Value = new[] { ruleset.GetAutoplayMod() }; - return new TestReplayPlayer(false); + Player = new TestReplayPlayer(false); } } } diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index 0f3f9f2199..a77ea80958 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Tests.Visual { /// From 5c795f492f7c284b3ca4657ad1a3bb7133b32e69 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 18:57:21 +0900 Subject: [PATCH 111/154] Reorder game key bindings to allow skip overlay to have precedence over replay controls --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 9d14ce95cf..d580eea248 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -35,8 +35,8 @@ namespace osu.Game.Input.Bindings // It is used to decide the order of precedence, with the earlier items having higher precedence. public override IEnumerable DefaultKeyBindings => GlobalKeyBindings .Concat(EditorKeyBindings) - .Concat(ReplayKeyBindings) .Concat(InGameKeyBindings) + .Concat(ReplayKeyBindings) .Concat(SongSelectKeyBindings) .Concat(AudioControlKeyBindings) // Overlay bindings may conflict with more local cases like the editor so they are checked last. From 61c968d7f8bf51692983e1cddaa175a8d1209878 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 19:18:00 +0900 Subject: [PATCH 112/154] Revert completely incorrect change --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index 05ba2b8f22..2d466b0da8 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -94,8 +94,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy d.Anchor = Anchor.TopCentre; d.RelativeSizeAxes = Axes.Both; d.Size = Vector2.One; - d.FillMode = FillMode.Stretch; - d.Height = minimumColumnWidth / d.DrawWidth * 1.6f; // constant matching stable. // Todo: Wrap? }); From 5091c5000342f40a28a0f81a556ad224d3fd70cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 19:18:17 +0900 Subject: [PATCH 113/154] Change scroll direction logic to not interfere with scale --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index 2d466b0da8..96dbbf6620 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -163,7 +163,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy if (bodySprite != null) { bodySprite.Origin = Anchor.BottomCentre; - bodySprite.Scale = new Vector2(1, -1); + bodySprite.Scale = new Vector2(bodySprite.Scale.X, Math.Abs(bodySprite.Scale.Y) * -1); } if (light != null) @@ -174,7 +174,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy if (bodySprite != null) { bodySprite.Origin = Anchor.TopCentre; - bodySprite.Scale = Vector2.One; + bodySprite.Scale = new Vector2(bodySprite.Scale.X, Math.Abs(bodySprite.Scale.Y)); } if (light != null) From 635e225d19e1a60a9258b6f4274d808004dcf5f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 19:18:41 +0900 Subject: [PATCH 114/154] Add correct lookup for `WidthForNoteHeightScale` --- osu.Game/Skinning/LegacyManiaSkinConfiguration.cs | 2 ++ osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs | 1 + osu.Game/Skinning/LegacyManiaSkinDecoder.cs | 4 +--- osu.Game/Skinning/LegacySkin.cs | 4 ++++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs index 5ed2ddc73c..192d00317b 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs @@ -29,6 +29,8 @@ namespace osu.Game.Skinning public Dictionary ImageLookups = new Dictionary(); + public float WidthForNoteHeightScale; + public readonly float[] ColumnLineWidth; public readonly float[] ColumnSpacing; public readonly float[] ColumnWidth; diff --git a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs index 3ec0ee6006..a73412ffc5 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs @@ -54,6 +54,7 @@ namespace osu.Game.Skinning HoldNoteBodyImage, HoldNoteLightImage, HoldNoteLightScale, + WidthForNoteHeightScale, ExplosionImage, ExplosionScale, ColumnLineColour, diff --git a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs index 0aafdd4db0..7f14d46cb9 100644 --- a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs +++ b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs @@ -115,9 +115,7 @@ namespace osu.Game.Skinning break; case "WidthForNoteHeightScale": - float minWidth = float.Parse(pair.Value, CultureInfo.InvariantCulture) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR; - if (minWidth > 0) - currentConfig.MinimumColumnWidth = minWidth; + currentConfig.WidthForNoteHeightScale = (float.Parse(pair.Value, CultureInfo.InvariantCulture)) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR; break; case string when pair.Key.StartsWith("Colour", StringComparison.Ordinal): diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 5f12d2ce23..ec1b1d8425 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -138,6 +138,10 @@ namespace osu.Game.Skinning Debug.Assert(maniaLookup.ColumnIndex != null); return SkinUtils.As(new Bindable(existing.ColumnWidth[maniaLookup.ColumnIndex.Value])); + case LegacyManiaSkinConfigurationLookups.WidthForNoteHeightScale: + Debug.Assert(maniaLookup.ColumnIndex != null); + return SkinUtils.As(new Bindable(existing.WidthForNoteHeightScale)); + case LegacyManiaSkinConfigurationLookups.ColumnSpacing: Debug.Assert(maniaLookup.ColumnIndex != null); return SkinUtils.As(new Bindable(existing.ColumnSpacing[maniaLookup.ColumnIndex.Value])); From bfbffc4a68284b2d94a43010c8523825490896b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 19:30:41 +0900 Subject: [PATCH 115/154] Add parsing support for mania `NoteBodyStyle` --- osu.Game/Skinning/LegacyManiaSkinConfiguration.cs | 2 ++ .../LegacyManiaSkinConfigurationLookup.cs | 1 + osu.Game/Skinning/LegacyManiaSkinDecoder.cs | 5 +++++ osu.Game/Skinning/LegacyNoteBodyStyle.cs | 15 +++++++++++++++ osu.Game/Skinning/LegacySkin.cs | 10 ++++++++++ 5 files changed, 33 insertions(+) create mode 100644 osu.Game/Skinning/LegacyNoteBodyStyle.cs diff --git a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs index 192d00317b..1ff9988332 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs @@ -43,6 +43,8 @@ namespace osu.Game.Skinning public bool ShowJudgementLine = true; public bool KeysUnderNotes; + public LegacyNoteBodyStyle? NoteBodyStyle; + public LegacyManiaSkinConfiguration(int keys) { Keys = keys; diff --git a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs index a73412ffc5..a2408a92bb 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs @@ -72,5 +72,6 @@ namespace osu.Game.Skinning Hit50, Hit0, KeysUnderNotes, + NoteBodyStyle } } diff --git a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs index 7f14d46cb9..e880e3c1ed 100644 --- a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs +++ b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs @@ -114,6 +114,11 @@ namespace osu.Game.Skinning parseArrayValue(pair.Value, currentConfig.HoldNoteLightWidth); break; + case "NoteBodyStyle": + if (Enum.TryParse(pair.Value, out var style)) + currentConfig.NoteBodyStyle = style; + break; + case "WidthForNoteHeightScale": currentConfig.WidthForNoteHeightScale = (float.Parse(pair.Value, CultureInfo.InvariantCulture)) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR; break; diff --git a/osu.Game/Skinning/LegacyNoteBodyStyle.cs b/osu.Game/Skinning/LegacyNoteBodyStyle.cs new file mode 100644 index 0000000000..788bcc5432 --- /dev/null +++ b/osu.Game/Skinning/LegacyNoteBodyStyle.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Skinning +{ + public enum LegacyNoteBodyStyle + { + Stretch = 0, + RepeatTop = 2, + RepeatBottom = 3, + RepeatTopAndBottom = 4, + //Repeat = 1, + //RepeatMiddle = 5, + } +} diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index ec1b1d8425..b2619fa55b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -189,6 +189,16 @@ namespace osu.Game.Skinning case LegacyManiaSkinConfigurationLookups.MinimumColumnWidth: return SkinUtils.As(new Bindable(existing.MinimumColumnWidth)); + case LegacyManiaSkinConfigurationLookups.NoteBodyStyle: + + if (existing.NoteBodyStyle != null) + return SkinUtils.As(new Bindable(existing.NoteBodyStyle.Value)); + + if (GetConfig(SkinConfiguration.LegacySetting.Version)?.Value < 2.5m) + return SkinUtils.As(new Bindable(LegacyNoteBodyStyle.Stretch)); + + return SkinUtils.As(new Bindable(LegacyNoteBodyStyle.RepeatBottom)); + case LegacyManiaSkinConfigurationLookups.NoteImage: Debug.Assert(maniaLookup.ColumnIndex != null); return SkinUtils.As(getManiaImage(existing, $"NoteImage{maniaLookup.ColumnIndex}")); From b1d2a433f8399b22be74dc79b6fb511307330379 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Feb 2023 20:36:58 +0900 Subject: [PATCH 116/154] Apply second attempt at fixing long note bodies --- .../Skinning/Legacy/LegacyBodyPiece.cs | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index 96dbbf6620..b26e33b133 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -2,12 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Testing; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; @@ -34,6 +37,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy private Drawable? lightContainer; private Drawable? light; + private LegacyNoteBodyStyle? bodyStyle; public LegacyBodyPiece() { @@ -54,9 +58,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy float lightScale = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.HoldNoteLightScale)?.Value ?? 1; - float minimumColumnWidth = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.MinimumColumnWidth)?.Value - ?? 1; - // Create a temporary animation to retrieve the number of frames, in an effort to calculate the intended frame length. // This animation is discarded and re-queried with the appropriate frame length afterwards. var tmp = skin.GetAnimation(lightImage, true, false); @@ -83,7 +84,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy }; } - bodySprite = skin.GetAnimation(imageName, WrapMode.ClampToEdge, WrapMode.ClampToEdge, true, true).With(d => + bodyStyle = skin.GetConfig(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.NoteBodyStyle))?.Value; + + var wrapMode = bodyStyle == LegacyNoteBodyStyle.Stretch ? WrapMode.ClampToEdge : WrapMode.Repeat; + + direction.BindTo(scrollingInfo.Direction); + isHitting.BindTo(holdNote.IsHitting); + + bodySprite = skin.GetAnimation(imageName, wrapMode, wrapMode, true, true).With(d => { if (d == null) return; @@ -99,9 +107,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy if (bodySprite != null) InternalChild = bodySprite; - - direction.BindTo(scrollingInfo.Direction); - isHitting.BindTo(holdNote.IsHitting); } protected override void LoadComplete() @@ -205,6 +210,29 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy { base.Update(); missFadeTime.Value ??= holdNote.HoldBrokenTime; + + // here we go... + switch (bodyStyle) + { + case LegacyNoteBodyStyle.Stretch: + // this is how lazer works by default. nothing required. + break; + + default: + // this is where things get fucked up. + // honestly there's three modes to handle here but they seem really pointless? + // let's wait to see if anyone actually uses them in skins. + if (bodySprite != null) + { + var sprite = bodySprite as Sprite ?? bodySprite.ChildrenOfType().Single(); + + bodySprite.FillMode = FillMode.Stretch; + // i dunno this looks about right?? + bodySprite.Scale = new Vector2(1, 10000 / sprite.DrawHeight); + } + + break; + } } protected override void Dispose(bool isDisposing) From 81c3e0da317acb6af9b2ec8741f3db105505c821 Mon Sep 17 00:00:00 2001 From: Terochi Date: Fri, 10 Feb 2023 17:58:48 +0100 Subject: [PATCH 117/154] Fixed timeLeft counter in SongProgressInfo being out of bounds after rotation --- osu.Game/Screens/Play/HUD/SongProgressInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs index 7f9f353ded..c04ecd671f 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs @@ -121,8 +121,8 @@ namespace osu.Game.Screens.Play.HUD AutoSizeAxes = Axes.Both, Child = new UprightAspectMaintainingContainer { - Origin = Anchor.CentreRight, - Anchor = Anchor.CentreRight, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, AutoSizeAxes = Axes.Both, Scaling = ScaleMode.Vertical, ScalingFactor = 0.5f, From 11296c4ffe179ad172e0d1233244865445a91291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 10 Feb 2023 21:25:19 +0100 Subject: [PATCH 118/154] Use better exception type --- osu.Game/Users/Drawables/ClickableAvatar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index bb57958239..e74ffc9d54 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -23,7 +23,7 @@ namespace osu.Game.Users.Drawables return ShowUsernameTooltip ? (user?.Username ?? string.Empty) : default_tooltip_text; } - set => throw new InvalidOperationException(); + set => throw new NotSupportedException(); } /// From d30d054b4c4ad7de66af26ff41985658854f6f15 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 9 Feb 2023 21:28:51 -0800 Subject: [PATCH 119/154] Add ability to abort dangerous dialog button on hover lost --- osu.Game/Graphics/Containers/HoldToConfirmContainer.cs | 2 +- osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index cbe327bac7..0ac368dca7 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -102,7 +102,7 @@ namespace osu.Game.Graphics.Containers /// protected void AbortConfirm() { - if (!AllowMultipleFires && Fired) return; + if (!confirming || (!AllowMultipleFires && Fired)) return; confirming = false; Fired = false; diff --git a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs index 6b3716ac8d..dac589919f 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs @@ -95,6 +95,16 @@ namespace osu.Game.Overlays.Dialog } } + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (!e.HasAnyButtonPressed) return; + + lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); + AbortConfirm(); + } + private void progressChanged(ValueChangedEvent progress) { if (progress.NewValue < progress.OldValue) return; From bfd83768c1368f1c07f6d85ed03b44b71c5b1033 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 10 Feb 2023 17:58:34 -0800 Subject: [PATCH 120/154] Fix skin component previews on toolbox buttons having incorrect size for one frame --- osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs b/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs index a8d64c1de8..28ceaf09fc 100644 --- a/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs +++ b/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs @@ -148,9 +148,9 @@ namespace osu.Game.Overlays.SkinEditor component.Origin = Anchor.Centre; } - protected override void Update() + protected override void UpdateAfterChildren() { - base.Update(); + base.UpdateAfterChildren(); if (component.DrawSize != Vector2.Zero) { From 94d6ab1ec7580ab03804a6436c4ec7ed62221e3a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 10 Feb 2023 19:09:30 -0800 Subject: [PATCH 121/154] Continue confirming when rehovering if mouse is still down --- .../Overlays/Dialog/PopupDialogDangerousButton.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs index dac589919f..5cbdf54aad 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs @@ -57,6 +57,7 @@ namespace osu.Game.Overlays.Dialog private Sample confirmSample; private double lastTickPlaybackTime; private AudioFilter lowPassFilter = null!; + private bool mouseDown; [BackgroundDependencyLoader] private void load(AudioManager audio) @@ -83,6 +84,7 @@ namespace osu.Game.Overlays.Dialog protected override bool OnMouseDown(MouseDownEvent e) { BeginConfirm(); + mouseDown = true; return true; } @@ -92,14 +94,23 @@ namespace osu.Game.Overlays.Dialog { lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); AbortConfirm(); + mouseDown = false; } } + protected override bool OnHover(HoverEvent e) + { + if (mouseDown) + BeginConfirm(); + + return base.OnHover(e); + } + protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - if (!e.HasAnyButtonPressed) return; + if (!mouseDown) return; lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); AbortConfirm(); From 86c86759105289ea88f2d719771deef1286ace18 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 11 Feb 2023 13:52:24 +0900 Subject: [PATCH 122/154] Update realm and other dependencies --- ...u.Game.Rulesets.EmptyFreeform.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 4 ++-- ....Game.Rulesets.EmptyScrolling.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 4 ++-- osu.Desktop/osu.Desktop.csproj | 5 +++-- .../osu.Game.Benchmarks.csproj | 5 +++-- .../osu.Game.Rulesets.Catch.Tests.csproj | 5 +++-- .../osu.Game.Rulesets.Catch.csproj | 4 ++++ .../osu.Game.Rulesets.Mania.Tests.csproj | 5 +++-- .../osu.Game.Rulesets.Mania.csproj | 4 ++++ .../osu.Game.Rulesets.Osu.Tests.csproj | 7 ++++--- .../osu.Game.Rulesets.Osu.csproj | 4 ++++ .../osu.Game.Rulesets.Taiko.Tests.csproj | 5 +++-- .../osu.Game.Rulesets.Taiko.csproj | 4 ++++ osu.Game.Tests/osu.Game.Tests.csproj | 7 ++++--- .../osu.Game.Tournament.Tests.csproj | 5 +++-- .../osu.Game.Tournament.csproj | 1 + osu.Game/osu.Game.csproj | 21 ++++++++++--------- 18 files changed, 62 insertions(+), 36 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index 52b728a115..a1c53ece03 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -9,9 +9,9 @@ false - + - + diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 95b96adab0..683e9fd5e8 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -9,9 +9,9 @@ false - + - + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index d12403016d..b7a7fff18a 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -9,9 +9,9 @@ false - + - + diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 95b96adab0..683e9fd5e8 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -9,9 +9,9 @@ false - + - + diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 1f4544098b..6a89b2b018 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -26,8 +26,9 @@ - - + + + diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index f47b069373..c6ed0d78be 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -7,9 +7,10 @@ - + - + + diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 5a2e8e0bf0..131471592c 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -1,9 +1,10 @@  - + - + + WinExe diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index ecce7c1b3f..ee4399267c 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index be51dc0e4c..f2bde15494 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -1,9 +1,10 @@  - + - + + WinExe diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 72f172188e..7f59e32ed2 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index c10c3ffb15..38467a354e 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -1,10 +1,11 @@  - - + + - + + WinExe diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index bf776fe5dd..1bcf6e4308 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 6af1beff69..9878f0cfcc 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -1,9 +1,10 @@  - + - + + WinExe diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index f0e1cb8e8f..2f8681420c 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 24969414d0..9ea8bc0e7d 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -2,11 +2,12 @@ - + - - + + + WinExe diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 9f2a088a4b..c54fe6b9a6 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -4,9 +4,10 @@ osu.Game.Tournament.Tests.TournamentTestRunner - + - + + WinExe diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index ab67e490cd..3822a80489 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -10,5 +10,6 @@ + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index cdb3d9b66b..b057e98b63 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,29 +18,29 @@ - + - - - - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + - + @@ -48,5 +48,6 @@ + From 20f3ab167e4c5585b3a4e8bd24a67ab0a3e2a166 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 11 Feb 2023 19:36:40 +0900 Subject: [PATCH 123/154] Re-centralise `BannedApiAnalysers` nuget package --- Directory.Build.props | 2 +- osu.Desktop/osu.Desktop.csproj | 1 - osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 1 - .../osu.Game.Rulesets.Catch.Tests.csproj | 1 - osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 4 ---- .../osu.Game.Rulesets.Mania.Tests.csproj | 1 - osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 4 ---- .../osu.Game.Rulesets.Osu.Tests.csproj | 1 - osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 4 ---- .../osu.Game.Rulesets.Taiko.Tests.csproj | 1 - osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 4 ---- osu.Game.Tests/osu.Game.Tests.csproj | 1 - osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 1 - osu.Game.Tournament/osu.Game.Tournament.csproj | 1 - osu.Game/osu.Game.csproj | 1 - 15 files changed, 1 insertion(+), 27 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 235feea8ce..3b6b985961 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -17,7 +17,7 @@ - + diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 6a89b2b018..f1b9c92429 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -28,7 +28,6 @@ - diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index c6ed0d78be..4719d54138 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -10,7 +10,6 @@ - diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 131471592c..01922b2a96 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,6 @@ - WinExe diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index ee4399267c..ecce7c1b3f 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -15,8 +15,4 @@ - - - - diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index f2bde15494..027bf60a0c 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,6 @@ - WinExe diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 7f59e32ed2..72f172188e 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -15,8 +15,4 @@ - - - - diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 38467a354e..57900bffd7 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -5,7 +5,6 @@ - WinExe diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 1bcf6e4308..bf776fe5dd 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -15,8 +15,4 @@ - - - - diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 9878f0cfcc..0c39ad988b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,6 @@ - WinExe diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 2f8681420c..f0e1cb8e8f 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -15,8 +15,4 @@ - - - - diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 9ea8bc0e7d..59a786a11d 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -7,7 +7,6 @@ - WinExe diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index c54fe6b9a6..5847079161 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,6 @@ - WinExe diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index 3822a80489..ab67e490cd 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -10,6 +10,5 @@ - diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b057e98b63..65ea301cbd 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -48,6 +48,5 @@ - From a3cc0d23b3e366c1d269f27fea020fb87a405eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 11 Feb 2023 16:26:32 +0100 Subject: [PATCH 124/154] Fix typo in xmldoc --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 5d75ae2db5..3f911f5067 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Edit.Timing if (editorClock != null) { - // When entering the timing screen, let's choose to closest valid timing point. + // When entering the timing screen, let's choose the closest valid timing point. // This will emulate the osu-stable behaviour where a metronome and timing information // are presented on entering the screen. var nearestTimingPoint = EditorBeatmap.ControlPointInfo.TimingPointAt(editorClock.CurrentTime); From 8d9245c1d4f72db4307da7492d65bd09fc48bc02 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 11 Feb 2023 12:54:16 -0800 Subject: [PATCH 125/154] Make `AbortConfirm()` virtual and override with filter logic --- osu.Game/Graphics/Containers/HoldToConfirmContainer.cs | 2 +- osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index 0ac368dca7..9f21512825 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -100,7 +100,7 @@ namespace osu.Game.Graphics.Containers /// /// Abort any ongoing confirmation. Should be called when the container's interaction is no longer valid (ie. the user releases a key). /// - protected void AbortConfirm() + protected virtual void AbortConfirm() { if (!confirming || (!AllowMultipleFires && Fired)) return; diff --git a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs index 5cbdf54aad..19d7ea7a87 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs @@ -74,6 +74,12 @@ namespace osu.Game.Overlays.Dialog Progress.BindValueChanged(progressChanged); } + protected override void AbortConfirm() + { + lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); + base.AbortConfirm(); + } + protected override void Confirm() { lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); @@ -92,7 +98,6 @@ namespace osu.Game.Overlays.Dialog { if (!e.HasAnyButtonPressed) { - lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); AbortConfirm(); mouseDown = false; } @@ -112,7 +117,6 @@ namespace osu.Game.Overlays.Dialog if (!mouseDown) return; - lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); AbortConfirm(); } From 9d09141ab735232f3e24cbbb73b33e4934a6ccbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 12 Feb 2023 16:08:23 +0900 Subject: [PATCH 126/154] Move taiko-specific property out of `DrawableHitObject` --- osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs | 4 ++-- .../Objects/Drawables/DrawableTaikoHitObject.cs | 9 +++++++++ osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 9 --------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs index 300c72a854..d0361b1c8d 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs @@ -23,8 +23,8 @@ namespace osu.Game.Rulesets.Taiko.Mods public void ApplyToDrawableHitObject(DrawableHitObject drawable) { - if (drawable is DrawableHit) - drawable.SnapJudgementLocation = true; + if (drawable is DrawableTaikoHitObject hit) + hit.SnapJudgementLocation = true; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 6172b75d2c..f912b5882c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -25,6 +25,15 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private readonly Container nonProxiedContent; + /// + /// Whether the location of the hit should be snapped to the hit target before animating. + /// + /// + /// This is how osu-stable worked, but notably is not how TnT works. + /// It results in less visual feedback on hit accuracy. + /// + public bool SnapJudgementLocation { get; set; } + protected DrawableTaikoHitObject([CanBeNull] TaikoHitObject hitObject) : base(hitObject) { diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 01550a113f..39f0888882 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -662,15 +662,6 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual double MaximumJudgementOffset => HitObject.HitWindows?.WindowFor(HitResult.Miss) ?? 0; - /// - /// Whether the location of the hit should be snapped to the hit target before animating. - /// - /// - /// This is how osu-stable worked, but notably is not how TnT works. - /// It results in less visual feedback on hit accuracy. - /// - public bool SnapJudgementLocation { get; set; } - /// /// Applies the of this , notifying responders such as /// the of the . From 67b6df31725e2cefa9b530dd669646ce5349b2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 12 Feb 2023 13:31:29 +0100 Subject: [PATCH 127/154] Reword ambiguous xmldoc --- .../Objects/Drawables/DrawableTaikoHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index f912b5882c..f695c505a4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// /// This is how osu-stable worked, but notably is not how TnT works. - /// It results in less visual feedback on hit accuracy. + /// Not snapping results in less visual feedback on hit accuracy. /// public bool SnapJudgementLocation { get; set; } From afb66d8af41517dc1ad85ed2f5798ea997a20193 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 12 Feb 2023 12:32:17 -0800 Subject: [PATCH 128/154] Make user activity class names more specific --- osu.Desktop/DiscordRichPresence.cs | 6 +++--- .../Visual/Online/TestSceneNowPlayingCommand.cs | 2 +- .../Visual/Online/TestSceneUserPanel.cs | 8 ++++---- osu.Game/Online/Chat/NowPlayingCommand.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Play/ReplayPlayer.cs | 2 +- osu.Game/Screens/Play/SoloSpectatorPlayer.cs | 2 +- osu.Game/Users/UserActivity.cs | 16 ++++++++-------- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index e24fe1a1ec..fe3e08537e 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -169,7 +169,7 @@ namespace osu.Desktop case UserActivity.InGame game: return game.BeatmapInfo; - case UserActivity.Editing edit: + case UserActivity.EditingBeatmap edit: return edit.BeatmapInfo; } @@ -183,10 +183,10 @@ namespace osu.Desktop case UserActivity.InGame game: return game.BeatmapInfo.ToString() ?? string.Empty; - case UserActivity.Editing edit: + case UserActivity.EditingBeatmap edit: return edit.BeatmapInfo.ToString() ?? string.Empty; - case UserActivity.Watching watching: + case UserActivity.WatchingReplay watching: return watching.BeatmapInfo.ToString(); case UserActivity.InLobby lobby: diff --git a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs index 4675410164..10c2b2b9e1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestEditActivity() { - AddStep("Set activity", () => api.Activity.Value = new UserActivity.Editing(new BeatmapInfo())); + AddStep("Set activity", () => api.Activity.Value = new UserActivity.EditingBeatmap(new BeatmapInfo())); AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 64a42ee6ce..765af8cd8b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -109,15 +109,15 @@ namespace osu.Game.Tests.Visual.Online AddStep("set online status", () => status.Value = new UserStatusOnline()); AddStep("idle", () => activity.Value = null); - AddStep("watching", () => activity.Value = new UserActivity.Watching(createScore(@"nats"))); - AddStep("spectating", () => activity.Value = new UserActivity.Spectating(createScore(@"mrekk"))); + AddStep("watching replay", () => activity.Value = new UserActivity.WatchingReplay(createScore(@"nats"))); + AddStep("spectating user", () => activity.Value = new UserActivity.SpectatingUser(createScore(@"mrekk"))); AddStep("solo (osu!)", () => activity.Value = soloGameStatusForRuleset(0)); AddStep("solo (osu!taiko)", () => activity.Value = soloGameStatusForRuleset(1)); AddStep("solo (osu!catch)", () => activity.Value = soloGameStatusForRuleset(2)); AddStep("solo (osu!mania)", () => activity.Value = soloGameStatusForRuleset(3)); AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap()); - AddStep("editing", () => activity.Value = new UserActivity.Editing(null)); - AddStep("modding", () => activity.Value = new UserActivity.Modding()); + AddStep("editing beatmap", () => activity.Value = new UserActivity.EditingBeatmap(null)); + AddStep("modding beatmap", () => activity.Value = new UserActivity.ModdingBeatmap()); } [Test] diff --git a/osu.Game/Online/Chat/NowPlayingCommand.cs b/osu.Game/Online/Chat/NowPlayingCommand.cs index 9902704883..e7018d6993 100644 --- a/osu.Game/Online/Chat/NowPlayingCommand.cs +++ b/osu.Game/Online/Chat/NowPlayingCommand.cs @@ -61,7 +61,7 @@ namespace osu.Game.Online.Chat beatmapInfo = game.BeatmapInfo; break; - case UserActivity.Editing edit: + case UserActivity.EditingBeatmap edit: verb = "editing"; beatmapInfo = edit.BeatmapInfo; break; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 0622cbebae..d9c2db9cec 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -157,7 +157,7 @@ namespace osu.Game.Screens.Edit private bool isNewBeatmap; - protected override UserActivity InitialActivity => new UserActivity.Editing(Beatmap.Value.BeatmapInfo); + protected override UserActivity InitialActivity => new UserActivity.EditingBeatmap(Beatmap.Value.BeatmapInfo); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 9e87969687..8a4e63d21c 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play private readonly bool replayIsFailedScore; - protected override UserActivity InitialActivity => new UserActivity.Watching(Score.ScoreInfo); + protected override UserActivity InitialActivity => new UserActivity.WatchingReplay(Score.ScoreInfo); // Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108) protected override bool CheckModsAllowFailure() diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index 8a9cda2af7..c9d1f4acaa 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Play { private readonly Score score; - protected override UserActivity InitialActivity => new UserActivity.Spectating(Score.ScoreInfo); + protected override UserActivity InitialActivity => new UserActivity.SpectatingUser(Score.ScoreInfo); public SoloSpectatorPlayer(Score score, PlayerConfiguration configuration = null) : base(score, configuration) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index b1c3fac382..a1575d5fc4 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -18,9 +18,9 @@ namespace osu.Game.Users public virtual Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; - public class Modding : UserActivity + public class ModdingBeatmap : UserActivity { - public override string GetStatus(bool hideIdentifiableInformation = false) => "Modding a map"; + public override string GetStatus(bool hideIdentifiableInformation = false) => "Modding a beatmap"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; } @@ -80,11 +80,11 @@ namespace osu.Game.Users } } - public class Editing : UserActivity + public class EditingBeatmap : UserActivity { public IBeatmapInfo BeatmapInfo { get; } - public Editing(IBeatmapInfo info) + public EditingBeatmap(IBeatmapInfo info) { BeatmapInfo = info; } @@ -92,7 +92,7 @@ namespace osu.Game.Users public override string GetStatus(bool hideIdentifiableInformation = false) => @"Editing a beatmap"; } - public class Watching : UserActivity + public class WatchingReplay : UserActivity { private readonly ScoreInfo score; @@ -100,7 +100,7 @@ namespace osu.Game.Users public BeatmapInfo BeatmapInfo => score.BeatmapInfo; - public Watching(ScoreInfo score) + public WatchingReplay(ScoreInfo score) { this.score = score; } @@ -108,11 +108,11 @@ namespace osu.Game.Users public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Watching a replay" : $@"Watching {Username}'s replay"; } - public class Spectating : Watching + public class SpectatingUser : WatchingReplay { public override string GetStatus(bool hideIdentifiableInformation = false) => hideIdentifiableInformation ? @"Spectating a user" : $@"Spectating {Username}"; - public Spectating(ScoreInfo score) + public SpectatingUser(ScoreInfo score) : base(score) { } From bbeef53569409900ae56816b0fefd83831d06b19 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 12 Feb 2023 13:04:12 -0800 Subject: [PATCH 129/154] Add `TestingBeatmap` activity --- osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs | 1 + osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs | 3 +++ osu.Game/Users/UserActivity.cs | 10 ++++++++++ 3 files changed, 14 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 765af8cd8b..737bc948d6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -118,6 +118,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap()); AddStep("editing beatmap", () => activity.Value = new UserActivity.EditingBeatmap(null)); AddStep("modding beatmap", () => activity.Value = new UserActivity.ModdingBeatmap()); + AddStep("testing beatmap", () => activity.Value = new UserActivity.TestingBeatmap(null, null)); } [Test] diff --git a/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs b/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs index e7db1c105b..7dff05667d 100644 --- a/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs +++ b/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs @@ -7,6 +7,7 @@ using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Screens.Play; +using osu.Game.Users; namespace osu.Game.Screens.Edit.GameplayTest { @@ -15,6 +16,8 @@ namespace osu.Game.Screens.Edit.GameplayTest private readonly Editor editor; private readonly EditorState editorState; + protected override UserActivity InitialActivity => new UserActivity.TestingBeatmap(Beatmap.Value.BeatmapInfo, Ruleset.Value); + [Resolved] private MusicController musicController { get; set; } = null!; diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index a1575d5fc4..4e0fad34d0 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -80,6 +80,16 @@ namespace osu.Game.Users } } + public class TestingBeatmap : InGame + { + public override string GetStatus(bool hideIdentifiableInformation = false) => "Testing a beatmap"; + + public TestingBeatmap(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset) + : base(beatmapInfo, ruleset) + { + } + } + public class EditingBeatmap : UserActivity { public IBeatmapInfo BeatmapInfo { get; } From cb51b9e350530b6e98f89ef627157452127fa099 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 12 Feb 2023 13:11:55 -0800 Subject: [PATCH 130/154] Use existing `ModdingBeatmap` activity --- osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 11 ++++++++++- osu.Game/Users/UserActivity.cs | 7 ++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 737bc948d6..a047e2f0c5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -117,7 +117,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("solo (osu!mania)", () => activity.Value = soloGameStatusForRuleset(3)); AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap()); AddStep("editing beatmap", () => activity.Value = new UserActivity.EditingBeatmap(null)); - AddStep("modding beatmap", () => activity.Value = new UserActivity.ModdingBeatmap()); + AddStep("modding beatmap", () => activity.Value = new UserActivity.ModdingBeatmap(null)); AddStep("testing beatmap", () => activity.Value = new UserActivity.TestingBeatmap(null, null)); } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index d9c2db9cec..bd133383d1 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -157,7 +157,16 @@ namespace osu.Game.Screens.Edit private bool isNewBeatmap; - protected override UserActivity InitialActivity => new UserActivity.EditingBeatmap(Beatmap.Value.BeatmapInfo); + protected override UserActivity InitialActivity + { + get + { + if (Beatmap.Value.Metadata.Author.OnlineID == api.LocalUser.Value.OnlineID) + return new UserActivity.EditingBeatmap(Beatmap.Value.BeatmapInfo); + + return new UserActivity.ModdingBeatmap(Beatmap.Value.BeatmapInfo); + } + } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 4e0fad34d0..0b11d12c46 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -18,10 +18,15 @@ namespace osu.Game.Users public virtual Color4 GetAppropriateColour(OsuColour colours) => colours.GreenDarker; - public class ModdingBeatmap : UserActivity + public class ModdingBeatmap : EditingBeatmap { public override string GetStatus(bool hideIdentifiableInformation = false) => "Modding a beatmap"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark; + + public ModdingBeatmap(IBeatmapInfo info) + : base(info) + { + } } public class ChoosingBeatmap : UserActivity From ca768ca4464900e158e2997022a93ee252a93c9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Feb 2023 17:43:52 +0900 Subject: [PATCH 131/154] Add comment regarding unused enum members in `LegacyNoteBodyStyle` --- osu.Game/Skinning/LegacyNoteBodyStyle.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacyNoteBodyStyle.cs b/osu.Game/Skinning/LegacyNoteBodyStyle.cs index 788bcc5432..3c1108dcef 100644 --- a/osu.Game/Skinning/LegacyNoteBodyStyle.cs +++ b/osu.Game/Skinning/LegacyNoteBodyStyle.cs @@ -6,10 +6,12 @@ namespace osu.Game.Skinning public enum LegacyNoteBodyStyle { Stretch = 0, + + // listed as the default on https://osu.ppy.sh/wiki/en/Skinning/skin.ini, but is seemingly not according to the source. + // Repeat = 1, + RepeatTop = 2, RepeatBottom = 3, RepeatTopAndBottom = 4, - //Repeat = 1, - //RepeatMiddle = 5, } } From 55358d36c83d8886a047cdeb95d20eaebf154bb5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Feb 2023 17:50:32 +0900 Subject: [PATCH 132/154] Change `MinimumColumnWidth` to remove setter --- osu.Game/Skinning/LegacyManiaSkinConfiguration.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs index 1ff9988332..f460a3d31a 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs @@ -59,12 +59,6 @@ namespace osu.Game.Skinning ColumnWidth.AsSpan().Fill(DEFAULT_COLUMN_SIZE); } - private float? minimumColumnWidth; - - public float MinimumColumnWidth - { - get => minimumColumnWidth ?? ColumnWidth.Min(); - set => minimumColumnWidth = value; - } + public float MinimumColumnWidth => ColumnWidth.Min(); } } From 006356e61777968d96957304cb31233c4587104b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 13 Feb 2023 14:17:33 +0300 Subject: [PATCH 133/154] Add TestSceneLetterboxOverlay --- .../Gameplay/TestSceneLetterboxOverlay.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneLetterboxOverlay.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLetterboxOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLetterboxOverlay.cs new file mode 100644 index 0000000000..ce93837925 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLetterboxOverlay.cs @@ -0,0 +1,24 @@ +// 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.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Screens.Play.Break; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public partial class TestSceneLetterboxOverlay : OsuTestScene + { + public TestSceneLetterboxOverlay() + { + AddRange(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both + }, + new LetterboxOverlay() + }); + } + } +} From 35bc0a29d8a890b936737035fd33f962fb7eae9d Mon Sep 17 00:00:00 2001 From: PC Date: Mon, 13 Feb 2023 15:11:55 +0300 Subject: [PATCH 134/154] Add setting skin on notification click --- osu.Game/Skinning/SkinManager.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index fca7dc0f5e..02be3abab7 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -87,6 +87,15 @@ namespace osu.Game.Skinning skinImporter = new SkinImporter(storage, realm, this) { PostNotification = obj => PostNotification?.Invoke(obj), + PresentImport = skins => + { + switch (skins.Count()) + { + case 1: + CurrentSkinInfo.Value = skins.Last(); + break; + } + }, }; var defaultSkins = new[] From 2dee783401b06da5dc9663b1ad4e6cfdfdca4419 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 13 Feb 2023 15:14:25 +0300 Subject: [PATCH 135/154] Remove not needed containers --- .../Screens/Play/Break/LetterboxOverlay.cs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/Break/LetterboxOverlay.cs b/osu.Game/Screens/Play/Break/LetterboxOverlay.cs index 92b432831d..c4e2dbf403 100644 --- a/osu.Game/Screens/Play/Break/LetterboxOverlay.cs +++ b/osu.Game/Screens/Play/Break/LetterboxOverlay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -22,29 +20,21 @@ namespace osu.Game.Screens.Play.Break RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[] { - new Container + new Box { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, RelativeSizeAxes = Axes.X, Height = height, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black, transparent_black), - } + Colour = ColourInfo.GradientVertical(Color4.Black, transparent_black), }, - new Container + new Box { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = height, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(transparent_black, Color4.Black), - } + Colour = ColourInfo.GradientVertical(transparent_black, Color4.Black), } }; } From a22a36bfe0c24a6bbbced56b9562ba0c2d4f1efd Mon Sep 17 00:00:00 2001 From: PC Date: Mon, 13 Feb 2023 20:31:09 +0300 Subject: [PATCH 136/154] Add navigation to skin settings on multiple import --- .../Overlays/Settings/Sections/SkinSection.cs | 23 +++++++++++++++++++ osu.Game/Skinning/SkinManager.cs | 12 +++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 5cf8157812..189db829bf 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -10,6 +10,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Logging; @@ -49,6 +50,9 @@ namespace osu.Game.Overlays.Settings.Sections [Resolved] private RealmAccess realm { get; set; } + [Resolved] + private SettingsOverlay settings { get; set; } + private IDisposable realmSubscription; [BackgroundDependencyLoader(permitNulls: true)] @@ -91,6 +95,25 @@ namespace osu.Game.Overlays.Settings.Sections skins.SelectRandomSkin(); } }); + + skins.PresentSkinsImport += presentSkinsImport; + } + + private void presentSkinsImport(IEnumerable> importedSkins) + { + switch (importedSkins.Count()) + { + case 1: + skins.CurrentSkinInfo.Value = importedSkins.Last(); + break; + + case > 1: + if (settings?.State.Value == Visibility.Hidden) + settings?.ToggleVisibility(); + + settings?.SectionsContainer.ScrollTo(this); + break; + } } private void skinsChanged(IRealmCollection sender, ChangeSet changes, Exception error) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 02be3abab7..2921a5bc17 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -44,6 +44,8 @@ namespace osu.Game.Skinning /// public Skin DefaultClassicSkin { get; } + public Action>> PresentSkinsImport { get; set; } + private readonly AudioManager audio; private readonly Scheduler scheduler; @@ -87,15 +89,7 @@ namespace osu.Game.Skinning skinImporter = new SkinImporter(storage, realm, this) { PostNotification = obj => PostNotification?.Invoke(obj), - PresentImport = skins => - { - switch (skins.Count()) - { - case 1: - CurrentSkinInfo.Value = skins.Last(); - break; - } - }, + PresentImport = skins => PresentSkinsImport?.Invoke(skins), }; var defaultSkins = new[] From 637b07efe6eb4f6619b66a5c0a1214c39ef6ffdd Mon Sep 17 00:00:00 2001 From: PC Date: Mon, 13 Feb 2023 22:36:51 +0300 Subject: [PATCH 137/154] Remove `Resolved` attribute --- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 189db829bf..f83ec95f93 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -50,9 +50,6 @@ namespace osu.Game.Overlays.Settings.Sections [Resolved] private RealmAccess realm { get; set; } - [Resolved] - private SettingsOverlay settings { get; set; } - private IDisposable realmSubscription; [BackgroundDependencyLoader(permitNulls: true)] @@ -101,6 +98,8 @@ namespace osu.Game.Overlays.Settings.Sections private void presentSkinsImport(IEnumerable> importedSkins) { + SettingsOverlay settings = this.FindClosestParent(); + switch (importedSkins.Count()) { case 1: From 46b13f2565316020c88cd0d0e81421b09721947b Mon Sep 17 00:00:00 2001 From: PC Date: Mon, 13 Feb 2023 22:44:11 +0300 Subject: [PATCH 138/154] Improve code quality --- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index f83ec95f93..cb1083c519 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -107,10 +107,10 @@ namespace osu.Game.Overlays.Settings.Sections break; case > 1: - if (settings?.State.Value == Visibility.Hidden) - settings?.ToggleVisibility(); + if (settings.State.Value == Visibility.Hidden) + settings.ToggleVisibility(); - settings?.SectionsContainer.ScrollTo(this); + settings.SectionsContainer.ScrollTo(this); break; } } From 10ab228d76270572fcfd335b3edcbe85efdf00e8 Mon Sep 17 00:00:00 2001 From: PC Date: Mon, 13 Feb 2023 22:47:29 +0300 Subject: [PATCH 139/154] Improve xml doc --- osu.Game/Skinning/SkinManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 2921a5bc17..8b7c886b3b 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -44,6 +44,9 @@ namespace osu.Game.Skinning /// public Skin DefaultClassicSkin { get; } + /// + /// Presents imported skin(s) to a user + /// public Action>> PresentSkinsImport { get; set; } private readonly AudioManager audio; From 6e6421caea281efd081f9a11b5bfa87cea10cf70 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 13 Feb 2023 22:07:09 +0100 Subject: [PATCH 140/154] Change FooterV2.cs colour to use `ColourProvider` instead of `OsuColour`. Remove unnecessary `FillFlowContainer` --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 3 +++ osu.Game/Screens/Select/FooterV2/FooterV2.cs | 25 ++++++------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index 773d067c15..72adbfc104 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -24,6 +24,9 @@ namespace osu.Game.Tests.Visual.SongSelect private DummyOverlay overlay = null!; + [Cached] + private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + [SetUp] public void SetUp() => Schedule(() => { diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs index 2bfa03d319..cd95f3eb6c 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osuTK; namespace osu.Game.Screens.Select.FooterV2 @@ -48,7 +49,7 @@ namespace osu.Game.Screens.Select.FooterV2 private FillFlowContainer buttons = null!; [BackgroundDependencyLoader] - private void load(OsuColour colour) + private void load(OverlayColourProvider colourProvider) { RelativeSizeAxes = Axes.X; Height = height; @@ -57,28 +58,16 @@ namespace osu.Game.Screens.Select.FooterV2 new Box { RelativeSizeAxes = Axes.Both, - Colour = colour.B5 + Colour = colourProvider.Background5 }, - new FillFlowContainer + buttons = new FillFlowContainer { + Position = new Vector2(TwoLayerButton.SIZE_EXTENDED.X + padding, 10), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Position = new Vector2(TwoLayerButton.SIZE_EXTENDED.X + padding, 10), - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, Direction = FillDirection.Horizontal, - Spacing = new Vector2(padding, 0), - Children = new Drawable[] - { - buttons = new FillFlowContainer - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(-FooterButtonV2.SHEAR_WIDTH + 7, 0), - AutoSizeAxes = Axes.Both - } - } + Spacing = new Vector2(-FooterButtonV2.SHEAR_WIDTH + 7, 0), + AutoSizeAxes = Axes.Both } }; } From 61584ba63c30b7f30f6338dc7262fd12f9d8ca25 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 13 Feb 2023 22:15:29 +0100 Subject: [PATCH 141/154] Fix corner_radius missing in some parts of `FooterButtonV2.cs`. Adjust shadow radius value to 5 to match figma. --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 409d9daaae..9d94475a8f 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -74,8 +74,7 @@ namespace osu.Game.Screens.Select.FooterV2 { Type = EdgeEffectType.Shadow, Radius = 5, - Roundness = 10, - Colour = Colour4.Black.Opacity(0.25f) + Colour = Colour4.Black.Opacity(0.5f) }; Shear = SHEAR; Size = new Vector2(button_width, button_height); @@ -124,7 +123,7 @@ namespace osu.Game.Screens.Select.FooterV2 Shear = -SHEAR, Anchor = Anchor.BottomCentre, Origin = Anchor.Centre, - Y = -10, + Y = -corner_radius, Size = new Vector2(120, 6), Masking = true, CornerRadius = 3, From be52d0a60c960451749a4bd3d6bc7256bfb65d76 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 13 Feb 2023 22:17:02 +0100 Subject: [PATCH 142/154] Add note explaining shadow opacity pass ColourProvider in from test, instead of hard coding it in `FooterButtonV2.cs` --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index 9d94475a8f..c172b6725a 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -36,8 +36,8 @@ namespace osu.Game.Screens.Select.FooterV2 protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / button_height, 0); - [Cached] - private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; private Colour4 buttonAccentColour; @@ -74,7 +74,8 @@ namespace osu.Game.Screens.Select.FooterV2 { Type = EdgeEffectType.Shadow, Radius = 5, - Colour = Colour4.Black.Opacity(0.5f) + // Figma says 50% opacity, but it does not match up visually if taken at face value, and looks bad. + Colour = Colour4.Black.Opacity(0.25f) }; Shear = SHEAR; Size = new Vector2(button_width, button_height); From ae9a17d76bc29eb45e7792af8b9250477e751217 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 13 Feb 2023 22:20:41 +0100 Subject: [PATCH 143/154] Add offset to `FooterButtonV2.cs` shadow --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index c172b6725a..d85eafa15f 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -75,7 +75,8 @@ namespace osu.Game.Screens.Select.FooterV2 Type = EdgeEffectType.Shadow, Radius = 5, // Figma says 50% opacity, but it does not match up visually if taken at face value, and looks bad. - Colour = Colour4.Black.Opacity(0.25f) + Colour = Colour4.Black.Opacity(0.25f), + Offset = new Vector2(0, 2), }; Shear = SHEAR; Size = new Vector2(button_width, button_height); From 7f7e72705faf247c1ef9e3d107550359c3ea6254 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 13 Feb 2023 14:15:37 -0800 Subject: [PATCH 144/154] Fix beatmap card song preview progress sometimes showing past progress for one frame --- osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs index f808fd21b7..8304cdfc08 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs @@ -75,9 +75,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons Playing.BindValueChanged(updateState, true); } - protected override void Update() + protected override void UpdateAfterChildren() { - base.Update(); + base.UpdateAfterChildren(); if (Playing.Value && previewTrack != null && previewTrack.TrackLoaded) progress.Value = previewTrack.CurrentTime / previewTrack.Length; From 5006dbe3db1f6f8056b27e5d4e58eba526885e55 Mon Sep 17 00:00:00 2001 From: MK56 <74463310+mk56-spn@users.noreply.github.com> Date: Tue, 14 Feb 2023 00:07:02 +0100 Subject: [PATCH 145/154] Update osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs Co-authored-by: Joseph Madamba --- osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs index d85eafa15f..2f5046d2bb 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonV2.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select.FooterV2 EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, - Radius = 5, + Radius = 4, // Figma says 50% opacity, but it does not match up visually if taken at face value, and looks bad. Colour = Colour4.Black.Opacity(0.25f), Offset = new Vector2(0, 2), From f8f485e4c8b8d4e149bbbb244d1098d9353f1c62 Mon Sep 17 00:00:00 2001 From: PC Date: Tue, 14 Feb 2023 02:29:50 +0300 Subject: [PATCH 146/154] Move `PresentSkinsImport` to `OsuGame`. Replace switch with if statement --- osu.Game/OsuGame.cs | 20 +++++++++++++++++ .../Overlays/Settings/Sections/SkinSection.cs | 22 ------------------- osu.Game/Skinning/SkinManager.cs | 6 ----- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index df3d8b99f4..900c07b3c5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -49,6 +49,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; using osu.Game.Overlays.Music; using osu.Game.Overlays.Notifications; +using osu.Game.Overlays.Settings.Sections; using osu.Game.Overlays.SkinEditor; using osu.Game.Overlays.Toolbar; using osu.Game.Overlays.Volume; @@ -60,6 +61,7 @@ using osu.Game.Screens.Menu; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Screens.Select; +using osu.Game.Skinning; using osu.Game.Updater; using osu.Game.Users; using osu.Game.Utils; @@ -501,6 +503,23 @@ namespace osu.Game /// The build version of the update stream public void ShowChangelogBuild(string updateStream, string version) => waitForReady(() => changelogOverlay, _ => changelogOverlay.ShowBuild(updateStream, version)); + /// + /// Present ether a skin select if one skin was imported or navigate to the skin selection menu if multiple skins were imported immediately. + /// + /// List of imported skins + public void PresentSkins(IEnumerable> importedSkins) + { + int importedSkinsCount = importedSkins.Count(); + + if (importedSkinsCount == 1) + SkinManager.CurrentSkinInfo.Value = importedSkins.Single(); + else if (importedSkinsCount > 1) + { + Settings.Show(); + Settings.SectionsContainer.ScrollTo(Settings.SectionsContainer.Single(container => container is SkinSection)); + } + } + /// /// Present a beatmap at song select immediately. /// The user should have already requested this interactively. @@ -777,6 +796,7 @@ namespace osu.Game // todo: all archive managers should be able to be looped here. SkinManager.PostNotification = n => Notifications.Post(n); + SkinManager.PresentImport = PresentSkins; BeatmapManager.PostNotification = n => Notifications.Post(n); BeatmapManager.PresentImport = items => PresentBeatmap(items.First().Value); diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index cb1083c519..5cf8157812 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -10,7 +10,6 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Logging; @@ -92,27 +91,6 @@ namespace osu.Game.Overlays.Settings.Sections skins.SelectRandomSkin(); } }); - - skins.PresentSkinsImport += presentSkinsImport; - } - - private void presentSkinsImport(IEnumerable> importedSkins) - { - SettingsOverlay settings = this.FindClosestParent(); - - switch (importedSkins.Count()) - { - case 1: - skins.CurrentSkinInfo.Value = importedSkins.Last(); - break; - - case > 1: - if (settings.State.Value == Visibility.Hidden) - settings.ToggleVisibility(); - - settings.SectionsContainer.ScrollTo(this); - break; - } } private void skinsChanged(IRealmCollection sender, ChangeSet changes, Exception error) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 8b7c886b3b..fca7dc0f5e 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -44,11 +44,6 @@ namespace osu.Game.Skinning /// public Skin DefaultClassicSkin { get; } - /// - /// Presents imported skin(s) to a user - /// - public Action>> PresentSkinsImport { get; set; } - private readonly AudioManager audio; private readonly Scheduler scheduler; @@ -92,7 +87,6 @@ namespace osu.Game.Skinning skinImporter = new SkinImporter(storage, realm, this) { PostNotification = obj => PostNotification?.Invoke(obj), - PresentImport = skins => PresentSkinsImport?.Invoke(skins), }; var defaultSkins = new[] From 24a5a1061f792e4f2b5c6bc6927bda47f051693f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 13 Feb 2023 10:18:45 -0800 Subject: [PATCH 147/154] Fix `OsuClickableContainer` sounds not being blocked by nested drawables --- osu.Game/Graphics/Containers/OsuClickableContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index 6fe1de2216..fceee90d06 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -46,8 +46,8 @@ namespace osu.Game.Graphics.Containers AddRangeInternal(new Drawable[] { + CreateHoverSounds(sampleSet), content, - CreateHoverSounds(sampleSet) }); } From f0ebb920b905a6daa0fe1bc381e50c841f449626 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2023 13:54:00 +0900 Subject: [PATCH 148/154] Make `Action`s nullable --- osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs index e3882588d9..70d1c0c19e 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonRandomV2.cs @@ -17,8 +17,8 @@ namespace osu.Game.Screens.Select.FooterV2 { public partial class FooterButtonRandomV2 : FooterButtonV2 { - public Action NextRandom { get; set; } = null!; - public Action PreviousRandom { get; set; } = null!; + public Action? NextRandom { get; set; } + public Action? PreviousRandom { get; set; } private Container persistentText = null!; private OsuSpriteText randomSpriteText = null!; @@ -83,11 +83,11 @@ namespace osu.Game.Screens.Select.FooterV2 persistentText.FadeInFromZero(fade_time, Easing.In); - PreviousRandom.Invoke(); + PreviousRandom?.Invoke(); } else { - NextRandom.Invoke(); + NextRandom?.Invoke(); } }; } From 90643912262ef9e79531802aaa49a0eddb489ce3 Mon Sep 17 00:00:00 2001 From: PC Date: Tue, 14 Feb 2023 08:24:03 +0300 Subject: [PATCH 149/154] Use `ChildrenOfType` instead of linq --- osu.Game/OsuGame.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 900c07b3c5..ddba5667d8 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -29,6 +29,7 @@ using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Collections; @@ -516,7 +517,7 @@ namespace osu.Game else if (importedSkinsCount > 1) { Settings.Show(); - Settings.SectionsContainer.ScrollTo(Settings.SectionsContainer.Single(container => container is SkinSection)); + Settings.SectionsContainer.ScrollTo(Settings.SectionsContainer.ChildrenOfType().Single()); } } From bd8c58dc62f7a97dba8aa8ce0e629f04f2258bf4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2023 14:34:12 +0900 Subject: [PATCH 150/154] Adjust applied body ratio to ROUGHLY match stable --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index b26e33b133..69eacda541 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -228,7 +228,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy bodySprite.FillMode = FillMode.Stretch; // i dunno this looks about right?? - bodySprite.Scale = new Vector2(1, 10000 / sprite.DrawHeight); + bodySprite.Scale = new Vector2(1, 32800 / sprite.DrawHeight); } break; From ea624b8ad0fa0d9fd78e192edb986abb360f6b3f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 13 Feb 2023 22:39:34 -0800 Subject: [PATCH 151/154] Reset preview track when stopping instead --- osu.Game/Audio/PreviewTrack.cs | 3 +++ osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 2c63c16274..d625566ee7 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -98,6 +98,9 @@ namespace osu.Game.Audio Track.Stop(); + // Ensure the track is reset immediately on stopping, so the next time it is started it has a correct time value. + Track.Seek(0); + Stopped?.Invoke(); } diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs index 8304cdfc08..f808fd21b7 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs @@ -75,9 +75,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons Playing.BindValueChanged(updateState, true); } - protected override void UpdateAfterChildren() + protected override void Update() { - base.UpdateAfterChildren(); + base.Update(); if (Playing.Value && previewTrack != null && previewTrack.TrackLoaded) progress.Value = previewTrack.CurrentTime / previewTrack.Length; From ca2603324cf28123ce3448ff90119034920043dc Mon Sep 17 00:00:00 2001 From: PC Date: Tue, 14 Feb 2023 09:43:40 +0300 Subject: [PATCH 152/154] Change present from skin selection tab to `SkinCollection.First()` --- osu.Game/OsuGame.cs | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ddba5667d8..56e17107b6 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -29,7 +29,6 @@ using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Screens; -using osu.Framework.Testing; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Collections; @@ -50,7 +49,6 @@ using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; using osu.Game.Overlays.Music; using osu.Game.Overlays.Notifications; -using osu.Game.Overlays.Settings.Sections; using osu.Game.Overlays.SkinEditor; using osu.Game.Overlays.Toolbar; using osu.Game.Overlays.Volume; @@ -505,21 +503,10 @@ namespace osu.Game public void ShowChangelogBuild(string updateStream, string version) => waitForReady(() => changelogOverlay, _ => changelogOverlay.ShowBuild(updateStream, version)); /// - /// Present ether a skin select if one skin was imported or navigate to the skin selection menu if multiple skins were imported immediately. + /// Present a skin select immediately. /// - /// List of imported skins - public void PresentSkins(IEnumerable> importedSkins) - { - int importedSkinsCount = importedSkins.Count(); - - if (importedSkinsCount == 1) - SkinManager.CurrentSkinInfo.Value = importedSkins.Single(); - else if (importedSkinsCount > 1) - { - Settings.Show(); - Settings.SectionsContainer.ScrollTo(Settings.SectionsContainer.ChildrenOfType().Single()); - } - } + /// Skin to select + public void PresentSkin(Live importedSkin) => SkinManager.CurrentSkinInfo.Value = importedSkin; /// /// Present a beatmap at song select immediately. @@ -797,7 +784,7 @@ namespace osu.Game // todo: all archive managers should be able to be looped here. SkinManager.PostNotification = n => Notifications.Post(n); - SkinManager.PresentImport = PresentSkins; + SkinManager.PresentImport = items => PresentSkin(items.First()); BeatmapManager.PostNotification = n => Notifications.Post(n); BeatmapManager.PresentImport = items => PresentBeatmap(items.First().Value); From 21429e164ff7e6364a24c50bd382984cf10977c4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2023 15:55:31 +0900 Subject: [PATCH 153/154] Fix comment grammar --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 56e17107b6..6fc420e437 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -505,7 +505,7 @@ namespace osu.Game /// /// Present a skin select immediately. /// - /// Skin to select + /// The skin to select. public void PresentSkin(Live importedSkin) => SkinManager.CurrentSkinInfo.Value = importedSkin; /// From 0ad245e9e031468bbbb86e30f8f641397160bcab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2023 16:00:22 +0900 Subject: [PATCH 154/154] Rewrite implementation to match other implementations --- osu.Game/OsuGame.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6fc420e437..7c9b03bd5b 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -505,8 +505,19 @@ namespace osu.Game /// /// Present a skin select immediately. /// - /// The skin to select. - public void PresentSkin(Live importedSkin) => SkinManager.CurrentSkinInfo.Value = importedSkin; + /// The skin to select. + public void PresentSkin(SkinInfo skin) + { + var databasedSkin = SkinManager.Query(s => s.ID == skin.ID); + + if (databasedSkin == null) + { + Logger.Log("The requested skin could not be loaded.", LoggingTarget.Information); + return; + } + + SkinManager.CurrentSkinInfo.Value = databasedSkin; + } /// /// Present a beatmap at song select immediately. @@ -784,7 +795,7 @@ namespace osu.Game // todo: all archive managers should be able to be looped here. SkinManager.PostNotification = n => Notifications.Post(n); - SkinManager.PresentImport = items => PresentSkin(items.First()); + SkinManager.PresentImport = items => PresentSkin(items.First().Value); BeatmapManager.PostNotification = n => Notifications.Post(n); BeatmapManager.PresentImport = items => PresentBeatmap(items.First().Value);