From f262f288fceef2e066761367a0f25297ff411da9 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 6 Aug 2021 19:58:46 +0900 Subject: [PATCH 01/20] Fix DHO state is overwritten to `Idle` on `LoadComplete` The state may already be changed before `LoadComplete` is called because DHO is already added to the draw hierarchy. --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 25f3b8931a..ff6168ee37 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -190,7 +190,9 @@ namespace osu.Game.Rulesets.Objects.Drawables comboIndexBindable.BindValueChanged(_ => UpdateComboColour()); comboIndexWithOffsetsBindable.BindValueChanged(_ => UpdateComboColour(), true); - updateState(ArmedState.Idle, true); + // If the state is changed, transforms are already initialized. + if (state.Value == ArmedState.Idle) + updateState(ArmedState.Idle, true); } /// From 53b98520340a9abf2d0b6415de8d78eb9c27ff12 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 6 Aug 2021 19:59:02 +0900 Subject: [PATCH 02/20] Add test case for DHO state change before load complete --- .../Gameplay/TestSceneDrawableHitObject.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs index 0ce71696bd..58f4c4c8db 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs @@ -2,11 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; using osu.Game.Tests.Visual; namespace osu.Game.Tests.Gameplay @@ -121,6 +123,18 @@ namespace osu.Game.Tests.Gameplay AddAssert("Drawable lifetime is restored", () => dho.LifetimeStart == 666 && dho.LifetimeEnd == 999); } + [Test] + public void TestStateChangeBeforeLoadComplete() + { + TestDrawableHitObject dho = null; + AddStep("Add DHO and apply result", () => + { + Child = dho = new TestDrawableHitObject(new HitObject { StartTime = Time.Current }); + dho.MissForcefully(); + }); + AddAssert("DHO state is correct", () => dho.State.Value == ArmedState.Miss); + } + private class TestDrawableHitObject : DrawableHitObject { public const double INITIAL_LIFETIME_OFFSET = 100; @@ -141,6 +155,19 @@ namespace osu.Game.Tests.Gameplay if (SetLifetimeStartOnApply) LifetimeStart = LIFETIME_ON_APPLY; } + + public void MissForcefully() => ApplyResult(r => r.Type = HitResult.Miss); + + protected override void UpdateHitStateTransforms(ArmedState state) + { + if (state != ArmedState.Miss) + { + base.UpdateHitStateTransforms(state); + return; + } + + this.FadeOut(1000); + } } private class TestLifetimeEntry : HitObjectLifetimeEntry From 9e805dcd44843ef04ea23ed26d311d3a39daebc0 Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Sun, 8 Aug 2021 21:27:32 +1000 Subject: [PATCH 03/20] Fix legacy slider body colour interpolation --- .../Skinning/Legacy/LegacySliderBody.cs | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 744ded37c9..9e4b57ca10 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK.Graphics; @@ -40,7 +39,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Color4 outerColour = AccentColour.Darken(0.1f); Color4 innerColour = lighten(AccentColour, 0.5f); - return Interpolation.ValueAt(position / realGradientPortion, outerColour, innerColour, 0, 1); + // Stable doesn't use linear space / gamma-correct colour interpolation + // for slider bodies, so we can't use Interpolation.ValueAt(). + // Instead, we use a local method that interpolates between the colours directly in sRGB space. + return valueAt(position / realGradientPortion, outerColour, innerColour, 0, 1); } /// @@ -55,6 +57,26 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Math.Min(1, color.B * (1 + 0.5f * amount) + 1 * amount), color.A); } + + private static Color4 valueAt(double time, Color4 startColour, Color4 endColour, double startTime, double endTime) + { + if (startColour == endColour) + return startColour; + + double current = time - startTime; + double duration = endTime - startTime; + + if (duration == 0 || current == 0) + return startColour; + + float t = (float)Math.Max(0, Math.Min(1, current / duration)); + + return new Color4( + startColour.R + t * (endColour.R - startColour.R), + startColour.G + t * (endColour.G - startColour.G), + startColour.B + t * (endColour.B - startColour.B), + startColour.A + t * (endColour.A - startColour.A)); + } } } } From 140d29d53762b1d0df5e44fdcd125410769ca50b Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Sun, 8 Aug 2021 23:54:35 +1000 Subject: [PATCH 04/20] Use helper methods instead of local valueAt() method --- .../Skinning/Legacy/LegacySliderBody.cs | 34 +++++-------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 9e4b57ca10..a8bb69c080 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; using osuTK.Graphics; @@ -36,13 +37,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy position -= realBorderPortion; - Color4 outerColour = AccentColour.Darken(0.1f); - Color4 innerColour = lighten(AccentColour, 0.5f); + // Stable interpolates slider body colour directly in sRGB space, and because + // Interpolation.ValueAt() uses linear space, we have to counteract applying it + // by calling ToSRGB() on the input colours, and ToLinear() on the resulting colour. - // Stable doesn't use linear space / gamma-correct colour interpolation - // for slider bodies, so we can't use Interpolation.ValueAt(). - // Instead, we use a local method that interpolates between the colours directly in sRGB space. - return valueAt(position / realGradientPortion, outerColour, innerColour, 0, 1); + Color4 outerColour = AccentColour.Darken(0.1f).ToSRGB(); + Color4 innerColour = lighten(AccentColour, 0.5f).ToSRGB(); + + return Interpolation.ValueAt(position / realGradientPortion, outerColour, innerColour, 0, 1).ToLinear(); } /// @@ -57,26 +59,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Math.Min(1, color.B * (1 + 0.5f * amount) + 1 * amount), color.A); } - - private static Color4 valueAt(double time, Color4 startColour, Color4 endColour, double startTime, double endTime) - { - if (startColour == endColour) - return startColour; - - double current = time - startTime; - double duration = endTime - startTime; - - if (duration == 0 || current == 0) - return startColour; - - float t = (float)Math.Max(0, Math.Min(1, current / duration)); - - return new Color4( - startColour.R + t * (endColour.R - startColour.R), - startColour.G + t * (endColour.G - startColour.G), - startColour.B + t * (endColour.B - startColour.B), - startColour.A + t * (endColour.A - startColour.A)); - } } } } From a552b659d3f3fae9ac274686c240d83d1b761d51 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 8 Aug 2021 19:36:27 -0700 Subject: [PATCH 05/20] Update build status badge to github actions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 016bd7d922..8f922f74a7 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # osu! -[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) +[![Build status](https://github.com/ppy/osu/actions/workflows/ci.yml/badge.svg?branch=master&event=push)](https://github.com/ppy/osu/actions/workflows/ci.yml) [![GitHub release](https://img.shields.io/github/release/ppy/osu.svg)](https://github.com/ppy/osu/releases/latest) [![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) [![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy) From 1f69c61fd87a5a8b983bdcdbbca6be6d7811e198 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 16:38:21 +0900 Subject: [PATCH 06/20] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 7a0a542ee9..f757847c10 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0a6522f15e..3a840296ac 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 00222877f1..217ec6089a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 24accdcab05b99e1b01a8f71d0f41609738d5d3c Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Mon, 9 Aug 2021 18:56:47 +1000 Subject: [PATCH 07/20] Add LegacyUtils class with non linear colour interpolation method --- .../Skinning/Legacy/LegacySliderBody.cs | 12 ++-- osu.Game/Utils/LegacyUtils.cs | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Utils/LegacyUtils.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index a8bb69c080..92941665e0 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -3,9 +3,9 @@ using System; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; +using osu.Game.Utils; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy @@ -37,14 +37,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy position -= realBorderPortion; - // Stable interpolates slider body colour directly in sRGB space, and because - // Interpolation.ValueAt() uses linear space, we have to counteract applying it - // by calling ToSRGB() on the input colours, and ToLinear() on the resulting colour. + Color4 outerColour = AccentColour.Darken(0.1f); + Color4 innerColour = lighten(AccentColour, 0.5f); - Color4 outerColour = AccentColour.Darken(0.1f).ToSRGB(); - Color4 innerColour = lighten(AccentColour, 0.5f).ToSRGB(); - - return Interpolation.ValueAt(position / realGradientPortion, outerColour, innerColour, 0, 1).ToLinear(); + return LegacyUtils.InterpolateNonLinear(position / realGradientPortion, outerColour, innerColour, 0, 1); } /// diff --git a/osu.Game/Utils/LegacyUtils.cs b/osu.Game/Utils/LegacyUtils.cs new file mode 100644 index 0000000000..9351125acd --- /dev/null +++ b/osu.Game/Utils/LegacyUtils.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.Graphics; +using osu.Framework.Graphics.Transforms; +using osuTK.Graphics; + +namespace osu.Game.Utils +{ + public static class LegacyUtils + { + public static Color4 InterpolateNonLinear(double time, Color4 startColour, Color4 endColour, double startTime, double endTime, Easing easing = Easing.None) + => InterpolateNonLinear(time, startColour, endColour, startTime, endTime, new DefaultEasingFunction(easing)); + + public static Colour4 InterpolateNonLinear(double time, Colour4 startColour, Colour4 endColour, double startTime, double endTime, Easing easing = Easing.None) + => InterpolateNonLinear(time, startColour, endColour, startTime, endTime, new DefaultEasingFunction(easing)); + + /// + /// Interpolates between two sRGB s directly in sRGB space. + /// + public static Color4 InterpolateNonLinear(double time, Color4 startColour, Color4 endColour, double startTime, double endTime, TEasing easing) where TEasing : IEasingFunction + { + if (startColour == endColour) + return startColour; + + double current = time - startTime; + double duration = endTime - startTime; + + if (duration == 0 || current == 0) + return startColour; + + float t = Math.Max(0, Math.Min(1, (float)easing.ApplyEasing(current / duration))); + + return new Color4( + startColour.R + t * (endColour.R - startColour.R), + startColour.G + t * (endColour.G - startColour.G), + startColour.B + t * (endColour.B - startColour.B), + startColour.A + t * (endColour.A - startColour.A)); + } + + /// + /// Interpolates between two sRGB s directly in sRGB space. + /// + public static Colour4 InterpolateNonLinear(double time, Colour4 startColour, Colour4 endColour, double startTime, double endTime, in TEasing easing) where TEasing : IEasingFunction + { + if (startColour == endColour) + return startColour; + + double current = time - startTime; + double duration = endTime - startTime; + + if (duration == 0 || current == 0) + return startColour; + + float t = Math.Max(0, Math.Min(1, (float)easing.ApplyEasing(current / duration))); + + return new Colour4( + startColour.R + t * (endColour.R - startColour.R), + startColour.G + t * (endColour.G - startColour.G), + startColour.B + t * (endColour.B - startColour.B), + startColour.A + t * (endColour.A - startColour.A)); + } + } +} From ea6e441dec4201f10fe21bd71aea833f1cf5c9a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Aug 2021 19:18:13 +0900 Subject: [PATCH 08/20] Simplify method of marking players as playing in test scenes --- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 9 ++++++--- .../TestSceneMultiplayerGameplayLeaderboard.cs | 7 ++++--- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 14 ++++++++------ .../Play/HUD/MultiplayerGameplayLeaderboard.cs | 2 +- .../Visual/Multiplayer/TestMultiplayerClient.cs | 11 ++++++++++- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 072e32370d..e9fae32335 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.UI; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps.IO; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -47,8 +48,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("start players silently", () => { - Client.CurrentMatchPlayingUserIds.Add(PLAYER_1_ID); - Client.CurrentMatchPlayingUserIds.Add(PLAYER_2_ID); + OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_1_ID }, true); + OnlinePlayDependencies.Client.AddUser(new User { Id = PLAYER_2_ID }, true); + playingUserIds.Add(PLAYER_1_ID); playingUserIds.Add(PLAYER_2_ID); }); @@ -264,7 +266,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { foreach (int id in userIds) { - Client.CurrentMatchPlayingUserIds.Add(id); + OnlinePlayDependencies.Client.AddUser(new User { Id = id }, true); + SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); playingUserIds.Add(id); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 0e368b59dd..8121492a0b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -20,6 +20,7 @@ using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -53,10 +54,10 @@ namespace osu.Game.Tests.Visual.Multiplayer var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); foreach (var user in users) + { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); - - // Todo: This is REALLY bad. - Client.CurrentMatchPlayingUserIds.AddRange(users); + OnlinePlayDependencies.Client.AddUser(new User { Id = user }, true); + } Children = new Drawable[] { diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index bffb2d341a..14beb38cde 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -62,7 +62,9 @@ namespace osu.Game.Online.Multiplayer /// /// The users in the joined which are participating in the current gameplay loop. /// - public readonly BindableList CurrentMatchPlayingUserIds = new BindableList(); + public IBindableList CurrentMatchPlayingUserIds => PlayingUserIds; + + protected readonly BindableList PlayingUserIds = new BindableList(); public readonly Bindable CurrentMatchPlayingItem = new Bindable(); @@ -179,7 +181,7 @@ namespace osu.Game.Online.Multiplayer { APIRoom = null; Room = null; - CurrentMatchPlayingUserIds.Clear(); + PlayingUserIds.Clear(); RoomUpdated?.Invoke(); }); @@ -376,7 +378,7 @@ namespace osu.Game.Online.Multiplayer return; Room.Users.Remove(user); - CurrentMatchPlayingUserIds.Remove(user.UserID); + PlayingUserIds.Remove(user.UserID); RoomUpdated?.Invoke(); }, false); @@ -659,16 +661,16 @@ namespace osu.Game.Online.Multiplayer /// The new state of the user. private void updateUserPlayingState(int userId, MultiplayerUserState state) { - bool wasPlaying = CurrentMatchPlayingUserIds.Contains(userId); + bool wasPlaying = PlayingUserIds.Contains(userId); bool isPlaying = state >= MultiplayerUserState.WaitingForLoad && state <= MultiplayerUserState.FinishedPlay; if (isPlaying == wasPlaying) return; if (isPlaying) - CurrentMatchPlayingUserIds.Add(userId); + PlayingUserIds.Add(userId); else - CurrentMatchPlayingUserIds.Remove(userId); + PlayingUserIds.Remove(userId); } private Task scheduleAsync(Action action, CancellationToken cancellationToken = default) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index a10c16fcd5..7ee77759b0 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Play.HUD private UserLookupCache userLookupCache { get; set; } private readonly ScoreProcessor scoreProcessor; - private readonly BindableList playingUsers; + private readonly IBindableList playingUsers; private Bindable scoringMode; /// diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 43aadf5acb..cffaea5c94 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -50,7 +50,16 @@ namespace osu.Game.Tests.Visual.Multiplayer public void Disconnect() => isConnected.Value = false; - public void AddUser(User user) => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(user.Id) { User = user }); + public MultiplayerRoomUser AddUser(User user, bool markAsPlaying = false) + { + var roomUser = new MultiplayerRoomUser(user.Id) { User = user }; + ((IMultiplayerClient)this).UserJoined(roomUser); + + if (markAsPlaying) + PlayingUserIds.Add(user.Id); + + return roomUser; + } public void AddNullUser(int userId) => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(userId)); From 76e5a40b8ed15dfba6bf5812743a5bbf1f15a542 Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Mon, 9 Aug 2021 20:53:02 +1000 Subject: [PATCH 09/20] Remove unnecessary "in" keyword --- osu.Game/Utils/LegacyUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Utils/LegacyUtils.cs b/osu.Game/Utils/LegacyUtils.cs index 9351125acd..64306adf50 100644 --- a/osu.Game/Utils/LegacyUtils.cs +++ b/osu.Game/Utils/LegacyUtils.cs @@ -42,7 +42,7 @@ namespace osu.Game.Utils /// /// Interpolates between two sRGB s directly in sRGB space. /// - public static Colour4 InterpolateNonLinear(double time, Colour4 startColour, Colour4 endColour, double startTime, double endTime, in TEasing easing) where TEasing : IEasingFunction + public static Colour4 InterpolateNonLinear(double time, Colour4 startColour, Colour4 endColour, double startTime, double endTime, TEasing easing) where TEasing : IEasingFunction { if (startColour == endColour) return startColour; From c5b490c4414d64a9dc80353850cad62d707aa85d Mon Sep 17 00:00:00 2001 From: TheOmyNomy Date: Tue, 10 Aug 2021 11:29:31 +1000 Subject: [PATCH 10/20] Use non linear colour interpolation for legacy health display --- osu.Game/Skinning/LegacyHealthDisplay.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacyHealthDisplay.cs b/osu.Game/Skinning/LegacyHealthDisplay.cs index 67280e4acd..b1cd1f86c0 100644 --- a/osu.Game/Skinning/LegacyHealthDisplay.cs +++ b/osu.Game/Skinning/LegacyHealthDisplay.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Utils; using osu.Game.Rulesets.Judgements; using osu.Game.Screens.Play.HUD; +using osu.Game.Utils; using osuTK; using osuTK.Graphics; @@ -83,10 +84,10 @@ namespace osu.Game.Skinning private static Color4 getFillColour(double hp) { if (hp < 0.2) - return Interpolation.ValueAt(0.2 - hp, Color4.Black, Color4.Red, 0, 0.2); + return LegacyUtils.InterpolateNonLinear(0.2 - hp, Color4.Black, Color4.Red, 0, 0.2); if (hp < epic_cutoff) - return Interpolation.ValueAt(0.5 - hp, Color4.White, Color4.Black, 0, 0.5); + return LegacyUtils.InterpolateNonLinear(0.5 - hp, Color4.White, Color4.Black, 0, 0.5); return Color4.White; } From 3aa72163f234ab22dff7a350b1aeba9cafdb76c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 15:14:43 +0900 Subject: [PATCH 11/20] Add simple download progress display to download buttons on playlist items --- osu.Game/Graphics/UserInterface/GrayButton.cs | 4 ++-- .../BeatmapListing/Panels/BeatmapPanelDownloadButton.cs | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/GrayButton.cs b/osu.Game/Graphics/UserInterface/GrayButton.cs index 88c46f29e0..0a2c83d5a8 100644 --- a/osu.Game/Graphics/UserInterface/GrayButton.cs +++ b/osu.Game/Graphics/UserInterface/GrayButton.cs @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load() { - Children = new Drawable[] + AddRange(new Drawable[] { Background = new Box { @@ -42,7 +42,7 @@ namespace osu.Game.Graphics.UserInterface Size = new Vector2(13), Icon = icon, }, - }; + }); } } } diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs index cec1a5ac12..47b477ef9a 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs @@ -37,6 +37,13 @@ namespace osu.Game.Overlays.BeatmapListing.Panels RelativeSizeAxes = Axes.Both, }, }; + + button.Add(new DownloadProgressBar(beatmapSet) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Depth = -1, + }); } protected override void LoadComplete() From 5ea7909eeae16e20c265c95889f459cd0b7e64ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 16:18:57 +0900 Subject: [PATCH 12/20] Fix incorrectly failing test --- .../Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index dfb78a235b..5e30cb86cc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -15,6 +15,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Online.Rooms; using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapListing.Panels; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; @@ -215,7 +216,7 @@ namespace osu.Game.Tests.Visual.Multiplayer assertDownloadButtonVisible(false); void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}", - () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0)); + () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0)); } [Test] @@ -229,7 +230,7 @@ namespace osu.Game.Tests.Visual.Multiplayer createPlaylist(byOnlineId, byChecksum); - AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent)); + AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent)); } [Test] From c63dfa21e130ebf85bf6f860a5fbb427f0eb2f26 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 10 Aug 2021 16:34:38 +0900 Subject: [PATCH 13/20] Always initialize DHO transforms on LoadComplete With the previous commit, the transform application is skipped when the state is already changed. But it turns out the previous commit breaks slider animation in the standard editor. This is probably due to the transforms are applied before nested hit objects are added. --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index ff6168ee37..29d8a475ef 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -190,9 +190,8 @@ namespace osu.Game.Rulesets.Objects.Drawables comboIndexBindable.BindValueChanged(_ => UpdateComboColour()); comboIndexWithOffsetsBindable.BindValueChanged(_ => UpdateComboColour(), true); - // If the state is changed, transforms are already initialized. - if (state.Value == ArmedState.Idle) - updateState(ArmedState.Idle, true); + // Apply transforms + updateState(State.Value, true); } /// From 2b9168157db3e99b2ee759cd71d5114c9642faa2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 16:50:39 +0900 Subject: [PATCH 14/20] Fix `CurrentMatchPlayingItem` not being reset on leaving a multiplayer room --- .../NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs | 4 ++++ osu.Game/Online/Multiplayer/MultiplayerClient.cs | 1 + 2 files changed, 5 insertions(+) diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index 0983b806e2..07ec86b0e7 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -24,6 +24,8 @@ namespace osu.Game.Tests.NonVisual.Multiplayer AddRepeatStep("add some users", () => Client.AddUser(new User { Id = id++ }), 5); checkPlayingUserCount(0); + AddAssert("playlist item is available", () => Client.CurrentMatchPlayingItem.Value != null); + changeState(3, MultiplayerUserState.WaitingForLoad); checkPlayingUserCount(3); @@ -41,6 +43,8 @@ namespace osu.Game.Tests.NonVisual.Multiplayer AddStep("leave room", () => Client.LeaveRoom()); checkPlayingUserCount(0); + + AddAssert("playlist item is null", () => Client.CurrentMatchPlayingItem.Value == null); } [Test] diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 14beb38cde..dafc737ba2 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -181,6 +181,7 @@ namespace osu.Game.Online.Multiplayer { APIRoom = null; Room = null; + CurrentMatchPlayingItem.Value = null; PlayingUserIds.Clear(); RoomUpdated?.Invoke(); From e0e0d5deb0f7debb5ffce87075a847304bdf759c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Aug 2021 17:25:10 +0900 Subject: [PATCH 15/20] Remove unused using --- .../Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 5e30cb86cc..93bdbb79f4 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -14,7 +14,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Online.Rooms; -using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing.Panels; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; From d9b5f235d88a28ba1577a94f479016b1ef81d397 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 17:36:58 +0900 Subject: [PATCH 16/20] Add xmldoc explaining thread safety limitations of `IModelManager` "events" --- osu.Game/Database/IModelManager.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index 7f7e5565f1..8c314f1617 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -13,8 +13,16 @@ namespace osu.Game.Database public interface IModelManager where TModel : class { + /// + /// A bindable which contains a weak reference to the last item that was updated. + /// This is not thread-safe and should be scheduled locally if consumed from a drawable component. + /// IBindable> ItemUpdated { get; } + /// + /// A bindable which contains a weak reference to the last item that was removed. + /// This is not thread-safe and should be scheduled locally if consumed from a drawable component. + /// IBindable> ItemRemoved { get; } } } From b121d95400727bedb1c6d929d8ed5a741e904399 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 17:37:24 +0900 Subject: [PATCH 17/20] Avoid potential null reference exception in `OnlinePlayBeatmapAvailabilityTracker` --- osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs index 72ea84d4a8..86879ba245 100644 --- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs @@ -59,8 +59,8 @@ namespace osu.Game.Online.Rooms protected override bool VerifyDatabasedModel(BeatmapSetInfo databasedSet) { - int? beatmapId = SelectedItem.Value.Beatmap.Value.OnlineBeatmapID; - string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash; + int? beatmapId = SelectedItem.Value?.Beatmap.Value.OnlineBeatmapID; + string checksum = SelectedItem.Value?.Beatmap.Value.MD5Hash; var matchingBeatmap = databasedSet.Beatmaps.FirstOrDefault(b => b.OnlineBeatmapID == beatmapId && b.MD5Hash == checksum); From f86ef54e93dc1ea0e346554bfc5ddbec8f2312f0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Aug 2021 17:36:40 +0900 Subject: [PATCH 18/20] Fix incorrect legacy slider body alpha --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 92941665e0..1c8dfeac52 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy // Roughly matches osu!stable's slider border portions. => base.CalculatedBorderPortion * 0.77f; - public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, base.AccentColour.A * 0.70f); + public new Color4 AccentColour => new Color4(base.AccentColour.R, base.AccentColour.G, base.AccentColour.B, 0.7f); protected override Color4 ColourAt(float position) { From 60302e3daae38014ed9577ffd0c7d172482a05a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 18:46:20 +0900 Subject: [PATCH 19/20] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f757847c10..c1eddfd428 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3a840296ac..55bac93f30 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 217ec6089a..5a0b21f51d 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 58db6b758d07150acbd2b58a92e3b7bea9120c17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Aug 2021 18:47:39 +0900 Subject: [PATCH 20/20] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c1eddfd428..8de516240f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 55bac93f30..59283084db 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5a0b21f51d..c8d3d150db 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - +