From 6fe5cacd3c5ccc9102a1444ecbeef563f35381d8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 14 Jun 2022 20:05:07 +0300 Subject: [PATCH 1/7] Fix hot reload crashing toolbar test scene --- .../Visual/Menus/TestSceneToolbar.cs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index eb77453199..7cb467aa19 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using JetBrains.Annotations; using Moq; using NUnit.Framework; using osu.Framework.Allocation; @@ -13,6 +14,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Game.Graphics.Containers; using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Toolbar; using osu.Game.Rulesets; using osuTK.Graphics; @@ -28,14 +30,14 @@ namespace osu.Game.Tests.Visual.Menus [Resolved] private IRulesetStore rulesets { get; set; } - private readonly Mock notifications = new Mock(); + private readonly Mock notifications = new Mock(); private readonly BindableInt unreadNotificationCount = new BindableInt(); [BackgroundDependencyLoader] private void load() { - Dependencies.CacheAs(notifications.Object); + Dependencies.CacheAs(notifications.Object); notifications.SetupGet(n => n.UnreadCount).Returns(unreadNotificationCount); } @@ -126,5 +128,21 @@ namespace osu.Game.Tests.Visual.Menus { public new Bindable OverlayActivationMode => base.OverlayActivationMode as Bindable; } + + // interface mocks break hot reload, mocking this stub implementation instead works around it. + // see: https://github.com/moq/moq4/issues/1252 + [UsedImplicitly] + public class TestNotificationOverlay : INotificationOverlay + { + public virtual void Post(Notification notification) + { + } + + public virtual void Hide() + { + } + + public virtual IBindable UnreadCount => null; + } } } From 7f23677972b5bfc794eabdfce1361d025fa5bf70 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 14 Jun 2022 20:35:09 +0300 Subject: [PATCH 2/7] Add volume control support via toolbar music button --- .../Visual/Menus/TestSceneToolbar.cs | 38 ++++++++++++++++++- .../Overlays/Toolbar/ToolbarMusicButton.cs | 10 +++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 7cb467aa19..09fae2fb77 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -30,6 +30,21 @@ namespace osu.Game.Tests.Visual.Menus [Resolved] private IRulesetStore rulesets { get; set; } + [Cached] + private readonly NowPlayingOverlay nowPlayingOverlay = new NowPlayingOverlay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Y = Toolbar.HEIGHT, + }; + + [Cached] + private readonly VolumeOverlay volumeOverlay = new VolumeOverlay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }; + private readonly Mock notifications = new Mock(); private readonly BindableInt unreadNotificationCount = new BindableInt(); @@ -44,7 +59,15 @@ namespace osu.Game.Tests.Visual.Menus [SetUp] public void SetUp() => Schedule(() => { - Child = toolbar = new TestToolbar { State = { Value = Visibility.Visible } }; + Remove(nowPlayingOverlay); + Remove(volumeOverlay); + + Children = new Drawable[] + { + nowPlayingOverlay, + volumeOverlay, + toolbar = new TestToolbar { State = { Value = Visibility.Visible } }, + }; }); [Test] @@ -124,6 +147,19 @@ namespace osu.Game.Tests.Visual.Menus AddAssert("not scrolled", () => scroll.Current == 0); } + [Test] + public void TestVolumeControlViaMusicButton() + { + AddStep("hover toolbar music button", () => InputManager.MoveMouseTo(this.ChildrenOfType().Single())); + + AddStep("reset volume", () => Audio.Volume.Value = 1); + + AddRepeatStep("scroll down", () => InputManager.ScrollVerticalBy(-10), 5); + AddAssert("volume lowered down", () => Audio.Volume.Value < 1); + AddRepeatStep("scroll up", () => InputManager.ScrollVerticalBy(10), 5); + AddAssert("volume raised up", () => Audio.Volume.Value == 1); + } + public class TestToolbar : Toolbar { public new Bindable OverlayActivationMode => base.OverlayActivationMode as Bindable; diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 0f5e8e5456..9804c857bf 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Toolbar @@ -21,5 +22,14 @@ namespace osu.Game.Overlays.Toolbar { StateContainer = music; } + + [Resolved(canBeNull: true)] + private VolumeOverlay volume { get; set; } + + protected override bool OnScroll(ScrollEvent e) + { + volume?.Adjust(GlobalAction.IncreaseVolume, e.ScrollDelta.Y, e.IsPrecise); + return true; + } } } From 1f31e3fb5199b646c00ed448fe1ca2b7658752e8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 14 Jun 2022 22:13:26 +0300 Subject: [PATCH 3/7] Add volume UI to toolbar music button --- .../Overlays/Toolbar/ToolbarMusicButton.cs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 9804c857bf..34dc3b4080 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -2,30 +2,79 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Bindables; +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.Input.Bindings; +using osuTK.Graphics; namespace osu.Game.Overlays.Toolbar { public class ToolbarMusicButton : ToolbarOverlayToggleButton { + private Circle volumeBar; + protected override Anchor TooltipAnchor => Anchor.TopRight; public ToolbarMusicButton() { Hotkey = GlobalAction.ToggleNowPlaying; + AutoSizeAxes = Axes.X; } [BackgroundDependencyLoader(true)] private void load(NowPlayingOverlay music) { StateContainer = music; + + Flow.Padding = new MarginPadding { Horizontal = Toolbar.HEIGHT / 4 }; + Flow.Add(new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 3f, + Height = IconContainer.Height, + Margin = new MarginPadding { Horizontal = 2.5f }, + Masking = true, + Children = new[] + { + new Circle + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White.Opacity(0.25f), + }, + volumeBar = new Circle + { + RelativeSizeAxes = Axes.Both, + Height = 0f, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = Color4.White, + } + } + }); } + [Resolved] + private AudioManager audio { get; set; } + [Resolved(canBeNull: true)] private VolumeOverlay volume { get; set; } + private IBindable globalVolume; + + protected override void LoadComplete() + { + base.LoadComplete(); + + globalVolume = audio.Volume.GetBoundCopy(); + globalVolume.BindValueChanged(v => volumeBar.Height = (float)v.NewValue, true); + } + protected override bool OnScroll(ScrollEvent e) { volume?.Adjust(GlobalAction.IncreaseVolume, e.ScrollDelta.Y, e.IsPrecise); From 5eb56ab814a465e0ef52daaeb40b59a626bc4dae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Jun 2022 15:41:38 +0900 Subject: [PATCH 4/7] Ensure `Master` volume is updated when scrolling on toolbar button --- osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs | 1 + osu.Game/Overlays/VolumeOverlay.cs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 34dc3b4080..0c948990a0 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -77,6 +77,7 @@ namespace osu.Game.Overlays.Toolbar protected override bool OnScroll(ScrollEvent e) { + volume?.FocusMasterVolume(); volume?.Adjust(GlobalAction.IncreaseVolume, e.ScrollDelta.Y, e.IsPrecise); return true; } diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 9d2ed3f837..46ea45491e 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -140,11 +140,16 @@ namespace osu.Game.Overlays private ScheduledDelegate popOutDelegate; + public void FocusMasterVolume() + { + volumeMeters.Select(volumeMeterMaster); + } + public override void Show() { // Focus on the master meter as a default if previously hidden if (State.Value == Visibility.Hidden) - volumeMeters.Select(volumeMeterMaster); + FocusMasterVolume(); if (State.Value == Visibility.Visible) schedulePopOut(); From 3df9d7c9e1b37d386b43f739eb8f8383122d2d2a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Jun 2022 15:56:59 +0900 Subject: [PATCH 5/7] Add a bit more animation when adjusting --- .../Overlays/Toolbar/ToolbarMusicButton.cs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 0c948990a0..689b750826 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -8,7 +8,9 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Transforms; using osu.Framework.Input.Events; +using osu.Framework.Threading; using osu.Game.Input.Bindings; using osuTK.Graphics; @@ -32,7 +34,7 @@ namespace osu.Game.Overlays.Toolbar StateContainer = music; Flow.Padding = new MarginPadding { Horizontal = Toolbar.HEIGHT / 4 }; - Flow.Add(new Container + Flow.Add(volumeDisplay = new Container { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -66,20 +68,46 @@ namespace osu.Game.Overlays.Toolbar private VolumeOverlay volume { get; set; } private IBindable globalVolume; + private Container volumeDisplay; protected override void LoadComplete() { base.LoadComplete(); globalVolume = audio.Volume.GetBoundCopy(); - globalVolume.BindValueChanged(v => volumeBar.Height = (float)v.NewValue, true); + globalVolume.BindValueChanged(v => volumeBar.ResizeHeightTo((float)v.NewValue, 200, Easing.OutQuint), true); } protected override bool OnScroll(ScrollEvent e) { - volume?.FocusMasterVolume(); + focusForAdjustment(); volume?.Adjust(GlobalAction.IncreaseVolume, e.ScrollDelta.Y, e.IsPrecise); return true; } + + private void focusForAdjustment() + { + volume?.FocusMasterVolume(); + expandVolumeBarTemporarily(); + } + + private TransformSequence expandTransform; + private ScheduledDelegate contractTransform; + + private void expandVolumeBarTemporarily() + { + // avoid starting a new transform if one is already active. + if (expandTransform == null) + { + expandTransform = volumeDisplay.ResizeWidthTo(6, 500, Easing.OutQuint); + expandTransform.Finally(_ => expandTransform = null); + } + + contractTransform?.Cancel(); + contractTransform = Scheduler.AddDelayed(() => + { + volumeDisplay.ResizeWidthTo(3f, 500, Easing.OutQuint); + }, 1000); + } } } From 873806c2ea4112d4ef7510d37933340b7921a1b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Jun 2022 15:57:09 +0900 Subject: [PATCH 6/7] Add keyboard adjustment support --- .../Visual/Menus/TestSceneToolbar.cs | 15 ++++++++++++++- .../Overlays/Toolbar/ToolbarMusicButton.cs | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 09fae2fb77..f230e48b11 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -148,7 +148,7 @@ namespace osu.Game.Tests.Visual.Menus } [Test] - public void TestVolumeControlViaMusicButton() + public void TestVolumeControlViaMusicButtonScroll() { AddStep("hover toolbar music button", () => InputManager.MoveMouseTo(this.ChildrenOfType().Single())); @@ -160,6 +160,19 @@ namespace osu.Game.Tests.Visual.Menus AddAssert("volume raised up", () => Audio.Volume.Value == 1); } + [Test] + public void TestVolumeControlViaMusicButtonArrowKeys() + { + AddStep("hover toolbar music button", () => InputManager.MoveMouseTo(this.ChildrenOfType().Single())); + + AddStep("reset volume", () => Audio.Volume.Value = 1); + + AddRepeatStep("arrow down", () => InputManager.Key(Key.Down), 5); + AddAssert("volume lowered down", () => Audio.Volume.Value < 1); + AddRepeatStep("arrow up", () => InputManager.Key(Key.Up), 5); + AddAssert("volume raised up", () => Audio.Volume.Value == 1); + } + public class TestToolbar : Toolbar { public new Bindable OverlayActivationMode => base.OverlayActivationMode as Bindable; diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 689b750826..2104fcbbfe 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -13,6 +13,7 @@ using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Game.Input.Bindings; using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Overlays.Toolbar { @@ -78,6 +79,24 @@ namespace osu.Game.Overlays.Toolbar globalVolume.BindValueChanged(v => volumeBar.ResizeHeightTo((float)v.NewValue, 200, Easing.OutQuint), true); } + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Up: + focusForAdjustment(); + volume?.Adjust(GlobalAction.IncreaseVolume); + return true; + + case Key.Down: + focusForAdjustment(); + volume?.Adjust(GlobalAction.IncreaseVolume, -1); + return true; + } + + return base.OnKeyDown(e); + } + protected override bool OnScroll(ScrollEvent e) { focusForAdjustment(); From 583619b9151fad54c4abde8c915846fda62b0bd5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 15 Jun 2022 10:21:27 +0300 Subject: [PATCH 7/7] Use `GlobalAction.DecreaseVolume` instead --- osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 2104fcbbfe..d59127d61f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Toolbar case Key.Down: focusForAdjustment(); - volume?.Adjust(GlobalAction.IncreaseVolume, -1); + volume?.Adjust(GlobalAction.DecreaseVolume); return true; }