From fc74726d114f97fd8f885d2ddb42c4bf1bb7b91e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Nov 2025 17:25:40 +0900 Subject: [PATCH 1/8] Ensure the skip overlay shows when someone votes to skip --- .../Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs index 35e85c3273..79fd0eb8d1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs @@ -95,6 +95,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private void onUserVotedToSkipIntro(int userId) => Schedule(() => { + FadingContent.TriggerShow(); + updateText(); countText.ScaleTo(1.5f).ScaleTo(1, 200, Easing.OutSine); From 1c33291b3f041fabc5faf342bcf2b57e7bee042c Mon Sep 17 00:00:00 2001 From: Salman Alshamrani Date: Thu, 4 Dec 2025 13:38:28 -0500 Subject: [PATCH 2/8] Adjust skip button colour and add triangles --- osu.Game/Screens/Play/SkipOverlay.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 700ea2e532..1d7961093a 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -93,7 +93,7 @@ namespace osu.Game.Screens.Play Height = 5, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - Colour = colours.Yellow, + Colour = colours.Orange3, RelativeSizeAxes = Axes.X } } @@ -328,8 +328,8 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(OsuColour colours, AudioManager audio) { - colourNormal = colours.Yellow; - colourHover = colours.YellowDark; + colourNormal = colours.Orange3; + colourHover = colours.Orange4; sampleConfirm = audio.Samples.Get(@"UI/submit-select"); @@ -356,6 +356,11 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Colour = colourNormal, }, + new TrianglesV2 + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(colourNormal.Lighten(0.2f), colourNormal) + }, flow = new FillFlowContainer { Anchor = Anchor.TopCentre, From 99da986e0265379c6ba050c0da9f9b74bd8a62c5 Mon Sep 17 00:00:00 2001 From: Salman Alshamrani Date: Thu, 4 Dec 2025 13:00:47 -0500 Subject: [PATCH 3/8] Implement redesigned multiplayer vote-to-skip button --- .../Multiplayer/MultiplayerSkipOverlay.cs | 297 ++++++++++++++---- osu.Game/Screens/Play/SkipOverlay.cs | 31 +- 2 files changed, 255 insertions(+), 73 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs index 79fd0eb8d1..5c2cc25157 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs @@ -4,15 +4,24 @@ using System; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Play; +using osu.Game.Screens.Ranking; using osuTK; using osuTK.Graphics; @@ -23,92 +32,49 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } = null!; - private Drawable votedIcon = null!; - private OsuSpriteText countText = null!; + [Resolved] + private OsuColour colours { get; set; } = null!; + + private Button skipButton = null!; public MultiplayerSkipOverlay(double startTime) : base(startTime) { } - [BackgroundDependencyLoader] - private void load() + protected override OsuClickableContainer CreateButton() => skipButton = new Button { - FadingContent.AddRange( - [ - votedIcon = new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Position = new Vector2(50, 0), - Size = new Vector2(20), - Alpha = 0, - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Green - }, - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.5f), - Icon = FontAwesome.Solid.Check - } - } - }, - countText = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.X, - Position = new Vector2(0.75f, 0), - Font = OsuFont.Default.With(size: 36, weight: FontWeight.Bold) - } - ]); - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; protected override void LoadComplete() { base.LoadComplete(); + skipButton.Enabled.BindValueChanged(e => + { + RemainingTimeBox.Colour = e.NewValue ? colours.Orange3 : Button.COLOUR_GRAY; + }, true); + client.UserLeft += onUserLeft; client.UserStateChanged += onUserStateChanged; client.UserVotedToSkipIntro += onUserVotedToSkipIntro; - updateText(); + updateCount(); } - private void onUserLeft(MultiplayerRoomUser user) - { - Schedule(updateText); - } + private void onUserLeft(MultiplayerRoomUser user) => Schedule(updateCount); - private void onUserStateChanged(MultiplayerRoomUser user, MultiplayerUserState state) - { - Schedule(updateText); - } + private void onUserStateChanged(MultiplayerRoomUser user, MultiplayerUserState state) => Schedule(updateCount); private void onUserVotedToSkipIntro(int userId) => Schedule(() => { FadingContent.TriggerShow(); - - updateText(); - - countText.ScaleTo(1.5f).ScaleTo(1, 200, Easing.OutSine); - - if (userId == client.LocalUser?.UserID) - { - votedIcon.ScaleTo(1.5f).ScaleTo(1, 200, Easing.OutSine); - votedIcon.FadeInFromZero(100); - } + updateCount(); }); - private void updateText() + private void updateCount() { if (client.Room == null || client.Room.Settings.AutoSkip) return; @@ -117,7 +83,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer int countSkipped = client.Room.Users.Count(u => u.State == MultiplayerUserState.Playing && u.VotedToSkipIntro); int countRequired = countTotal / 2 + 1; - countText.Text = $"{Math.Min(countRequired, countSkipped)} / {countRequired}"; + skipButton.SkippedCount.Value = Math.Min(countRequired, countSkipped); + skipButton.RequiredCount.Value = countRequired; } protected override void Dispose(bool isDisposing) @@ -131,5 +98,211 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer client.UserVotedToSkipIntro -= onUserVotedToSkipIntro; } } + + public partial class Button : OsuClickableContainer + { + private const float chevron_y = 0.4f; + private const float secondary_y = 0.7f; + + public static readonly Color4 COLOUR_GRAY = OsuColour.Gray(0.4f); + + private Box background = null!; + private Box box = null!; + private TrianglesV2 triangles = null!; + private OsuSpriteText countText = null!; + private OsuSpriteText skipText = null!; + private AspectContainer aspect = null!; + + private FillFlowContainer chevrons = null!; + + private Sample sampleConfirm = null!; + + public readonly BindableInt SkippedCount = new BindableInt(); + public readonly BindableInt RequiredCount = new BindableInt(); + + [Resolved] + private OsuColour colours { get; set; } = null!; + + public Button() + { + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleConfirm = audio.Samples.Get(@"UI/submit-select"); + + Children = new Drawable[] + { + background = new Box + { + Alpha = 0.2f, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + aspect = new AspectContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Height = 0.6f, + Masking = true, + CornerRadius = 15, + Children = new Drawable[] + { + box = new Box + { + RelativeSizeAxes = Axes.Both, + }, + triangles = new TrianglesV2 + { + RelativeSizeAxes = Axes.Both, + }, + countText = new OsuSpriteText + { + Anchor = Anchor.TopCentre, + RelativePositionAxes = Axes.Y, + Y = 0.35f, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24), + Origin = Anchor.Centre, + }, + chevrons = new FillFlowContainer + { + Anchor = Anchor.TopCentre, + RelativePositionAxes = Axes.Y, + AutoSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + Children = new[] + { + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.Solid.ChevronRight }, + } + }, + skipText = new OsuSpriteText + { + Anchor = Anchor.TopCentre, + RelativePositionAxes = Axes.Y, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), + Origin = Anchor.Centre, + Text = @"SKIP", + Y = secondary_y, + }, + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + SkippedCount.BindValueChanged(_ => updateCount()); + RequiredCount.BindValueChanged(_ => updateCount(), true); + Enabled.BindValueChanged(_ => updateColours(), true); + + FinishTransforms(true); + } + + private void updateChevronsSpacing() + { + if (SkippedCount.Value > 0 && RequiredCount.Value > 1) + chevrons.TransformSpacingTo(new Vector2(-5f), 500, Easing.OutQuint); + else + chevrons.TransformSpacingTo(IsHovered ? new Vector2(5f) : new Vector2(0f), 500, Easing.OutQuint); + } + + private void updateCount() + { + if (SkippedCount.Value > 0 && RequiredCount.Value > 1) + { + countText.FadeIn(300, Easing.OutQuint); + countText.Text = $"{SkippedCount.Value} / {RequiredCount.Value}"; + + chevrons.ScaleTo(0.5f, 300, Easing.OutQuint) + .MoveTo(new Vector2(-11, secondary_y), 300, Easing.OutQuint); + + skipText.MoveToX(11f, 300, Easing.OutQuint); + } + else + { + countText.FadeOut(300, Easing.OutQuint); + + chevrons.ScaleTo(1f, 300, Easing.OutQuint) + .MoveTo(new Vector2(0, chevron_y), 300, Easing.OutQuint); + + skipText.MoveToX(0f, 300, Easing.OutQuint); + } + + updateChevronsSpacing(); + updateColours(); + } + + private void updateColours() + { + if (!Enabled.Value) + { + box.FadeColour(COLOUR_GRAY, 500, Easing.OutQuint); + triangles.FadeColour(ColourInfo.GradientVertical(COLOUR_GRAY.Lighten(0.2f), COLOUR_GRAY), 500, Easing.OutQuint); + } + else + { + box.FadeColour(IsHovered ? colours.Orange4 : colours.Orange3, 500, Easing.OutQuint); + triangles.FadeColour(ColourInfo.GradientVertical(colours.Orange3.Lighten(0.2f), colours.Orange3), 500, Easing.OutQuint); + } + } + + protected override bool OnHover(HoverEvent e) + { + if (Enabled.Value) + { + updateChevronsSpacing(); + updateColours(); + background.FadeTo(0.4f, 500, Easing.OutQuint); + } + + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateChevronsSpacing(); + updateColours(); + background.FadeTo(0.2f, 500, Easing.OutQuint); + base.OnHoverLost(e); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (Enabled.Value) + aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); + return base.OnMouseDown(e); + } + + protected override void OnMouseUp(MouseUpEvent e) + { + if (Enabled.Value) + aspect.ScaleTo(1, 1000, Easing.OutElastic); + base.OnMouseUp(e); + } + + protected override bool OnClick(ClickEvent e) + { + if (!Enabled.Value) + return false; + + sampleConfirm.Play(); + + box.FlashColour(Color4.White, 500, Easing.OutQuint); + aspect.ScaleTo(1.2f, 2000, Easing.OutQuint); + + base.OnClick(e); + + Enabled.Value = false; + return true; + } + } } } diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 1d7961093a..305117283d 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -10,7 +10,9 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; @@ -19,6 +21,7 @@ using osu.Framework.Input.Events; using osu.Framework.Utils; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; @@ -41,9 +44,10 @@ namespace osu.Game.Screens.Play protected FadeContainer FadingContent { get; private set; } - private Button button; + private OsuClickableContainer button; + private ButtonContainer buttonContainer; - private Circle remainingTimeBox; + protected Circle RemainingTimeBox; private double displayTime; private bool isClickable; @@ -83,12 +87,8 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - button = new Button - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - remainingTimeBox = new Circle + button = CreateButton(), + RemainingTimeBox = new Circle { Height = 5, Anchor = Anchor.BottomCentre, @@ -101,6 +101,12 @@ namespace osu.Game.Screens.Play }; } + protected virtual OsuClickableContainer CreateButton() => new Button + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + private const double fade_time = 300; private double fadeOutBeginTime => startTime - MasterGameplayClockContainer.MINIMUM_SKIP_TIME; @@ -174,10 +180,13 @@ namespace osu.Game.Screens.Play double progress = Math.Max(0, 1 - (gameplayClock.CurrentTime - displayTime) / (fadeOutBeginTime - displayTime)); - remainingTimeBox.Width = (float)Interpolation.Lerp(remainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1)); + RemainingTimeBox.Width = (float)Interpolation.Lerp(RemainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1)); isClickable = progress > 0; - button.Enabled.Value = isClickable; + + if (!isClickable) + button.Enabled.Value = false; + buttonContainer.State.Value = isClickable ? Visibility.Visible : Visibility.Hidden; } @@ -220,7 +229,7 @@ namespace osu.Game.Screens.Play float progress = (float)(gameplayClock.CurrentTime - displayTime) / (float)(fadeOutBeginTime - displayTime); float newWidth = 1 - Math.Clamp(progress, 0, 1); - remainingTimeBox.ResizeWidthTo(newWidth, timingPoint.BeatLength * 3.5, Easing.OutQuint); + RemainingTimeBox.ResizeWidthTo(newWidth, timingPoint.BeatLength * 3.5, Easing.OutQuint); } public partial class FadeContainer : Container, IStateful From fef8117b5cd5c497d49cc93e99417f6abade30e5 Mon Sep 17 00:00:00 2001 From: Salman Alshamrani Date: Thu, 4 Dec 2025 13:00:55 -0500 Subject: [PATCH 4/8] Add test coverage for players leaving during intro --- .../TestSceneMultiplayerSkipOverlay.cs | 78 +++++++++++++++++-- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSkipOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSkipOverlay.cs index 059af2484d..c7ce67d168 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSkipOverlay.cs @@ -1,9 +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.Linq; using NUnit.Framework; using osu.Framework.Extensions; using osu.Framework.Graphics; +using osu.Framework.Testing; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets.Osu; @@ -33,6 +35,9 @@ namespace osu.Game.Tests.Visual.Multiplayer Children = new Drawable[] { new MultiplayerSkipOverlay(120000) + { + RequestSkip = () => MultiplayerClient.VoteToSkipIntro().WaitSafely(), + } }, }; @@ -47,26 +52,83 @@ namespace osu.Game.Tests.Visual.Multiplayer { for (int i = 0; i < 4; i++) { - int i2 = i; + int userId = i; - AddStep($"join user {i2}", () => + AddStep($"join user {userId}", () => { MultiplayerClient.AddUser(new APIUser { - Id = i2, - Username = $"User {i2}" + Id = userId, + Username = $"User {userId}" }); - MultiplayerClient.ChangeUserState(i2, MultiplayerUserState.Playing); + MultiplayerClient.ChangeUserState(userId, MultiplayerUserState.Playing); }); } - AddStep("local user votes", () => MultiplayerClient.VoteToSkipIntro().WaitSafely()); + AddStep("user 0 votes", () => MultiplayerClient.UserVoteToSkipIntro(0).WaitSafely()); + AddStep("local user votes", () => this.ChildrenOfType().Single().TriggerClick()); + AddStep("user 1 votes", () => MultiplayerClient.UserVoteToSkipIntro(1).WaitSafely()); + } + [Test] + public void TestLeavingBeforeLocalVote() + { for (int i = 0; i < 4; i++) { - int i2 = i; - AddStep($"user {i2} votes", () => MultiplayerClient.UserVoteToSkipIntro(i2).WaitSafely()); + int userId = i; + + AddStep($"join user {userId}", () => + { + MultiplayerClient.AddUser(new APIUser + { + Id = userId, + Username = $"User {userId}" + }); + + MultiplayerClient.ChangeUserState(userId, MultiplayerUserState.Playing); + }); + } + + AddStep("user 0 votes", () => MultiplayerClient.UserVoteToSkipIntro(0).WaitSafely()); + AddStep("user 1 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 1 })); + AddStep("user 2 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 2 })); + AddStep("user 3 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 3 })); + AddStep("user 0 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 0 })); + } + + [Test] + public void TestLeavingAfterLocalVote() + { + for (int i = 0; i < 4; i++) + { + int userId = i; + + AddStep($"join user {userId}", () => + { + MultiplayerClient.AddUser(new APIUser + { + Id = userId, + Username = $"User {userId}" + }); + + MultiplayerClient.ChangeUserState(userId, MultiplayerUserState.Playing); + }); + } + + AddStep("local user votes", () => this.ChildrenOfType().Single().TriggerClick()); + AddStep("user 0 votes", () => MultiplayerClient.UserVoteToSkipIntro(0).WaitSafely()); + AddStep("user 1 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 1 })); + AddStep("user 2 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 2 })); + AddStep("user 3 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 3 })); + AddStep("user 0 leaves", () => MultiplayerClient.RemoveUser(new APIUser { Id = 0 })); + } + + public partial class TestMultiplayerSkipOverlay : MultiplayerSkipOverlay + { + public TestMultiplayerSkipOverlay() + : base(120000) + { } } } From 2d8b1e71526f471919447a5a51965ecfc9d48da0 Mon Sep 17 00:00:00 2001 From: Salman Alshamrani Date: Thu, 4 Dec 2025 13:58:41 -0500 Subject: [PATCH 5/8] Make button brighter on hover --- .../Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs index 5c2cc25157..02f28c2c45 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs @@ -249,7 +249,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } else { - box.FadeColour(IsHovered ? colours.Orange4 : colours.Orange3, 500, Easing.OutQuint); + box.FadeColour(IsHovered ? colours.Orange3.Lighten(0.2f) : colours.Orange3, 500, Easing.OutQuint); triangles.FadeColour(ColourInfo.GradientVertical(colours.Orange3.Lighten(0.2f), colours.Orange3), 500, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 305117283d..e17d639a1b 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -338,7 +338,7 @@ namespace osu.Game.Screens.Play private void load(OsuColour colours, AudioManager audio) { colourNormal = colours.Orange3; - colourHover = colours.Orange4; + colourHover = colours.Orange3.Lighten(0.2f); sampleConfirm = audio.Samples.Get(@"UI/submit-select"); From b1e27d842b99188a6e4337f8c3cc881cc8b96fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 5 Dec 2025 12:34:18 +0100 Subject: [PATCH 6/8] Ensure skip counter doesn't overflow the button --- .../OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs index 02f28c2c45..9e237483fe 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerSkipOverlay.cs @@ -303,6 +303,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Enabled.Value = false; return true; } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + countText.Scale = new Vector2(Math.Min(0.85f * aspect.DrawWidth / countText.DrawWidth, 1)); + } } } } From 6343bf7d298887daaedc16cd77c4eae476656a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 5 Dec 2025 12:35:26 +0100 Subject: [PATCH 7/8] Privatise setter --- osu.Game/Screens/Play/SkipOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index e17d639a1b..0509c845f8 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Play private OsuClickableContainer button; private ButtonContainer buttonContainer; - protected Circle RemainingTimeBox; + protected Circle RemainingTimeBox { get; private set; } private double displayTime; private bool isClickable; From 8e2230d14912fb9af70d1066213bd44fcf170302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 5 Dec 2025 13:05:51 +0100 Subject: [PATCH 8/8] Add xmldoc to confusing field I don't have any better ideas at this time. --- osu.Game/Screens/Play/SkipOverlay.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 0509c845f8..361de71103 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -50,7 +50,12 @@ namespace osu.Game.Screens.Play protected Circle RemainingTimeBox { get; private set; } private double displayTime; + + /// + /// Becomes when the overlay starts fading out. + /// private bool isClickable; + private bool skipQueued; [Resolved]