From 637119f7d4ae7142d9cef29e8a2cd22000c95fb1 Mon Sep 17 00:00:00 2001 From: iminlikewithyou Date: Thu, 28 Dec 2023 17:15:23 -0600 Subject: [PATCH 1/9] increase the base size of button icons --- osu.Game/Screens/Menu/MainMenuButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index bc638b44ac..a9927541f1 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -125,7 +125,7 @@ public MainMenuButton(LocalisableString text, string sampleName, IconUsage symbo Shadow = true, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(30), + Size = new Vector2(32), Position = new Vector2(0, 0), Icon = symbol }, From 4760c6aaee2bef3a47329158c612d9ea231d4e3b Mon Sep 17 00:00:00 2001 From: iminlikewithyou Date: Thu, 28 Dec 2023 17:17:24 -0600 Subject: [PATCH 2/9] move icon upwards to be visually centered --- osu.Game/Screens/Menu/MainMenuButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index a9927541f1..87136675a2 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -126,7 +126,7 @@ public MainMenuButton(LocalisableString text, string sampleName, IconUsage symbo Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(32), - Position = new Vector2(0, 0), + Position = new Vector2(0, -4), Icon = symbol }, new OsuSpriteText @@ -186,7 +186,7 @@ protected override void OnHoverLost(HoverLostEvent e) { icon.ClearTransforms(); icon.RotateTo(0, 500, Easing.Out); - icon.MoveTo(Vector2.Zero, 500, Easing.Out); + icon.MoveTo(new Vector2(0, -4), 500, Easing.Out); icon.ScaleTo(Vector2.One, 200, Easing.Out); if (State == ButtonState.Expanded) From f1f1221e0e4f5e83f89b74df1c6e1b1c3ce4e04d Mon Sep 17 00:00:00 2001 From: iminlikewithyou Date: Thu, 28 Dec 2023 17:18:41 -0600 Subject: [PATCH 3/9] move text left to be visually centered in the skewed rectangle --- osu.Game/Screens/Menu/MainMenuButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index 87136675a2..69dbaa8ed8 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -135,7 +135,7 @@ public MainMenuButton(LocalisableString text, string sampleName, IconUsage symbo AllowMultiline = false, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Position = new Vector2(0, 35), + Position = new Vector2(-3, 35), Text = text } } From 51d26d2d715f463a13b47d4692daac3d13a9319d Mon Sep 17 00:00:00 2001 From: iminlikewithyou Date: Thu, 28 Dec 2023 17:20:44 -0600 Subject: [PATCH 4/9] make the hover scale bigger as a consequence, the rotation needs to be tweaked to be lower --- osu.Game/Screens/Menu/MainMenuButton.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index 69dbaa8ed8..3d56a75ca8 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -31,6 +31,9 @@ namespace osu.Game.Screens.Menu /// public partial class MainMenuButton : BeatSyncedContainer, IStateful { + public const float BOUNCE_COMPRESSION = 0.9f; + public const float HOVER_SCALE = 1.2f; + public const float BOUNCE_ROTATION = 8; public event Action? StateChanged; public readonly Key[] TriggerKeys; @@ -153,14 +156,14 @@ protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, double duration = timingPoint.BeatLength / 2; - icon.RotateTo(rightward ? 10 : -10, duration * 2, Easing.InOutSine); + icon.RotateTo(rightward ? BOUNCE_ROTATION : -BOUNCE_ROTATION, duration * 2, Easing.InOutSine); icon.Animate( i => i.MoveToY(-10, duration, Easing.Out), - i => i.ScaleTo(1, duration, Easing.Out) + i => i.ScaleTo(HOVER_SCALE, duration, Easing.Out) ).Then( i => i.MoveToY(0, duration, Easing.In), - i => i.ScaleTo(new Vector2(1, 0.9f), duration, Easing.In) + i => i.ScaleTo(new Vector2(HOVER_SCALE, HOVER_SCALE * BOUNCE_COMPRESSION), duration, Easing.In) ); rightward = !rightward; @@ -177,8 +180,8 @@ protected override bool OnHover(HoverEvent e) double duration = TimeUntilNextBeat; icon.ClearTransforms(); - icon.RotateTo(rightward ? -10 : 10, duration, Easing.InOutSine); - icon.ScaleTo(new Vector2(1, 0.9f), duration, Easing.Out); + icon.RotateTo(rightward ? -BOUNCE_ROTATION : BOUNCE_ROTATION, duration, Easing.InOutSine); + icon.ScaleTo(new Vector2(HOVER_SCALE, HOVER_SCALE * BOUNCE_COMPRESSION), duration, Easing.Out); return true; } From cc89390ea89e6b1f8127adef2717e4d6438b7b46 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 30 Dec 2023 21:33:03 +0300 Subject: [PATCH 5/9] Expose `SuggestedOffset` bindable for testing purposes --- .../Sections/Audio/AudioOffsetAdjustControl.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs index 08bf4b0dad..e46dc602eb 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs @@ -24,6 +24,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { public partial class AudioOffsetAdjustControl : SettingsItem { + public IBindable SuggestedOffset => ((AudioOffsetPreview)Control).SuggestedOffset; + [BackgroundDependencyLoader] private void load() { @@ -44,7 +46,7 @@ public Bindable Current private readonly IBindableList averageHitErrorHistory = new BindableList(); - private readonly Bindable suggestedOffset = new Bindable(); + public readonly Bindable SuggestedOffset = new Bindable(); private Container notchContainer = null!; private TextFlowContainer hintText = null!; @@ -90,8 +92,8 @@ private void load(SessionAverageHitErrorTracker hitErrorTracker) Text = "Apply suggested offset", Action = () => { - if (suggestedOffset.Value.HasValue) - current.Value = suggestedOffset.Value.Value; + if (SuggestedOffset.Value.HasValue) + current.Value = SuggestedOffset.Value.Value; hitErrorTracker.ClearHistory(); } } @@ -104,7 +106,7 @@ protected override void LoadComplete() base.LoadComplete(); averageHitErrorHistory.BindCollectionChanged(updateDisplay, true); - suggestedOffset.BindValueChanged(_ => updateHintText(), true); + SuggestedOffset.BindValueChanged(_ => updateHintText(), true); } private void updateDisplay(object? _, NotifyCollectionChangedEventArgs e) @@ -143,17 +145,17 @@ private void updateDisplay(object? _, NotifyCollectionChangedEventArgs e) break; } - suggestedOffset.Value = averageHitErrorHistory.Any() ? -averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset) : null; + SuggestedOffset.Value = averageHitErrorHistory.Any() ? -averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset) : null; } private float getXPositionForOffset(double offset) => (float)(Math.Clamp(offset, current.MinValue, current.MaxValue) / (2 * current.MaxValue)); private void updateHintText() { - hintText.Text = suggestedOffset.Value == null + hintText.Text = SuggestedOffset.Value == null ? @"Play a few beatmaps to receive a suggested offset!" - : $@"Based on the last {averageHitErrorHistory.Count} play(s), the suggested offset is {suggestedOffset.Value:N0} ms."; - applySuggestion.Enabled.Value = suggestedOffset.Value != null; + : $@"Based on the last {averageHitErrorHistory.Count} play(s), the suggested offset is {SuggestedOffset.Value:N0} ms."; + applySuggestion.Enabled.Value = SuggestedOffset.Value != null; } } } From 68dd103c89e25619bf4aea6aea65e61d369396d6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 30 Dec 2023 21:33:22 +0300 Subject: [PATCH 6/9] Add failing test cases --- .../TestSceneAudioOffsetAdjustControl.cs | 88 ++++++++++++++++--- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneAudioOffsetAdjustControl.cs b/osu.Game.Tests/Visual/Settings/TestSceneAudioOffsetAdjustControl.cs index efb65bb0a8..85cde966b1 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneAudioOffsetAdjustControl.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneAudioOffsetAdjustControl.cs @@ -3,7 +3,7 @@ using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; @@ -25,9 +25,15 @@ public partial class TestSceneAudioOffsetAdjustControl : OsuTestScene private Container content = null!; protected override Container Content => content; + private OsuConfigManager localConfig = null!; + private AudioOffsetAdjustControl adjustControl = null!; + [BackgroundDependencyLoader] private void load() { + localConfig = new OsuConfigManager(LocalStorage); + Dependencies.CacheAs(localConfig); + base.Content.AddRange(new Drawable[] { tracker, @@ -41,17 +47,21 @@ private void load() }); } - [Test] - public void TestBehaviour() + [SetUp] + public void SetUp() => Schedule(() => { - AddStep("create control", () => Child = new AudioOffsetAdjustControl + Child = adjustControl = new AudioOffsetAdjustControl { - Current = new BindableDouble - { - MinValue = -500, - MaxValue = 500 - } - }); + Current = localConfig.GetBindable(OsuSetting.AudioOffset), + }; + + localConfig.SetValue(OsuSetting.AudioOffset, 0.0); + tracker.ClearHistory(); + }); + + [Test] + public void TestDisplay() + { AddStep("set new score", () => statics.SetValue(Static.LastLocalUserScore, new ScoreInfo { HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(RNG.NextDouble(-100, 100)), @@ -59,5 +69,63 @@ public void TestBehaviour() })); AddStep("clear history", () => tracker.ClearHistory()); } + + [Test] + public void TestBehaviour() + { + AddStep("set score with -20ms", () => setScore(-20)); + AddAssert("suggested global offset is 20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(20)); + AddStep("clear history", () => tracker.ClearHistory()); + + AddStep("set score with 40ms", () => setScore(40)); + AddAssert("suggested global offset is -40ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(-40)); + AddStep("clear history", () => tracker.ClearHistory()); + } + + [Test] + public void TestNonZeroGlobalOffset() + { + AddStep("set global offset to -20ms", () => localConfig.SetValue(OsuSetting.AudioOffset, -20.0)); + AddStep("set score with -20ms", () => setScore(-20)); + AddAssert("suggested global offset is 0ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(0)); + AddStep("clear history", () => tracker.ClearHistory()); + + AddStep("set global offset to 20ms", () => localConfig.SetValue(OsuSetting.AudioOffset, 20.0)); + AddStep("set score with 40ms", () => setScore(40)); + AddAssert("suggested global offset is -20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(-20)); + AddStep("clear history", () => tracker.ClearHistory()); + } + + [Test] + public void TestMultiplePlays() + { + AddStep("set score with -20ms", () => setScore(-20)); + AddStep("set score with -10ms", () => setScore(-10)); + AddAssert("suggested global offset is 15ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(15)); + AddStep("clear history", () => tracker.ClearHistory()); + + AddStep("set score with -20ms", () => setScore(-20)); + AddStep("set global offset to 30ms", () => localConfig.SetValue(OsuSetting.AudioOffset, 30.0)); + AddStep("set score with 10ms", () => setScore(10)); + AddAssert("suggested global offset is 20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(20)); + AddStep("clear history", () => tracker.ClearHistory()); + } + + private void setScore(double averageHitError) + { + statics.SetValue(Static.LastLocalUserScore, new ScoreInfo + { + HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(averageHitError), + BeatmapInfo = Beatmap.Value.BeatmapInfo, + }); + } + + protected override void Dispose(bool isDisposing) + { + if (localConfig.IsNotNull()) + localConfig.Dispose(); + + base.Dispose(isDisposing); + } } } From e6fe631625643a23b18641a132c6e67c1062b9ee Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 30 Dec 2023 21:34:37 +0300 Subject: [PATCH 7/9] Fix suggested value in audio offset adjust control being opposite in signs --- .../Settings/Sections/Audio/AudioOffsetAdjustControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs index e46dc602eb..90f5a59215 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs @@ -145,7 +145,7 @@ private void updateDisplay(object? _, NotifyCollectionChangedEventArgs e) break; } - SuggestedOffset.Value = averageHitErrorHistory.Any() ? -averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset) : null; + SuggestedOffset.Value = averageHitErrorHistory.Any() ? averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset) : null; } private float getXPositionForOffset(double offset) => (float)(Math.Clamp(offset, current.MinValue, current.MaxValue) / (2 * current.MaxValue)); From 452f201f0673426df7e88b78f720293863e8d660 Mon Sep 17 00:00:00 2001 From: iminlikewithyou Date: Sat, 30 Dec 2023 12:56:38 -0600 Subject: [PATCH 8/9] use margins isntead of moving the position of the sprite --- osu.Game/Screens/Menu/MainMenuButton.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index 3d56a75ca8..422599a4a8 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -129,7 +129,8 @@ public MainMenuButton(LocalisableString text, string sampleName, IconUsage symbo Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(32), - Position = new Vector2(0, -4), + Position = new Vector2(0, 0), + Margin = new MarginPadding { Top = -4 }, Icon = symbol }, new OsuSpriteText @@ -138,7 +139,8 @@ public MainMenuButton(LocalisableString text, string sampleName, IconUsage symbo AllowMultiline = false, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Position = new Vector2(-3, 35), + Position = new Vector2(0, 35), + Margin = new MarginPadding { Left = -3 }, Text = text } } @@ -189,7 +191,7 @@ protected override void OnHoverLost(HoverLostEvent e) { icon.ClearTransforms(); icon.RotateTo(0, 500, Easing.Out); - icon.MoveTo(new Vector2(0, -4), 500, Easing.Out); + icon.MoveTo(Vector2.Zero, 500, Easing.Out); icon.ScaleTo(Vector2.One, 200, Easing.Out); if (State == ButtonState.Expanded) From 922b6ccb83b0e83d9b2be6f63ee7e8366e500c73 Mon Sep 17 00:00:00 2001 From: Gabriel Del Nero <43073074+Gabixel@users.noreply.github.com> Date: Sun, 31 Dec 2023 00:36:55 +0100 Subject: [PATCH 9/9] Use `FontAwesome` solid heart icon instead of `OsuIcon`'s --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 08a816930e..85751e7457 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -145,7 +145,7 @@ private void updateDisplay(APIUser? user) bool anyInfoAdded = false; anyInfoAdded |= tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); - anyInfoAdded |= tryAddInfo(OsuIcon.Heart, user.Interests); + anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Heart, user.Interests); anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation); if (anyInfoAdded)