From 9d28d5f8ee5472356d6ef5fb2a992965b656d751 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 1 Jul 2022 20:43:12 +0900 Subject: [PATCH 01/16] Update SFX for mod overlay show/hide --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 39 ++++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 69cb3a49fc..bf5200902c 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -28,6 +30,9 @@ namespace osu.Game.Overlays.Mods { public const int BUTTON_WIDTH = 200; + protected override string PopInSampleName => ""; + protected override string PopOutSampleName => @"SongSelect/mod-select-overlay-pop-out"; + [Cached] public Bindable> SelectedMods { get; private set; } = new Bindable>(Array.Empty()); @@ -101,17 +106,21 @@ namespace osu.Game.Overlays.Mods private ShearedToggleButton? customisationButton; + private Sample? columnAppearSample; + protected ModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Green) : base(colourScheme) { } [BackgroundDependencyLoader] - private void load(OsuGameBase game, OsuColour colours) + private void load(OsuGameBase game, OsuColour colours, AudioManager audio) { Header.Title = ModSelectOverlayStrings.ModSelectTitle; Header.Description = ModSelectOverlayStrings.ModSelectDescription; + columnAppearSample = audio.Samples.Get(@"SongSelect/mod-column-pop-in"); + AddRange(new Drawable[] { new ClickToReturnContainer @@ -453,8 +462,32 @@ namespace osu.Game.Overlays.Mods .MoveToY(0, duration, Easing.OutQuint) .FadeIn(duration, Easing.OutQuint); - if (!allFiltered) - nonFilteredColumnCount += 1; + if (allFiltered) + continue; + + int columnNumber = nonFilteredColumnCount; + Scheduler.AddDelayed(() => + { + var channel = columnAppearSample?.GetChannel(); + if (channel == null) return; + + // don't play sample if column isn't visible, but try to play it at least 5 times (assuming there's at least 5 visible columns in `columnFlow`) + if (columnNumber > 5 && !column.Active.Value) return; + + // use X position of the column on screen as a basis for panning the sample + var bounds = column.Parent.BoundingBox; + float balance = (bounds.TopLeft.X + bounds.Width / 2) / RelativeToAbsoluteFactor.X; + + // dip frequency and ramp volume of sample over the first 5 displayed columns + float progress = Math.Min(1, columnNumber / 5f); + + channel.Frequency.Value = 1.3 - (progress * 0.3) + RNG.NextDouble(0.1); + channel.Volume.Value = Math.Max(progress, 0.2); + channel.Balance.Value = -1 + balance * 2; + channel.Play(); + }, delay); + + nonFilteredColumnCount += 1; } } From 76d4f86ca3616bc00b9fb62b62244496ab8c5661 Mon Sep 17 00:00:00 2001 From: goodtrailer Date: Fri, 1 Jul 2022 18:21:03 -0700 Subject: [PATCH 02/16] Make legacy slider ball fade out instantly --- .../Skinning/Legacy/LegacySliderBall.cs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index 07e60c82d0..f3be52b227 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -7,6 +7,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK.Graphics; @@ -18,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private readonly ISkin skin; + private DrawableSlider slider; + private Sprite layerNd; private Sprite layerSpec; @@ -30,8 +34,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy } [BackgroundDependencyLoader] - private void load() + private void load(DrawableHitObject dho) { + slider = (DrawableSlider)dho; + var ballColour = skin.GetConfig(OsuSkinColour.SliderBall)?.Value ?? Color4.White; InternalChildren = new[] @@ -56,6 +62,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Blending = BlendingParameters.Additive, }, }; + + slider.ApplyCustomUpdateState += updateStateTransforms; } protected override void UpdateAfterChildren() @@ -68,5 +76,25 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy layerNd.Rotation = -appliedRotation; layerSpec.Rotation = -appliedRotation; } + + private void updateStateTransforms(DrawableHitObject obj, ArmedState _) + { + if (obj is not DrawableSlider) + return; + + using (BeginAbsoluteSequence(slider.StateUpdateTime)) + this.FadeIn(); + + using (BeginAbsoluteSequence(slider.HitStateUpdateTime)) + this.FadeOut(); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (slider != null) + slider.ApplyCustomUpdateState -= updateStateTransforms; + } } } From 623a99d53abda7e654e4e7a660e0364e2ef54026 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Jul 2022 11:58:45 +0900 Subject: [PATCH 03/16] 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 584fe0a3ef..86f4337521 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 ff223f5107..40c22c1b21 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 b8a4aca02e..09ae70a01f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -62,7 +62,7 @@ - + From 4fd47b5fa0fffdc882779ac11a78b7bbc0f492b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Jul 2022 12:35:29 +0900 Subject: [PATCH 04/16] Add more verbose logging to realm blocking process --- osu.Game.Tests/Database/GeneralUsageTests.cs | 8 ++++---- osu.Game.Tests/Database/RealmLiveTests.cs | 2 +- .../Database/RealmSubscriptionRegistrationTests.cs | 12 ++++++------ osu.Game/Database/EFToRealmMigrator.cs | 2 +- osu.Game/Database/RealmAccess.cs | 11 ++++++++--- osu.Game/OsuGameBase.cs | 2 +- .../Sections/DebugSettings/MemorySettings.cs | 4 ++-- 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Database/GeneralUsageTests.cs b/osu.Game.Tests/Database/GeneralUsageTests.cs index 5b6f7a0a53..fd0b391d0d 100644 --- a/osu.Game.Tests/Database/GeneralUsageTests.cs +++ b/osu.Game.Tests/Database/GeneralUsageTests.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealm((realm, _) => { - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { } }); @@ -56,7 +56,7 @@ namespace osu.Game.Tests.Database { Task writeTask; - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { writeTask = realm.WriteAsync(r => r.Add(TestResources.CreateTestBeatmapSetInfo())); Thread.Sleep(100); @@ -169,7 +169,7 @@ namespace osu.Game.Tests.Database Assert.Throws(() => { - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { } }); @@ -177,7 +177,7 @@ namespace osu.Game.Tests.Database stopThreadedUsage.Set(); // Ensure we can block a second time after the usage has ended. - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { } }); diff --git a/osu.Game.Tests/Database/RealmLiveTests.cs b/osu.Game.Tests/Database/RealmLiveTests.cs index fd1f564f59..a50eb22c67 100644 --- a/osu.Game.Tests/Database/RealmLiveTests.cs +++ b/osu.Game.Tests/Database/RealmLiveTests.cs @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Database { migratedStorage.DeleteDirectory(string.Empty); - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { storage.Migrate(migratedStorage); } diff --git a/osu.Game.Tests/Database/RealmSubscriptionRegistrationTests.cs b/osu.Game.Tests/Database/RealmSubscriptionRegistrationTests.cs index c74341b5c9..4ee302bbd0 100644 --- a/osu.Game.Tests/Database/RealmSubscriptionRegistrationTests.cs +++ b/osu.Game.Tests/Database/RealmSubscriptionRegistrationTests.cs @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Database resolvedItems = null; lastChanges = null; - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) Assert.That(resolvedItems, Is.Empty); realm.Write(r => r.Add(TestResources.CreateTestBeatmapSetInfo())); @@ -154,7 +154,7 @@ namespace osu.Game.Tests.Database testEventsArriving(false); // And make sure even after another context loss we don't get firings. - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) Assert.That(resolvedItems, Is.Null); realm.Write(r => r.Add(TestResources.CreateTestBeatmapSetInfo())); @@ -212,7 +212,7 @@ namespace osu.Game.Tests.Database Assert.That(beatmapSetInfo, Is.Not.Null); - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { // custom disposal action fired when context lost. Assert.That(beatmapSetInfo, Is.Null); @@ -226,7 +226,7 @@ namespace osu.Game.Tests.Database Assert.That(beatmapSetInfo, Is.Null); - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) Assert.That(beatmapSetInfo, Is.Null); realm.Run(r => r.Refresh()); @@ -251,7 +251,7 @@ namespace osu.Game.Tests.Database Assert.That(receivedValue, Is.Not.Null); receivedValue = null; - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { } @@ -262,7 +262,7 @@ namespace osu.Game.Tests.Database subscription.Dispose(); receivedValue = null; - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) Assert.That(receivedValue, Is.Null); realm.Run(r => r.Refresh()); diff --git a/osu.Game/Database/EFToRealmMigrator.cs b/osu.Game/Database/EFToRealmMigrator.cs index 896d111989..8f2ff600d8 100644 --- a/osu.Game/Database/EFToRealmMigrator.cs +++ b/osu.Game/Database/EFToRealmMigrator.cs @@ -126,7 +126,7 @@ namespace osu.Game.Database string backupSuffix = $"before_final_migration_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"; // required for initial backup. - var realmBlockOperations = realm.BlockAllOperations(); + var realmBlockOperations = realm.BlockAllOperations("EF migration"); Task.Factory.StartNew(() => { diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 8cf9bb4a47..9c7ecd8a03 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -780,7 +780,7 @@ namespace osu.Game.Database public void CreateBackup(string backupFilename, IDisposable? blockAllOperations = null) { - using (blockAllOperations ?? BlockAllOperations()) + using (blockAllOperations ?? BlockAllOperations("creating backup")) { Logger.Log($"Creating full realm database backup at {backupFilename}", LoggingTarget.Database); @@ -811,9 +811,12 @@ namespace osu.Game.Database /// This should be used in places we need to ensure no ongoing reads/writes are occurring with realm. /// ie. to move the realm backing file to a new location. /// + /// The reason for blocking. Used for logging purposes. /// An which should be disposed to end the blocking section. - public IDisposable BlockAllOperations() + public IDisposable BlockAllOperations(string reason) { + Logger.Log($@"Attempting to block all realm operations for {reason}.", LoggingTarget.Database); + if (!ThreadSafety.IsUpdateThread) throw new InvalidOperationException(@$"{nameof(BlockAllOperations)} must be called from the update thread."); @@ -843,7 +846,7 @@ namespace osu.Game.Database updateRealm = null; } - Logger.Log(@"Blocking realm operations.", LoggingTarget.Database); + Logger.Log(@"Lock acquired for blocking operations", LoggingTarget.Database); const int sleep_length = 200; int timeout = 5000; @@ -867,6 +870,8 @@ namespace osu.Game.Database Logger.Log($"Realm compact failed with error {e}", LoggingTarget.Database); } + Logger.Log(@"Realm usage isolated via compact", LoggingTarget.Database); + // In order to ensure events arrive in the correct order, these *must* be fired post disposal of the update realm, // and must be posted to the synchronization context. // This is because realm may fire event callbacks between the `unregisterAllSubscriptions` and `updateRealm.Dispose` diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 9a001c92cd..ead3eeb0dc 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -446,7 +446,7 @@ namespace osu.Game Scheduler.Add(() => { - realmBlocker = realm.BlockAllOperations(); + realmBlocker = realm.BlockAllOperations("migration"); readyToRun.Set(); }, false); diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs index 77eede0e46..42ac4adb34 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings Action = () => { // Blocking operations implicitly causes a Compact(). - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("compact")) { } } @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings { try { - var token = realm.BlockAllOperations(); + var token = realm.BlockAllOperations("maintenance"); blockAction.Enabled.Value = false; From 1fd9c6480394798d4b0fb814fbed9a3b067db2c4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Jul 2022 12:48:33 +0900 Subject: [PATCH 05/16] Change song select `FooterButton` sound --- osu.Game/Screens/Select/FooterButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index c251e94ef2..6c9032f5d8 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Select private readonly Box light; public FooterButton() - : base(HoverSampleSet.Toolbar) + : base(HoverSampleSet.Default) { AutoSizeAxes = Axes.Both; Shear = SHEAR; From a03abc747b9ff4042d1be6117f7de620884da249 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Jul 2022 12:58:34 +0900 Subject: [PATCH 06/16] Tidy up comments and simplify bounding box centre logic --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 5 ++--- osu.Game/Screens/Select/FooterButton.cs | 10 ++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index bf5200902c..04c424461e 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -471,12 +471,11 @@ namespace osu.Game.Overlays.Mods var channel = columnAppearSample?.GetChannel(); if (channel == null) return; - // don't play sample if column isn't visible, but try to play it at least 5 times (assuming there's at least 5 visible columns in `columnFlow`) + // Still play sound effects for off-screen columns up to a certain point. if (columnNumber > 5 && !column.Active.Value) return; // use X position of the column on screen as a basis for panning the sample - var bounds = column.Parent.BoundingBox; - float balance = (bounds.TopLeft.X + bounds.Width / 2) / RelativeToAbsoluteFactor.X; + float balance = column.Parent.BoundingBox.Centre.X / RelativeToAbsoluteFactor.X; // dip frequency and ramp volume of sample over the first 5 displayed columns float progress = Math.Min(1, columnNumber / 5f); diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 6c9032f5d8..3f8cf2e13a 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -4,19 +4,18 @@ #nullable disable using System; -using osuTK; -using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; 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.Sprites; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; -using osu.Framework.Input.Bindings; -using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Select { @@ -68,7 +67,6 @@ namespace osu.Game.Screens.Select private readonly Box light; public FooterButton() - : base(HoverSampleSet.Default) { AutoSizeAxes = Axes.Both; Shear = SHEAR; From 2352636bf2455b8f8e111df0aadc6c2858a7f427 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Jul 2022 13:11:49 +0900 Subject: [PATCH 07/16] Fix ID clash with announce and PM channels in chat overlay tests Yet Another Issue. https://github.com/ppy/osu/runs/7159306924?check_suite_focus=true Not sure why announce channel was using a user id for its channel ID. Bad copy paste? --- osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 247ea52648..0b982a5745 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -576,12 +576,13 @@ namespace osu.Game.Tests.Visual.Online private Channel createAnnounceChannel() { - int id = RNG.Next(0, DummyAPIAccess.DUMMY_USER_ID - 1); + const int announce_channel_id = 133337; + return new Channel { - Name = $"Announce {id}", + Name = $"Announce {announce_channel_id}", Type = ChannelType.Announce, - Id = id, + Id = announce_channel_id, }; } From 2e3ff2c7e0a86b1d9e03859fa6f83bc057d9d962 Mon Sep 17 00:00:00 2001 From: goodtrailer Date: Fri, 1 Jul 2022 21:12:36 -0700 Subject: [PATCH 08/16] Prefer [Resolved] and LoadComplete --- .../Skinning/Legacy/LegacySliderBall.cs | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index f3be52b227..fdf7f18bb9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -1,14 +1,12 @@ // 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.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK.Graphics; @@ -20,10 +18,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private readonly ISkin skin; - private DrawableSlider slider; + [Resolved(canBeNull: true)] + private DrawableHitObject? drawableObject { get; set; } - private Sprite layerNd; - private Sprite layerSpec; + private Sprite layerNd = null!; + private Sprite layerSpec = null!; public LegacySliderBall(Drawable animationContent, ISkin skin) { @@ -36,8 +35,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy [BackgroundDependencyLoader] private void load(DrawableHitObject dho) { - slider = (DrawableSlider)dho; - var ballColour = skin.GetConfig(OsuSkinColour.SliderBall)?.Value ?? Color4.White; InternalChildren = new[] @@ -62,8 +59,17 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Blending = BlendingParameters.Additive, }, }; + } - slider.ApplyCustomUpdateState += updateStateTransforms; + protected override void LoadComplete() + { + base.LoadComplete(); + + if (drawableObject != null) + { + drawableObject.ApplyCustomUpdateState += updateStateTransforms; + updateStateTransforms(drawableObject, drawableObject.State.Value); + } } protected override void UpdateAfterChildren() @@ -79,13 +85,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private void updateStateTransforms(DrawableHitObject obj, ArmedState _) { - if (obj is not DrawableSlider) - return; - - using (BeginAbsoluteSequence(slider.StateUpdateTime)) + using (BeginAbsoluteSequence(drawableObject.AsNonNull().StateUpdateTime)) this.FadeIn(); - using (BeginAbsoluteSequence(slider.HitStateUpdateTime)) + using (BeginAbsoluteSequence(drawableObject.AsNonNull().HitStateUpdateTime)) this.FadeOut(); } @@ -93,8 +96,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { base.Dispose(isDisposing); - if (slider != null) - slider.ApplyCustomUpdateState -= updateStateTransforms; + if (drawableObject != null) + drawableObject.ApplyCustomUpdateState -= updateStateTransforms; } } } From 6d6ffd35d01c9ffb8d40943fa50776ef3974a2be Mon Sep 17 00:00:00 2001 From: goodtrailer Date: Fri, 1 Jul 2022 21:14:53 -0700 Subject: [PATCH 09/16] Remove unused parameter --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index fdf7f18bb9..57422e3709 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy } [BackgroundDependencyLoader] - private void load(DrawableHitObject dho) + private void load() { var ballColour = skin.GetConfig(OsuSkinColour.SliderBall)?.Value ?? Color4.White; From 471b64bd20619ff1124193cde8bc9621bce4d476 Mon Sep 17 00:00:00 2001 From: goodtrailer Date: Fri, 1 Jul 2022 21:19:54 -0700 Subject: [PATCH 10/16] Reinstate early return with comment Whoops, didn't read the reply until after I pushed... --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index 57422e3709..e9fa5cbe43 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK.Graphics; @@ -85,6 +86,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private void updateStateTransforms(DrawableHitObject obj, ArmedState _) { + // Gets called by slider ticks, tails, etc., leading to duplicated + // animations which in this case have no visual impact (due to + // instant fade) but may negatively affect performance + if (obj is not DrawableSlider) + return; + using (BeginAbsoluteSequence(drawableObject.AsNonNull().StateUpdateTime)) this.FadeIn(); From f2141715b8c6f22eba91df5f98d1f1eb91017c35 Mon Sep 17 00:00:00 2001 From: goodtrailer Date: Fri, 1 Jul 2022 21:22:48 -0700 Subject: [PATCH 11/16] Replace AsNonNull() with Assert() --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index e9fa5cbe43..d0745450da 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -1,8 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; using osu.Framework.Allocation; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -92,10 +92,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy if (obj is not DrawableSlider) return; - using (BeginAbsoluteSequence(drawableObject.AsNonNull().StateUpdateTime)) + Debug.Assert(drawableObject != null); + + using (BeginAbsoluteSequence(drawableObject.StateUpdateTime)) this.FadeIn(); - using (BeginAbsoluteSequence(drawableObject.AsNonNull().HitStateUpdateTime)) + using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime)) this.FadeOut(); } From 9a5431d93f2688a01249729619d9154af84f2f9e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Jul 2022 13:36:41 +0900 Subject: [PATCH 12/16] Minor renaming / refactoring to use local parameter rather than DI'd object --- .../Skinning/Legacy/LegacySliderBall.cs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index d0745450da..414879f42d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.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.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private readonly ISkin skin; [Resolved(canBeNull: true)] - private DrawableHitObject? drawableObject { get; set; } + private DrawableHitObject? parentObject { get; set; } private Sprite layerNd = null!; private Sprite layerSpec = null!; @@ -66,10 +65,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { base.LoadComplete(); - if (drawableObject != null) + if (parentObject != null) { - drawableObject.ApplyCustomUpdateState += updateStateTransforms; - updateStateTransforms(drawableObject, drawableObject.State.Value); + parentObject.ApplyCustomUpdateState += updateStateTransforms; + updateStateTransforms(parentObject, parentObject.State.Value); } } @@ -84,16 +83,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy layerSpec.Rotation = -appliedRotation; } - private void updateStateTransforms(DrawableHitObject obj, ArmedState _) + private void updateStateTransforms(DrawableHitObject drawableObject, ArmedState _) { // Gets called by slider ticks, tails, etc., leading to duplicated // animations which in this case have no visual impact (due to // instant fade) but may negatively affect performance - if (obj is not DrawableSlider) + if (drawableObject is not DrawableSlider) return; - Debug.Assert(drawableObject != null); - using (BeginAbsoluteSequence(drawableObject.StateUpdateTime)) this.FadeIn(); @@ -105,8 +102,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { base.Dispose(isDisposing); - if (drawableObject != null) - drawableObject.ApplyCustomUpdateState -= updateStateTransforms; + if (parentObject != null) + parentObject.ApplyCustomUpdateState -= updateStateTransforms; } } } From 93809a92d4d9fdf2e355fc81e03c65c783c2958b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Jul 2022 16:30:04 +0900 Subject: [PATCH 13/16] Fix clashing error messaging during realm block operations --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 9c7ecd8a03..cfb0280d2d 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -860,7 +860,7 @@ namespace osu.Game.Database timeout -= sleep_length; if (timeout < 0) - throw new TimeoutException(@"Took too long to acquire lock"); + throw new TimeoutException($@"Realm compact failed after {timeout / sleep_length} attempts over {timeout / 1000} seconds"); } } catch (RealmException e) From e28ee8bc7a7bc6ce7628cc1ee9e50a1c8e783719 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 2 Jul 2022 10:46:52 +0300 Subject: [PATCH 14/16] Count time spent upwards to display attempts correctly --- osu.Game/Database/RealmAccess.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index cfb0280d2d..ed56049064 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -849,7 +849,7 @@ namespace osu.Game.Database Logger.Log(@"Lock acquired for blocking operations", LoggingTarget.Database); const int sleep_length = 200; - int timeout = 5000; + int timeSpent = 0; try { @@ -857,10 +857,10 @@ namespace osu.Game.Database while (!Compact()) { Thread.Sleep(sleep_length); - timeout -= sleep_length; + timeSpent += sleep_length; - if (timeout < 0) - throw new TimeoutException($@"Realm compact failed after {timeout / sleep_length} attempts over {timeout / 1000} seconds"); + if (timeSpent > 5000) + throw new TimeoutException($@"Realm compact failed after {timeSpent / sleep_length} attempts over {timeSpent / 1000} seconds"); } } catch (RealmException e) From 24cd845d1b9f69b24a23f4bcc53cb4d4b4c83933 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 2 Jul 2022 17:18:50 +0900 Subject: [PATCH 15/16] 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 86f4337521..ceea60a1c1 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 40c22c1b21..560f7409ff 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 09ae70a01f..0133c6334c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -61,7 +61,7 @@ - + @@ -84,7 +84,7 @@ - + From b626135940eb728c64acc49dd0facc98f7e8b10b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Jun 2022 04:39:59 +0900 Subject: [PATCH 16/16] Fix dragging slider bars on nub not performing correctly relative movement --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 3356153e17..7cd89e5b87 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -165,6 +165,9 @@ namespace osu.Game.Graphics.UserInterface base.OnHoverLost(e); } + protected override bool ShouldHandleAsRelativeDrag(MouseDownEvent e) + => Nub.ReceivePositionalInputAt(e.ScreenSpaceMouseDownPosition); + protected override void OnDragEnd(DragEndEvent e) { updateGlow();