From 857e943b8d5b3924378a1de65804d6fdc4c5467d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 11 Sep 2022 17:30:14 +0800 Subject: [PATCH 01/82] hide catchcombo when Hud hide --- .../Legacy/LegacyCatchComboCounter.cs | 2 - .../UI/CatchComboDisplay.cs | 64 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs index b2dd29841b..b4d29988d9 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs @@ -1,8 +1,6 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Catch.UI; diff --git a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs index e9c289e46a..a923aca2c8 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs @@ -4,9 +4,13 @@ #nullable disable using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Configuration; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; using osu.Game.Skinning; using osuTK.Graphics; @@ -22,11 +26,69 @@ namespace osu.Game.Rulesets.Catch.UI [CanBeNull] public ICatchComboCounter ComboCounter => Drawable as ICatchComboCounter; + private Bindable hudVisibilityMode = null!; + + private readonly BindableBool replayLoaded = new BindableBool(); + + private readonly BindableBool showCombo = new BindableBool(); + + [Resolved] + private OsuConfigManager config { get; set; } + public CatchComboDisplay() : base(new CatchSkinComponent(CatchSkinComponents.CatchComboCounter), _ => Empty()) { } + [BackgroundDependencyLoader(true)] + private void load(DrawableRuleset drawableRuleset) + { + hudVisibilityMode = config.GetBindable(OsuSetting.HUDVisibilityMode); + + hudVisibilityMode.BindValueChanged(s => + { + updateVisibilityState(); + }); + + if (drawableRuleset != null) + replayLoaded.BindTo(drawableRuleset.HasReplayLoaded); + + replayLoaded.BindValueChanged(s => + { + updateVisibilityState(); + }); + + showCombo.BindValueChanged(s => + { + if (ComboCounter == null) return; + + if (!s.NewValue) + { + ComboCounter.Hide(); + } + }); + + updateVisibilityState(); + + void updateVisibilityState() + { + switch (hudVisibilityMode.Value) + { + case HUDVisibilityMode.Never: + showCombo.Value = false; + break; + + case HUDVisibilityMode.HideDuringGameplay: + showCombo.Value = replayLoaded.Value; + break; + + case HUDVisibilityMode.Always: + showCombo.Value = true; + break; + } + } + } + protected override void SkinChanged(ISkinSource skin) { base.SkinChanged(skin); @@ -57,6 +119,8 @@ namespace osu.Game.Rulesets.Catch.UI private void updateCombo(int newCombo, Color4? hitObjectColour) { + if (!showCombo.Value) return; + currentCombo = newCombo; ComboCounter?.UpdateCombo(newCombo, hitObjectColour); } From 2bd72fd9b439f6b723ed43f963b7b5db62daf8d6 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 12 Sep 2022 17:53:38 +0800 Subject: [PATCH 02/82] add test for hide catchercombo --- .../TestSceneComboCounter.cs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs index 7f513728af..f39af76a2d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs @@ -1,12 +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 System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Utils; +using osu.Game.Configuration; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.UI; @@ -19,15 +19,25 @@ namespace osu.Game.Rulesets.Catch.Tests { public class TestSceneComboCounter : CatchSkinnableTestScene { - private ScoreProcessor scoreProcessor; + private OsuConfigManager localConfig = null!; + + private ScoreProcessor scoreProcessor = null!; private Color4 judgedObjectColour = Color4.White; + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(localConfig = new OsuConfigManager(LocalStorage)); + } + [SetUp] public void SetUp() => Schedule(() => { scoreProcessor = new ScoreProcessor(new CatchRuleset()); + localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always); + SetContents(_ => new CatchComboDisplay { Anchor = Anchor.Centre, @@ -51,9 +61,15 @@ namespace osu.Game.Rulesets.Catch.Tests 1f ); }); + + AddStep("set hud to never show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + AddRepeatStep("perform hit", () => performJudgement(HitResult.Great), 5); + + AddStep("set hud to show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always)); + AddRepeatStep("perform hit", () => performJudgement(HitResult.Great), 5); } - private void performJudgement(HitResult type, Judgement judgement = null) + private void performJudgement(HitResult type, Judgement? judgement = null) { var judgedObject = new DrawableFruit(new Fruit()) { AccentColour = { Value = judgedObjectColour } }; From 1721b8e47aad4959d3b20f7516cb151e44938b92 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 16:25:26 +0300 Subject: [PATCH 03/82] Add request class --- .../API/Requests/CommentDeleteRequest.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 osu.Game/Online/API/Requests/CommentDeleteRequest.cs diff --git a/osu.Game/Online/API/Requests/CommentDeleteRequest.cs b/osu.Game/Online/API/Requests/CommentDeleteRequest.cs new file mode 100644 index 0000000000..4eb91718fe --- /dev/null +++ b/osu.Game/Online/API/Requests/CommentDeleteRequest.cs @@ -0,0 +1,28 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Net.Http; +using osu.Framework.IO.Network; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class CommentDeleteRequest : APIRequest + { + private readonly long id; + + public CommentDeleteRequest(long id) + { + this.id = id; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Delete; + return req; + } + + protected override string Target => $@"comments/{id}"; + } +} From 710f9e8f588907b61efb5eb4bd5032fc4237a41b Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 18:11:27 +0300 Subject: [PATCH 04/82] Setup a test scene --- .../Visual/Online/TestSceneCommentActions.cs | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs new file mode 100644 index 0000000000..2778cb509a --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -0,0 +1,109 @@ +// 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 System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Overlays.Comments; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneCommentActions : OsuTestScene + { + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + + [Cached] + private readonly DialogOverlay dialogOverlay = new DialogOverlay(); + + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + + private CommentsContainer commentsContainer = null!; + + [SetUpSteps] + public void SetUp() + { + API.Login("test", "test"); + Schedule(() => + { + if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); + Children = new Container[] + { + new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = commentsContainer = new CommentsContainer() + }, + dialogOverlay + }; + }); + } + + [Test] + public void TestNonOwnCommentCantBeDeleted() + { + addTestComments(); + } + + [Test] + public void TestDeletion() + { + addTestComments(); + } + + private void addTestComments() + { + CommentBundle cb = new CommentBundle + { + Comments = new List + { + new Comment + { + Id = 1, + Message = "This is our comment", + UserId = API.LocalUser.Value.Id, + CreatedAt = DateTimeOffset.Now, + User = API.LocalUser.Value, + }, + new Comment + { + Id = 2, + Message = "This is a comment by another user", + UserId = API.LocalUser.Value.Id + 1, + CreatedAt = DateTimeOffset.Now, + User = new APIUser + { + Id = API.LocalUser.Value.Id + 1, + Username = "Another user" + } + }, + }, + IncludedComments = new List(), + PinnedComments = new List(), + }; + setUpCommentsResponse(cb); + AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123)); + } + + private void setUpCommentsResponse(CommentBundle commentBundle) + => AddStep("set up response", () => + { + dummyAPI.HandleRequest = request => + { + if (!(request is GetCommentsRequest getCommentsRequest)) + return false; + + getCommentsRequest.TriggerSuccess(commentBundle); + return true; + }; + }); + } +} From 31a7ba3f9135be69c9de81682585b65ec783f6bc Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 18:23:15 +0300 Subject: [PATCH 05/82] Add delete button --- osu.Game/Overlays/Comments/DrawableComment.cs | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 296320ec1b..a0b752b842 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -22,6 +22,8 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.IEnumerableExtensions; using System.Collections.Specialized; using osu.Framework.Localisation; +using osu.Framework.Logging; +using osu.Game.Online.API; using osu.Game.Overlays.Comments.Buttons; using osu.Game.Resources.Localisation.Web; @@ -59,10 +61,11 @@ namespace osu.Game.Overlays.Comments } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load(OverlayColourProvider colourProvider, IAPIProvider api) { LinkFlowContainer username; FillFlowContainer info; + LinkFlowContainer actions; CommentMarkdownContainer message; GridContainer content; VotePill votePill; @@ -163,16 +166,30 @@ namespace osu.Game.Overlays.Comments DocumentMargin = new MarginPadding(0), DocumentPadding = new MarginPadding(0), }, - info = new FillFlowContainer + new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(10, 0), - Children = new Drawable[] + Children = new[] { - new DrawableDate(Comment.CreatedAt, 12, false) + info = new FillFlowContainer { - Colour = colourProvider.Foreground1 + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new DrawableDate(Comment.CreatedAt, 12, false) + { + Colour = colourProvider.Foreground1 + } + } + }, + actions = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold)) + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(10, 0) } } }, @@ -288,6 +305,11 @@ namespace osu.Game.Overlays.Comments votePill.Hide(); } + if (Comment.UserId.HasValue && Comment.UserId.Value == api.LocalUser.Value.Id) + { + actions.AddLink("Delete", () => Logger.Log("Attempt to delete a comment", level: LogLevel.Important)); + } + if (Comment.IsTopLevel) { AddInternal(new Box From 60ee813e45e462d354fbfd400818938bf6a0f192 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 18:33:16 +0300 Subject: [PATCH 06/82] Implement delete button --- osu.Game/Overlays/Comments/DrawableComment.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index a0b752b842..20869d1250 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -22,9 +22,10 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.IEnumerableExtensions; using System.Collections.Specialized; using osu.Framework.Localisation; -using osu.Framework.Logging; using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Overlays.Comments.Buttons; +using osu.Game.Overlays.Dialog; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Comments @@ -61,7 +62,7 @@ namespace osu.Game.Overlays.Comments } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, IAPIProvider api) + private void load(OverlayColourProvider colourProvider, IAPIProvider api, DialogOverlay dialogOverlay) { LinkFlowContainer username; FillFlowContainer info; @@ -307,7 +308,20 @@ namespace osu.Game.Overlays.Comments if (Comment.UserId.HasValue && Comment.UserId.Value == api.LocalUser.Value.Id) { - actions.AddLink("Delete", () => Logger.Log("Attempt to delete a comment", level: LogLevel.Important)); + actions.AddLink("Delete", () => + { + dialogOverlay.Push(new ConfirmDialog("Do you really want to delete your comment?", () => + { + var request = new CommentDeleteRequest(Comment.Id); + request.Success += _ => + { + //TODO this is temporary just for testing + content.FadeColour(OsuColour.Gray(0.5f)); + votePill.Hide(); + }; + api.Queue(request); + })); + }); } if (Comment.IsTopLevel) From 5da7cb5397867b99d671d21c81dd395ee270b284 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 19:02:18 +0300 Subject: [PATCH 07/82] Make comment ID public for test --- osu.Game/Online/API/Requests/CommentDeleteRequest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/CommentDeleteRequest.cs b/osu.Game/Online/API/Requests/CommentDeleteRequest.cs index 4eb91718fe..4209ff9d30 100644 --- a/osu.Game/Online/API/Requests/CommentDeleteRequest.cs +++ b/osu.Game/Online/API/Requests/CommentDeleteRequest.cs @@ -9,11 +9,11 @@ namespace osu.Game.Online.API.Requests { public class CommentDeleteRequest : APIRequest { - private readonly long id; + public readonly long ID; public CommentDeleteRequest(long id) { - this.id = id; + this.ID = id; } protected override WebRequest CreateWebRequest() @@ -23,6 +23,6 @@ namespace osu.Game.Online.API.Requests return req; } - protected override string Target => $@"comments/{id}"; + protected override string Target => $@"comments/{ID}"; } } From 2f551be1befa1fd1d0c6d8b6387bc023a3fd0efe Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 19:03:02 +0300 Subject: [PATCH 08/82] Implement tests --- .../Visual/Online/TestSceneCommentActions.cs | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index 2778cb509a..dcab92d772 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -3,20 +3,23 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.Comments; +using osuTK.Input; namespace osu.Game.Tests.Visual.Online { - public class TestSceneCommentActions : OsuTestScene + public class TestSceneCommentActions : OsuManualInputManagerTestScene { private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; @@ -51,12 +54,80 @@ namespace osu.Game.Tests.Visual.Online public void TestNonOwnCommentCantBeDeleted() { addTestComments(); + + AddAssert("First comment has button", () => + { + var comments = this.ChildrenOfType(); + var ourComment = comments.Single(x => x.Comment.Id == 1); + return ourComment.ChildrenOfType().Any(x => x.Text == "Delete"); + }); + + AddAssert("Second doesn't", () => + { + var comments = this.ChildrenOfType(); + var ourComment = comments.Single(x => x.Comment.Id == 2); + return ourComment.ChildrenOfType().All(x => x.Text != "Delete"); + }); } [Test] public void TestDeletion() { + DrawableComment ourComment = null!; + bool delete = false; + addTestComments(); + AddStep("Comment exists", () => + { + var comments = this.ChildrenOfType(); + ourComment = comments.Single(x => x.Comment.Id == 1); + }); + AddStep("It has delete button", () => + { + var btn = ourComment.ChildrenOfType().Single(x => x.Text == "Delete"); + InputManager.MoveMouseTo(btn); + }); + AddStep("Click delete button", () => + { + InputManager.Click(MouseButton.Left); + }); + AddStep("Setup request handling", () => + { + dummyAPI.HandleRequest = request => + { + if (!(request is CommentDeleteRequest req)) + return false; + + if (req.ID != 1) + return false; + + CommentBundle cb = new CommentBundle + { + Comments = new List + { + new Comment + { + Id = 2, + Message = "This is a comment by another user", + UserId = API.LocalUser.Value.Id + 1, + CreatedAt = DateTimeOffset.Now, + User = new APIUser + { + Id = API.LocalUser.Value.Id + 1, + Username = "Another user" + } + }, + }, + IncludedComments = new List(), + PinnedComments = new List(), + }; + delete = true; + req.TriggerSuccess(cb); + return true; + }; + }); + AddStep("Confirm dialog", () => InputManager.Key(Key.Number1)); + AddUntilStep("Deletion requested", () => delete); } private void addTestComments() From 5282c8b8c65cd3acda6488571c1de0bd903f36a7 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 19:40:18 +0300 Subject: [PATCH 09/82] Fix CQ --- osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs | 2 +- osu.Game/Online/API/Requests/CommentDeleteRequest.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index dcab92d772..2ffdc3be27 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.Online if (!(request is CommentDeleteRequest req)) return false; - if (req.ID != 1) + if (req.CommentId != 1) return false; CommentBundle cb = new CommentBundle diff --git a/osu.Game/Online/API/Requests/CommentDeleteRequest.cs b/osu.Game/Online/API/Requests/CommentDeleteRequest.cs index 4209ff9d30..b150a6d5fc 100644 --- a/osu.Game/Online/API/Requests/CommentDeleteRequest.cs +++ b/osu.Game/Online/API/Requests/CommentDeleteRequest.cs @@ -9,11 +9,11 @@ namespace osu.Game.Online.API.Requests { public class CommentDeleteRequest : APIRequest { - public readonly long ID; + public readonly long CommentId; public CommentDeleteRequest(long id) { - this.ID = id; + CommentId = id; } protected override WebRequest CreateWebRequest() @@ -23,6 +23,6 @@ namespace osu.Game.Online.API.Requests return req; } - protected override string Target => $@"comments/{ID}"; + protected override string Target => $@"comments/{CommentId}"; } } From 4013c96ca556410b3d4feddd729bb37f58ac3aa1 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 22:40:53 +0300 Subject: [PATCH 10/82] Fix test failures --- .../Visual/Online/TestSceneCommentActions.cs | 15 +++++++------- .../Online/TestSceneCommentsContainer.cs | 20 ++++++++++++++----- .../Visual/Online/TestSceneDrawableComment.cs | 5 +++++ .../TestSceneOfflineCommentsContainer.cs | 5 +++++ 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index 2ffdc3be27..88e4d6e83b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -34,9 +34,9 @@ namespace osu.Game.Tests.Visual.Online [SetUpSteps] public void SetUp() { - API.Login("test", "test"); Schedule(() => { + API.Login("test", "test"); if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); Children = new Container[] { @@ -55,11 +55,11 @@ namespace osu.Game.Tests.Visual.Online { addTestComments(); - AddAssert("First comment has button", () => + AddUntilStep("First comment has button", () => { var comments = this.ChildrenOfType(); - var ourComment = comments.Single(x => x.Comment.Id == 1); - return ourComment.ChildrenOfType().Any(x => x.Text == "Delete"); + var ourComment = comments.SingleOrDefault(x => x.Comment.Id == 1); + return ourComment != null && ourComment.ChildrenOfType().Any(x => x.Text == "Delete"); }); AddAssert("Second doesn't", () => @@ -73,14 +73,15 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestDeletion() { - DrawableComment ourComment = null!; + DrawableComment? ourComment = null; bool delete = false; addTestComments(); - AddStep("Comment exists", () => + AddUntilStep("Comment exists", () => { var comments = this.ChildrenOfType(); - ourComment = comments.Single(x => x.Comment.Id == 1); + ourComment = comments.SingleOrDefault(x => x.Comment.Id == 1); + return ourComment != null; }); AddStep("It has delete button", () => { diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index a94b9e61c0..08881e9718 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -25,17 +25,27 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + [Cached] + private readonly DialogOverlay dialogOverlay = new DialogOverlay(); + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; private CommentsContainer commentsContainer; [SetUp] public void SetUp() => Schedule(() => - Child = new BasicScrollContainer + { + if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Child = commentsContainer = new CommentsContainer() - }); + new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = commentsContainer = new CommentsContainer() + }, + dialogOverlay + }; + }); [Test] public void TestIdleState() @@ -139,7 +149,7 @@ namespace osu.Game.Tests.Visual.Online }; }); - private CommentBundle getExampleComments(bool withPinned = false) + private static CommentBundle getExampleComments(bool withPinned = false) { var bundle = new CommentBundle { diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index cab0ffa3ba..7253424984 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -20,11 +20,15 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + [Cached] + private readonly DialogOverlay dialogOverlay = new DialogOverlay(); + private Container container; [SetUp] public void SetUp() => Schedule(() => { + if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); Children = new Drawable[] { new Box @@ -37,6 +41,7 @@ namespace osu.Game.Tests.Visual.Online RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }, + dialogOverlay }; }); diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index 07ccfcec88..46bbbd635a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -24,17 +24,22 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + [Cached] + private readonly DialogOverlay dialogOverlay = new DialogOverlay(); + private TestCommentsContainer comments; [SetUp] public void SetUp() => Schedule(() => { + if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); Clear(); Add(new BasicScrollContainer { RelativeSizeAxes = Axes.Both, Child = comments = new TestCommentsContainer() }); + Add(dialogOverlay); }); [Test] From 58d9509ce686b5e96c0d592bf93f913b5f0ca2a9 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 22:45:05 +0300 Subject: [PATCH 11/82] Apply NRT to `Comment` --- .../Online/API/Requests/Responses/Comment.cs | 16 +++++++--------- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 500c0566e6..907632186c 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -1,8 +1,6 @@ // 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 Newtonsoft.Json; using System; @@ -16,18 +14,18 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"parent_id")] public long? ParentId { get; set; } - public Comment ParentComment { get; set; } + public Comment? ParentComment { get; set; } [JsonProperty(@"user_id")] public long? UserId { get; set; } - public APIUser User { get; set; } + public APIUser? User { get; set; } [JsonProperty(@"message")] - public string Message { get; set; } + public string Message { get; set; } = null!; [JsonProperty(@"message_html")] - public string MessageHtml { get; set; } + public string? MessageHtml { get; set; } [JsonProperty(@"replies_count")] public int RepliesCount { get; set; } @@ -36,13 +34,13 @@ namespace osu.Game.Online.API.Requests.Responses public int VotesCount { get; set; } [JsonProperty(@"commenatble_type")] - public string CommentableType { get; set; } + public string CommentableType { get; set; } = null!; [JsonProperty(@"commentable_id")] public int CommentableId { get; set; } [JsonProperty(@"legacy_name")] - public string LegacyName { get; set; } + public string? LegacyName { get; set; } [JsonProperty(@"created_at")] public DateTimeOffset CreatedAt { get; set; } @@ -62,7 +60,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"pinned")] public bool Pinned { get; set; } - public APIUser EditedUser { get; set; } + public APIUser? EditedUser { get; set; } public bool IsTopLevel => !ParentId.HasValue; diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 20869d1250..39f46210b0 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -266,7 +266,7 @@ namespace osu.Game.Overlays.Comments else username.AddText(Comment.LegacyName); - if (Comment.EditedAt.HasValue) + if (Comment.EditedAt.HasValue && Comment.EditedUser != null) { var font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular); var colour = colourProvider.Foreground1; From ae0d62838b76b9d451ab5e3f273a7eda74e48358 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 27 Sep 2022 22:46:23 +0300 Subject: [PATCH 12/82] Move API and DO to fields --- osu.Game/Overlays/Comments/DrawableComment.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 39f46210b0..03499ad375 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -56,13 +56,19 @@ namespace osu.Game.Overlays.Comments private ChevronButton chevronButton; private DeletedCommentsCounter deletedCommentsCounter; + [Resolved] + private DialogOverlay dialogOverlay { get; set; } + + [Resolved] + private IAPIProvider api { get; set; } + public DrawableComment(Comment comment) { Comment = comment; } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, IAPIProvider api, DialogOverlay dialogOverlay) + private void load(OverlayColourProvider colourProvider) { LinkFlowContainer username; FillFlowContainer info; From 636befb499d4307f023d007bcbb9ef40e49a0f61 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Wed, 28 Sep 2022 17:49:37 +0300 Subject: [PATCH 13/82] Add visual feedback for deleting process --- osu.Game/Overlays/Comments/DrawableComment.cs | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 03499ad375..f78778b96a 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -22,6 +22,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.IEnumerableExtensions; using System.Collections.Specialized; using osu.Framework.Localisation; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Comments.Buttons; @@ -54,6 +55,8 @@ namespace osu.Game.Overlays.Comments private ShowMoreRepliesButton showMoreButton; private ShowRepliesButton showRepliesButton; private ChevronButton chevronButton; + private LinkFlowContainer actionsContainer; + private LoadingSpinner actionsLoading; private DeletedCommentsCounter deletedCommentsCounter; [Resolved] @@ -72,7 +75,6 @@ namespace osu.Game.Overlays.Comments { LinkFlowContainer username; FillFlowContainer info; - LinkFlowContainer actions; CommentMarkdownContainer message; GridContainer content; VotePill votePill; @@ -178,7 +180,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(10, 0), - Children = new[] + Children = new Drawable[] { info = new FillFlowContainer { @@ -193,10 +195,16 @@ namespace osu.Game.Overlays.Comments } } }, - actions = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold)) + actionsContainer = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold)) { AutoSizeAxes = Axes.Both, Spacing = new Vector2(10, 0) + }, + actionsLoading = new LoadingSpinner + { + Size = new Vector2(12f), + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft } } }, @@ -314,20 +322,7 @@ namespace osu.Game.Overlays.Comments if (Comment.UserId.HasValue && Comment.UserId.Value == api.LocalUser.Value.Id) { - actions.AddLink("Delete", () => - { - dialogOverlay.Push(new ConfirmDialog("Do you really want to delete your comment?", () => - { - var request = new CommentDeleteRequest(Comment.Id); - request.Success += _ => - { - //TODO this is temporary just for testing - content.FadeColour(OsuColour.Gray(0.5f)); - votePill.Hide(); - }; - api.Queue(request); - })); - }); + actionsContainer.AddLink("Delete", deleteComment); } if (Comment.IsTopLevel) @@ -359,6 +354,30 @@ namespace osu.Game.Overlays.Comments }; } + private void deleteComment() + { + dialogOverlay.Push(new ConfirmDialog("Do you really want to delete your comment?", () => + { + actionsContainer.Hide(); + actionsLoading.Show(); + var request = new CommentDeleteRequest(Comment.Id); + request.Success += _ => + { + actionsLoading.Hide(); + AutoSizeAxes = Axes.None; + Masking = true; + this.ResizeHeightTo(0, 1000, Easing.Out); + this.FadeOut(1000, Easing.Out).Expire(); + }; + request.Failure += _ => + { + actionsLoading.Hide(); + actionsContainer.Show(); + }; + api.Queue(request); + })); + } + protected override void LoadComplete() { ShowDeleted.BindValueChanged(show => From 965e7bf265b9e73a20c58f19e9ba7259fbe7b3da Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Wed, 28 Sep 2022 17:52:12 +0300 Subject: [PATCH 14/82] Check local deletion in test --- osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index 88e4d6e83b..e1ac440168 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -129,6 +129,10 @@ namespace osu.Game.Tests.Visual.Online }); AddStep("Confirm dialog", () => InputManager.Key(Key.Number1)); AddUntilStep("Deletion requested", () => delete); + AddUntilStep("Comment is deleted locally", () => + { + return this.ChildrenOfType().SingleOrDefault(x => x.Comment.Id == 1) == null; + }); } private void addTestComments() From 85adfc2df7d931164181e145377a6ced8db2bfb3 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Wed, 28 Sep 2022 18:26:36 +0300 Subject: [PATCH 15/82] Fix DI type --- .../Visual/Online/TestSceneCommentActions.cs | 71 ++++++++++--------- .../Online/TestSceneCommentsContainer.cs | 2 +- .../Visual/Online/TestSceneDrawableComment.cs | 2 +- .../TestSceneOfflineCommentsContainer.cs | 2 +- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 5 files changed, 41 insertions(+), 38 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index e1ac440168..a58873e457 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Online { private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; - [Cached] + [Cached(typeof(IDialogOverlay))] private readonly DialogOverlay dialogOverlay = new DialogOverlay(); [Cached] @@ -137,49 +137,52 @@ namespace osu.Game.Tests.Visual.Online private void addTestComments() { - CommentBundle cb = new CommentBundle + AddStep("set up response", () => { - Comments = new List + CommentBundle cb = new CommentBundle { - new Comment + Comments = new List { - Id = 1, - Message = "This is our comment", - UserId = API.LocalUser.Value.Id, - CreatedAt = DateTimeOffset.Now, - User = API.LocalUser.Value, - }, - new Comment - { - Id = 2, - Message = "This is a comment by another user", - UserId = API.LocalUser.Value.Id + 1, - CreatedAt = DateTimeOffset.Now, - User = new APIUser + new Comment { - Id = API.LocalUser.Value.Id + 1, - Username = "Another user" - } + Id = 1, + Message = "This is our comment", + UserId = API.LocalUser.Value.Id, + CreatedAt = DateTimeOffset.Now, + User = API.LocalUser.Value, + }, + new Comment + { + Id = 2, + Message = "This is a comment by another user", + UserId = API.LocalUser.Value.Id + 1, + CreatedAt = DateTimeOffset.Now, + User = new APIUser + { + Id = API.LocalUser.Value.Id + 1, + Username = "Another user" + } + }, }, - }, - IncludedComments = new List(), - PinnedComments = new List(), - }; - setUpCommentsResponse(cb); + IncludedComments = new List(), + PinnedComments = new List(), + }; + setUpCommentsResponse(cb); + }); + AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123)); } private void setUpCommentsResponse(CommentBundle commentBundle) - => AddStep("set up response", () => + { + dummyAPI.HandleRequest = request => { - dummyAPI.HandleRequest = request => - { - if (!(request is GetCommentsRequest getCommentsRequest)) - return false; + if (!(request is GetCommentsRequest getCommentsRequest)) + return false; - getCommentsRequest.TriggerSuccess(commentBundle); - return true; - }; - }); + getCommentsRequest.TriggerSuccess(commentBundle); + return true; + }; + } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 08881e9718..d1624b8220 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); - [Cached] + [Cached(typeof(IDialogOverlay))] private readonly DialogOverlay dialogOverlay = new DialogOverlay(); private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index 7253424984..ccbf996c15 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); - [Cached] + [Cached(typeof(IDialogOverlay))] private readonly DialogOverlay dialogOverlay = new DialogOverlay(); private Container container; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index 46bbbd635a..07d491e8e3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); - [Cached] + [Cached(typeof(IDialogOverlay))] private readonly DialogOverlay dialogOverlay = new DialogOverlay(); private TestCommentsContainer comments; diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index f78778b96a..15594b2255 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Comments private DeletedCommentsCounter deletedCommentsCounter; [Resolved] - private DialogOverlay dialogOverlay { get; set; } + private IDialogOverlay dialogOverlay { get; set; } [Resolved] private IAPIProvider api { get; set; } From e98b4b4fbd81273091472ef13dd30f8b8d0e0688 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 3 Oct 2022 23:14:21 +0200 Subject: [PATCH 16/82] Make `updateDisplayModeDropdowns` regular method --- .../Sections/Graphics/LayoutSettings.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 28642f12a1..f3483478ff 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -202,19 +202,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics // initial update bypasses transforms updateScalingModeVisibility(); - void updateDisplayModeDropdowns() - { - if (resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen) - resolutionDropdown.Show(); - else - resolutionDropdown.Hide(); - - if (displayDropdown.Items.Count() > 1) - displayDropdown.Show(); - else - displayDropdown.Hide(); - } - void updateScalingModeVisibility() { if (scalingMode.Value == ScalingMode.Off) @@ -225,6 +212,19 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } + private void updateDisplayModeDropdowns() + { + if (resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen) + resolutionDropdown.Show(); + else + resolutionDropdown.Hide(); + + if (displayDropdown.Items.Count() > 1) + displayDropdown.Show(); + else + displayDropdown.Hide(); + } + private void updateScreenModeWarning() { if (RuntimeInfo.OS == RuntimeInfo.Platform.macOS) From 31fefc1ee2d07bf1b137d9bc3822f84bb6a8495b Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 3 Oct 2022 23:23:02 +0200 Subject: [PATCH 17/82] Add nullable annotation to `LayoutSettings` --- .../Sections/Graphics/LayoutSettings.cs | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index f3483478ff..dbedd01125 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,8 +1,6 @@ // 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 System; using System.Drawing; using System.Linq; @@ -29,31 +27,31 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override LocalisableString Header => GraphicsSettingsStrings.LayoutHeader; - private FillFlowContainer> scalingSettings; + private FillFlowContainer> scalingSettings = null!; private readonly Bindable currentDisplay = new Bindable(); private readonly IBindableList windowModes = new BindableList(); - private Bindable scalingMode; - private Bindable sizeFullscreen; + private Bindable scalingMode = null!; + private Bindable sizeFullscreen = null!; private readonly BindableList resolutions = new BindableList(new[] { new Size(9999, 9999) }); private readonly IBindable fullscreenCapability = new Bindable(FullscreenCapability.Capable); [Resolved] - private OsuGameBase game { get; set; } + private OsuGameBase game { get; set; } = null!; [Resolved] - private GameHost host { get; set; } + private GameHost host { get; set; } = null!; - private SettingsDropdown resolutionDropdown; - private SettingsDropdown displayDropdown; - private SettingsDropdown windowModeDropdown; + private SettingsDropdown resolutionDropdown = null!; + private SettingsDropdown displayDropdown = null!; + private SettingsDropdown windowModeDropdown = null!; - private Bindable scalingPositionX; - private Bindable scalingPositionY; - private Bindable scalingSizeX; - private Bindable scalingSizeY; + private Bindable scalingPositionX = null!; + private Bindable scalingPositionY = null!; + private Bindable scalingSizeX = null!; + private Bindable scalingSizeY = null!; private const int transition_duration = 400; @@ -280,7 +278,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }; } - private Drawable preview; + private Drawable? preview; private void showPreview() { From efc9bed4f062010097e9a8a13deb2b3856c7822b Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 3 Oct 2022 23:52:04 +0200 Subject: [PATCH 18/82] Use `IWindow.DisplaysChanged` to update displays --- .../Sections/Graphics/LayoutSettings.cs | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index dbedd01125..42edd49a47 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Drawing; using System.Linq; using osu.Framework; @@ -44,6 +45,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics [Resolved] private GameHost host { get; set; } = null!; + private IWindow? window; + private SettingsDropdown resolutionDropdown = null!; private SettingsDropdown displayDropdown = null!; private SettingsDropdown windowModeDropdown = null!; @@ -58,6 +61,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics [BackgroundDependencyLoader] private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, GameHost host) { + window = host.Window; + scalingMode = osuConfig.GetBindable(OsuSetting.Scaling); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); scalingSizeX = osuConfig.GetBindable(OsuSetting.ScalingSizeX); @@ -65,10 +70,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingPositionX = osuConfig.GetBindable(OsuSetting.ScalingPositionX); scalingPositionY = osuConfig.GetBindable(OsuSetting.ScalingPositionY); - if (host.Window != null) + if (window != null) { - currentDisplay.BindTo(host.Window.CurrentDisplayBindable); - windowModes.BindTo(host.Window.SupportedWindowModes); + currentDisplay.BindTo(window.CurrentDisplayBindable); + windowModes.BindTo(window.SupportedWindowModes); + window.DisplaysChanged += onDisplaysChanged; } if (host.Window is WindowsWindow windowsWindow) @@ -85,7 +91,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics displayDropdown = new DisplaySettingsDropdown { LabelText = GraphicsSettingsStrings.Display, - Items = host.Window?.Displays, + Items = window?.Displays, Current = currentDisplay, }, resolutionDropdown = new ResolutionSettingsDropdown @@ -210,6 +216,15 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } + private void onDisplaysChanged(IEnumerable displays) + { + Scheduler.AddOnce(d => + { + displayDropdown.Items = d; + updateDisplayModeDropdowns(); + }, displays); + } + private void updateDisplayModeDropdowns() { if (resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen) @@ -289,6 +304,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics preview.Expire(); } + protected override void Dispose(bool isDisposing) + { + if (window != null) + window.DisplaysChanged -= onDisplaysChanged; + + base.Dispose(isDisposing); + } + private class ScalingPreview : ScalingContainer { public ScalingPreview() From abf56c27a10abb47a360ecdfb15f2302bbd64f54 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Sat, 8 Oct 2022 17:11:09 +0300 Subject: [PATCH 19/82] Do not requere dialog overlay --- .../Online/TestSceneCommentsContainer.cs | 14 +-- .../Visual/Online/TestSceneDrawableComment.cs | 5 -- .../TestSceneOfflineCommentsContainer.cs | 4 - osu.Game/Overlays/Comments/DrawableComment.cs | 85 ++++++++++--------- 4 files changed, 50 insertions(+), 58 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index d1624b8220..49e16d9281 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -25,9 +25,6 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); - [Cached(typeof(IDialogOverlay))] - private readonly DialogOverlay dialogOverlay = new DialogOverlay(); - private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; private CommentsContainer commentsContainer; @@ -35,15 +32,10 @@ namespace osu.Game.Tests.Visual.Online [SetUp] public void SetUp() => Schedule(() => { - if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); - Children = new Drawable[] + Child = new BasicScrollContainer { - new BasicScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = commentsContainer = new CommentsContainer() - }, - dialogOverlay + RelativeSizeAxes = Axes.Both, + Child = commentsContainer = new CommentsContainer() }; }); diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index ccbf996c15..cab0ffa3ba 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -20,15 +20,11 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); - [Cached(typeof(IDialogOverlay))] - private readonly DialogOverlay dialogOverlay = new DialogOverlay(); - private Container container; [SetUp] public void SetUp() => Schedule(() => { - if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); Children = new Drawable[] { new Box @@ -41,7 +37,6 @@ namespace osu.Game.Tests.Visual.Online RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }, - dialogOverlay }; }); diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index 07d491e8e3..6cd6b25c14 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -24,22 +24,18 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); - [Cached(typeof(IDialogOverlay))] - private readonly DialogOverlay dialogOverlay = new DialogOverlay(); private TestCommentsContainer comments; [SetUp] public void SetUp() => Schedule(() => { - if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); Clear(); Add(new BasicScrollContainer { RelativeSizeAxes = Axes.Both, Child = comments = new TestCommentsContainer() }); - Add(dialogOverlay); }); [Test] diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 15594b2255..87545ee6a3 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -1,8 +1,6 @@ // 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.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Graphics; @@ -35,7 +33,7 @@ namespace osu.Game.Overlays.Comments { private const int avatar_size = 40; - public Action RepliesRequested; + public Action RepliesRequested = null!; public readonly Comment Comment; @@ -49,21 +47,21 @@ namespace osu.Game.Overlays.Comments private int currentPage; - private FillFlowContainer childCommentsVisibilityContainer; - private FillFlowContainer childCommentsContainer; - private LoadRepliesButton loadRepliesButton; - private ShowMoreRepliesButton showMoreButton; - private ShowRepliesButton showRepliesButton; - private ChevronButton chevronButton; - private LinkFlowContainer actionsContainer; - private LoadingSpinner actionsLoading; - private DeletedCommentsCounter deletedCommentsCounter; + private FillFlowContainer childCommentsVisibilityContainer = null!; + private FillFlowContainer childCommentsContainer = null!; + private LoadRepliesButton loadRepliesButton = null!; + private ShowMoreRepliesButton showMoreButton = null!; + private ShowRepliesButton showRepliesButton = null!; + private ChevronButton chevronButton = null!; + private LinkFlowContainer actionsContainer = null!; + private LoadingSpinner actionsLoading = null!; + private DeletedCommentsCounter deletedCommentsCounter = null!; + + [Resolved(canBeNull: true)] + private IDialogOverlay? dialogOverlay { get; set; } [Resolved] - private IDialogOverlay dialogOverlay { get; set; } - - [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; public DrawableComment(Comment comment) { @@ -278,7 +276,7 @@ namespace osu.Game.Overlays.Comments if (Comment.UserId.HasValue) username.AddUserLink(Comment.User); else - username.AddText(Comment.LegacyName); + username.AddText(Comment.LegacyName!); if (Comment.EditedAt.HasValue && Comment.EditedUser != null) { @@ -354,28 +352,39 @@ namespace osu.Game.Overlays.Comments }; } + /** + * Invokes comment deletion with confirmation. + */ private void deleteComment() { - dialogOverlay.Push(new ConfirmDialog("Do you really want to delete your comment?", () => + if (dialogOverlay == null) + deleteCommentRequest(); + else + dialogOverlay.Push(new ConfirmDialog("Do you really want to delete your comment?", deleteCommentRequest)); + } + + /** + * Invokes comment deletion directly. + */ + private void deleteCommentRequest() + { + actionsContainer.Hide(); + actionsLoading.Show(); + var request = new CommentDeleteRequest(Comment.Id); + request.Success += _ => { - actionsContainer.Hide(); - actionsLoading.Show(); - var request = new CommentDeleteRequest(Comment.Id); - request.Success += _ => - { - actionsLoading.Hide(); - AutoSizeAxes = Axes.None; - Masking = true; - this.ResizeHeightTo(0, 1000, Easing.Out); - this.FadeOut(1000, Easing.Out).Expire(); - }; - request.Failure += _ => - { - actionsLoading.Hide(); - actionsContainer.Show(); - }; - api.Queue(request); - })); + actionsLoading.Hide(); + AutoSizeAxes = Axes.None; + Masking = true; + this.ResizeHeightTo(0, 1000, Easing.Out); + this.FadeOut(1000, Easing.Out).Expire(); + }; + request.Failure += _ => + { + actionsLoading.Hide(); + actionsContainer.Show(); + }; + api.Queue(request); } protected override void LoadComplete() @@ -486,7 +495,7 @@ namespace osu.Game.Overlays.Comments { public LocalisableString TooltipText => getParentMessage(); - private readonly Comment parentComment; + private readonly Comment? parentComment; public ParentUsername(Comment comment) { @@ -506,7 +515,7 @@ namespace osu.Game.Overlays.Comments new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = parentComment?.User?.Username ?? parentComment?.LegacyName + Text = parentComment?.User?.Username ?? parentComment?.LegacyName! } }; } From 4e7c30504f2af736806c4839ea42df0c56e6b965 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Sat, 8 Oct 2022 17:15:10 +0300 Subject: [PATCH 20/82] Schedule action buttons visibility changes --- osu.Game/Overlays/Comments/DrawableComment.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 87545ee6a3..3cb7db0ec2 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -352,9 +352,9 @@ namespace osu.Game.Overlays.Comments }; } - /** - * Invokes comment deletion with confirmation. - */ + /// + /// Invokes comment deletion with confirmation. + /// private void deleteComment() { if (dialogOverlay == null) @@ -363,27 +363,27 @@ namespace osu.Game.Overlays.Comments dialogOverlay.Push(new ConfirmDialog("Do you really want to delete your comment?", deleteCommentRequest)); } - /** - * Invokes comment deletion directly. - */ + /// + /// Invokes comment deletion directly. + /// private void deleteCommentRequest() { actionsContainer.Hide(); actionsLoading.Show(); var request = new CommentDeleteRequest(Comment.Id); - request.Success += _ => + request.Success += _ => Schedule(() => { actionsLoading.Hide(); AutoSizeAxes = Axes.None; Masking = true; this.ResizeHeightTo(0, 1000, Easing.Out); this.FadeOut(1000, Easing.Out).Expire(); - }; - request.Failure += _ => + }); + request.Failure += _ => Schedule(() => { actionsLoading.Hide(); actionsContainer.Show(); - }; + }); api.Queue(request); } From c11258a7e9075a6ca818178365446a3d4024108c Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Sat, 8 Oct 2022 17:20:25 +0300 Subject: [PATCH 21/82] Tidy up test reloading --- .../Visual/Online/TestSceneCommentActions.cs | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index a58873e457..51ae8efba7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -21,6 +22,8 @@ namespace osu.Game.Tests.Visual.Online { public class TestSceneCommentActions : OsuManualInputManagerTestScene { + private Container content = null!; + protected override Container Content => content; private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; [Cached(typeof(IDialogOverlay))] @@ -31,22 +34,26 @@ namespace osu.Game.Tests.Visual.Online private CommentsContainer commentsContainer = null!; + [BackgroundDependencyLoader] + private void load() + { + base.Content.AddRange(new Drawable[] + { + content = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both + }, + dialogOverlay + }); + } + [SetUpSteps] public void SetUp() { Schedule(() => { API.Login("test", "test"); - if (dialogOverlay.Parent != null) Remove(dialogOverlay, false); - Children = new Container[] - { - new BasicScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = commentsContainer = new CommentsContainer() - }, - dialogOverlay - }; + Child = commentsContainer = new CommentsContainer(); }); } From 6e82ffbc6f2d762277ac872376fb0731a9ecc60c Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Sat, 8 Oct 2022 17:41:51 +0300 Subject: [PATCH 22/82] Add check for spinner --- osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index 51ae8efba7..8f9e2f6ba4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -136,6 +137,7 @@ namespace osu.Game.Tests.Visual.Online }); AddStep("Confirm dialog", () => InputManager.Key(Key.Number1)); AddUntilStep("Deletion requested", () => delete); + AddAssert("Loading spinner shown", () => commentsContainer.ChildrenOfType().Any(d => d.IsPresent)); AddUntilStep("Comment is deleted locally", () => { return this.ChildrenOfType().SingleOrDefault(x => x.Comment.Id == 1) == null; From b6972004609d613e4f33e21734ff6a3b4f13a9a1 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Sat, 8 Oct 2022 18:41:08 +0300 Subject: [PATCH 23/82] Properly modify comment visual state on deletion --- osu.Game/Overlays/Comments/DrawableComment.cs | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 3cb7db0ec2..00a832cac8 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -47,6 +47,11 @@ namespace osu.Game.Overlays.Comments private int currentPage; + /// + /// Local field for tracking comment state. Initialized from Comment.IsDeleted, may change when deleting was requested by user. + /// + public bool WasDeleted { get; protected set; } + private FillFlowContainer childCommentsVisibilityContainer = null!; private FillFlowContainer childCommentsContainer = null!; private LoadRepliesButton loadRepliesButton = null!; @@ -56,6 +61,9 @@ namespace osu.Game.Overlays.Comments private LinkFlowContainer actionsContainer = null!; private LoadingSpinner actionsLoading = null!; private DeletedCommentsCounter deletedCommentsCounter = null!; + private OsuSpriteText deletedLabel = null!; + private GridContainer content = null!; + private VotePill votePill = null!; [Resolved(canBeNull: true)] private IDialogOverlay? dialogOverlay { get; set; } @@ -74,8 +82,6 @@ namespace osu.Game.Overlays.Comments LinkFlowContainer username; FillFlowContainer info; CommentMarkdownContainer message; - GridContainer content; - VotePill votePill; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -158,9 +164,9 @@ namespace osu.Game.Overlays.Comments }, Comment.Pinned ? new PinnedCommentNotice() : Empty(), new ParentUsername(Comment), - new OsuSpriteText + deletedLabel = new OsuSpriteText { - Alpha = Comment.IsDeleted ? 1 : 0, + Alpha = 0f, Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Text = CommentsStrings.Deleted } @@ -312,11 +318,9 @@ namespace osu.Game.Overlays.Comments if (Comment.HasMessage) message.Text = Comment.Message; - if (Comment.IsDeleted) - { - content.FadeColour(OsuColour.Gray(0.5f)); - votePill.Hide(); - } + WasDeleted = Comment.IsDeleted; + if (WasDeleted) + makeDeleted(); if (Comment.UserId.HasValue && Comment.UserId.Value == api.LocalUser.Value.Id) { @@ -352,6 +356,17 @@ namespace osu.Game.Overlays.Comments }; } + /// + /// Transforms some comment's components to show it as deleted. Invoked both from loading and deleting. + /// + private void makeDeleted() + { + deletedLabel.Alpha = 1f; + content.FadeColour(OsuColour.Gray(0.5f)); + votePill.Hide(); + actionsContainer.Expire(); + } + /// /// Invokes comment deletion with confirmation. /// @@ -374,10 +389,10 @@ namespace osu.Game.Overlays.Comments request.Success += _ => Schedule(() => { actionsLoading.Hide(); - AutoSizeAxes = Axes.None; - Masking = true; - this.ResizeHeightTo(0, 1000, Easing.Out); - this.FadeOut(1000, Easing.Out).Expire(); + makeDeleted(); + WasDeleted = true; + if (!ShowDeleted.Value) + Hide(); }); request.Failure += _ => Schedule(() => { @@ -391,7 +406,7 @@ namespace osu.Game.Overlays.Comments { ShowDeleted.BindValueChanged(show => { - if (Comment.IsDeleted) + if (WasDeleted) this.FadeTo(show.NewValue ? 1 : 0); }, true); childrenExpanded.BindValueChanged(expanded => childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0), true); From c384093802edbbe0147a66a226125c6b02638a9f Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Sat, 8 Oct 2022 18:53:41 +0300 Subject: [PATCH 24/82] Update main test and add failure scenario test --- .../Visual/Online/TestSceneCommentActions.cs | 52 ++++++++++++++++++- osu.Game/Overlays/Comments/DrawableComment.cs | 1 + 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index 8f9e2f6ba4..11210db8a9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -140,7 +140,57 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Loading spinner shown", () => commentsContainer.ChildrenOfType().Any(d => d.IsPresent)); AddUntilStep("Comment is deleted locally", () => { - return this.ChildrenOfType().SingleOrDefault(x => x.Comment.Id == 1) == null; + return this.ChildrenOfType().Single(x => x.Comment.Id == 1).WasDeleted; + }); + } + + [Test] + public void TestDeletionFail() + { + DrawableComment? ourComment = null; + bool delete = false; + + addTestComments(); + AddUntilStep("Comment exists", () => + { + var comments = this.ChildrenOfType(); + ourComment = comments.SingleOrDefault(x => x.Comment.Id == 1); + return ourComment != null; + }); + AddStep("It has delete button", () => + { + var btn = ourComment.ChildrenOfType().Single(x => x.Text == "Delete"); + InputManager.MoveMouseTo(btn); + }); + AddStep("Click delete button", () => + { + InputManager.Click(MouseButton.Left); + }); + AddStep("Setup request handling", () => + { + dummyAPI.HandleRequest = request => + { + if (request is not CommentDeleteRequest req) + return false; + + req.TriggerFailure(new Exception()); + delete = true; + return false; + }; + }); + AddStep("Confirm dialog", () => InputManager.Key(Key.Number1)); + AddUntilStep("Deletion requested", () => delete); + AddUntilStep("Comment is available", () => + { + return !this.ChildrenOfType().Single(x => x.Comment.Id == 1).WasDeleted; + }); + AddAssert("Loading spinner hidden", () => + { + return ourComment.ChildrenOfType().All(d => !d.IsPresent); + }); + AddAssert("Actions available", () => + { + return ourComment.ChildrenOfType().Single(x => x.Name == @"Actions buttons").IsPresent; }); } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 00a832cac8..105618c728 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -201,6 +201,7 @@ namespace osu.Game.Overlays.Comments }, actionsContainer = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold)) { + Name = @"Actions buttons", AutoSizeAxes = Axes.Both, Spacing = new Vector2(10, 0) }, From e7b1f369a32fe42e5b1ef31d6b448c95cab6c1f1 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Sat, 8 Oct 2022 18:55:58 +0300 Subject: [PATCH 25/82] Revert unwanted changes in other tests --- osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs | 6 ++---- .../Visual/Online/TestSceneOfflineCommentsContainer.cs | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 49e16d9281..a94b9e61c0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -31,13 +31,11 @@ namespace osu.Game.Tests.Visual.Online [SetUp] public void SetUp() => Schedule(() => - { Child = new BasicScrollContainer { RelativeSizeAxes = Axes.Both, Child = commentsContainer = new CommentsContainer() - }; - }); + }); [Test] public void TestIdleState() @@ -141,7 +139,7 @@ namespace osu.Game.Tests.Visual.Online }; }); - private static CommentBundle getExampleComments(bool withPinned = false) + private CommentBundle getExampleComments(bool withPinned = false) { var bundle = new CommentBundle { diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index 6cd6b25c14..07ccfcec88 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -24,7 +24,6 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); - private TestCommentsContainer comments; [SetUp] From ff14453c2ba7e289e518586b2b97092d4355f761 Mon Sep 17 00:00:00 2001 From: pfg Date: Sat, 8 Oct 2022 12:42:29 -0400 Subject: [PATCH 26/82] Preserve collections when saving a beatmap --- osu.Game/Beatmaps/BeatmapManager.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 2c6edb64f8..1c9933387c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -17,6 +17,7 @@ using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps.Formats; +using osu.Game.Collections; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO.Archives; @@ -311,6 +312,8 @@ namespace osu.Game.Beatmaps if (existingFileInfo != null) DeleteFile(setInfo, existingFileInfo); + string? oldMd5Hash = beatmapInfo.MD5Hash; + beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); beatmapInfo.Hash = stream.ComputeSHA2Hash(); @@ -327,6 +330,12 @@ namespace osu.Game.Beatmaps setInfo.CopyChangesToRealm(liveBeatmapSet); + foreach (var collection in r.All()) + { + if (collection.BeatmapMD5Hashes.Remove(oldMd5Hash)) + collection.BeatmapMD5Hashes.Add(beatmapInfo.MD5Hash); + } + ProcessBeatmap?.Invoke((liveBeatmapSet, false)); }); } From edec61372450df63efb434a40b90329c1dfb26f4 Mon Sep 17 00:00:00 2001 From: pfg Date: Sat, 8 Oct 2022 13:58:42 -0400 Subject: [PATCH 27/82] Remove unnecessary '?' --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 1c9933387c..71cafd46c0 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -312,7 +312,7 @@ namespace osu.Game.Beatmaps if (existingFileInfo != null) DeleteFile(setInfo, existingFileInfo); - string? oldMd5Hash = beatmapInfo.MD5Hash; + string oldMd5Hash = beatmapInfo.MD5Hash; beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); beatmapInfo.Hash = stream.ComputeSHA2Hash(); From f219c0886d5875ba1e4632704f8f85741222b079 Mon Sep 17 00:00:00 2001 From: pfg Date: Sun, 9 Oct 2022 10:19:21 -0400 Subject: [PATCH 28/82] Add a test for realm preservation --- .../Beatmaps/WorkingBeatmapManagerTest.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs b/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs index f14288e7ba..8e8d45937a 100644 --- a/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs +++ b/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs @@ -9,8 +9,10 @@ using osu.Framework.Extensions; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Collections; using osu.Game.Database; using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Tests.Resources; using osu.Game.Tests.Visual; @@ -96,5 +98,39 @@ namespace osu.Game.Tests.Beatmaps var second = beatmaps.GetWorkingBeatmap(beatmap, true); Assert.That(first, Is.Not.SameAs(second)); }); + + [Test] + public void TestSavePreservesCollections() => AddStep("run test", () => + { + var beatmap = Realm.Run(r => r.Find(importedSet.Beatmaps.First().ID).Detach()); + + var map = beatmaps.GetWorkingBeatmap(beatmap); + + Assert.That(map.BeatmapInfo.BeatmapSet?.Files, Has.Count.GreaterThan(0)); + + string initialHash = map.BeatmapInfo.MD5Hash; + + var preserveCollection = new BeatmapCollection("test save preserves collection"); + preserveCollection.BeatmapMD5Hashes.Add(initialHash); + var noNewCollection = new BeatmapCollection("test save does not introduce new collection"); + Realm.Write(r => + { + r.Add(preserveCollection); + r.Add(noNewCollection); + }); + + Assert.That(preserveCollection.BeatmapMD5Hashes, Does.Contain(initialHash)); + Assert.That(noNewCollection.BeatmapMD5Hashes, Does.Not.Contain(initialHash)); + + beatmaps.Save(map.BeatmapInfo, map.GetPlayableBeatmap(new OsuRuleset().RulesetInfo)); + + string finalHash = map.BeatmapInfo.MD5Hash; + + Assert.That(finalHash, Is.Not.SameAs(initialHash)); + + Assert.That(preserveCollection.BeatmapMD5Hashes, Does.Not.Contain(initialHash)); + Assert.That(preserveCollection.BeatmapMD5Hashes, Does.Contain(finalHash)); + Assert.That(noNewCollection.BeatmapMD5Hashes, Does.Not.Contain(finalHash)); + }); } } From 7726dda97568e71e13cf3c9068e3e50c2bbe3696 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Oct 2022 15:31:45 +0900 Subject: [PATCH 29/82] Remove whitespace --- osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs b/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs index 8e8d45937a..006326fd3c 100644 --- a/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs +++ b/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs @@ -121,7 +121,7 @@ namespace osu.Game.Tests.Beatmaps Assert.That(preserveCollection.BeatmapMD5Hashes, Does.Contain(initialHash)); Assert.That(noNewCollection.BeatmapMD5Hashes, Does.Not.Contain(initialHash)); - + beatmaps.Save(map.BeatmapInfo, map.GetPlayableBeatmap(new OsuRuleset().RulesetInfo)); string finalHash = map.BeatmapInfo.MD5Hash; From e3b405cc23e51de735d49110358f3e739c677321 Mon Sep 17 00:00:00 2001 From: NotGumballer91 <64581009+NotGumballer91@users.noreply.github.com> Date: Mon, 10 Oct 2022 21:02:23 +0800 Subject: [PATCH 30/82] Update IWorkingBeatmap.cs --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index a39766abe1..cf72a611e5 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -134,6 +134,6 @@ namespace osu.Game.Beatmaps /// /// Reads the correct track restart point from beatmap metadata and sets looping to enabled. /// - void PrepareTrackForPreview(bool looping); + void PrepareTrackForPreview(bool looping, int priorToPreview = 0); } } From 749dc400627d45d8c6a8f101f8c573e6e961b0fd Mon Sep 17 00:00:00 2001 From: NotGumballer91 <64581009+NotGumballer91@users.noreply.github.com> Date: Mon, 10 Oct 2022 21:03:11 +0800 Subject: [PATCH 31/82] Update WorkingBeatmap.cs --- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 0a51c843cd..8bd0f4b14b 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -110,10 +110,10 @@ namespace osu.Game.Beatmaps public Track LoadTrack() => track = GetBeatmapTrack() ?? GetVirtualTrack(1000); - public void PrepareTrackForPreview(bool looping) + public void PrepareTrackForPreview(bool looping, int priorToPreview = 2000) { Track.Looping = looping; - Track.RestartPoint = Metadata.PreviewTime; + Track.RestartPoint = Metadata.PreviewTime - priorToPreview; if (Track.RestartPoint == -1) { From 9a3689b6e96acdef198a57c981b12b1267039934 Mon Sep 17 00:00:00 2001 From: NotGumballer91 <64581009+NotGumballer91@users.noreply.github.com> Date: Mon, 10 Oct 2022 21:04:14 +0800 Subject: [PATCH 32/82] Update IntroCircles.cs --- osu.Game/Screens/Menu/IntroCircles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index 7a4bdb231f..a69f2c8a65 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Menu protected override string BeatmapFile => "circles.osz"; - public const double TRACK_START_DELAY = 600; + public const double TRACK_START_DELAY = 1200; private const double delay_for_menu = 2900; From 3cd6ce8e3f2ef06f94e9a2711cb7e04cff816f48 Mon Sep 17 00:00:00 2001 From: NotGumballer91 <64581009+NotGumballer91@users.noreply.github.com> Date: Tue, 11 Oct 2022 01:48:55 +0800 Subject: [PATCH 33/82] Update WorkingBeatmap.cs --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 8bd0f4b14b..7eb7852897 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -110,7 +110,7 @@ namespace osu.Game.Beatmaps public Track LoadTrack() => track = GetBeatmapTrack() ?? GetVirtualTrack(1000); - public void PrepareTrackForPreview(bool looping, int priorToPreview = 2000) + public void PrepareTrackForPreview(bool looping, int priorToPreview = 0) { Track.Looping = looping; Track.RestartPoint = Metadata.PreviewTime - priorToPreview; From 8a4f2efa141c47a54dcfb12ae4047d508e7659f4 Mon Sep 17 00:00:00 2001 From: NotGumballer91 <64581009+NotGumballer91@users.noreply.github.com> Date: Tue, 11 Oct 2022 01:49:49 +0800 Subject: [PATCH 34/82] Update IntroScreen.cs --- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 409c7d6c8d..42a993ff63 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -278,7 +278,7 @@ namespace osu.Game.Screens.Menu if (!UsingThemedIntro) { - initialBeatmap?.PrepareTrackForPreview(false); + initialBeatmap?.PrepareTrackForPreview(false, 2200); drawableTrack.VolumeTo(0); drawableTrack.Restart(); From ef840e98cf5c75b56d051c489a3179ebbf34c3c2 Mon Sep 17 00:00:00 2001 From: NotGumballer91 <64581009+NotGumballer91@users.noreply.github.com> Date: Tue, 11 Oct 2022 01:49:53 +0800 Subject: [PATCH 35/82] Update IntroCircles.cs --- osu.Game/Screens/Menu/IntroCircles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index a69f2c8a65..97654a81df 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Menu protected override string BeatmapFile => "circles.osz"; - public const double TRACK_START_DELAY = 1200; + public const double TRACK_START_DELAY = 1000; private const double delay_for_menu = 2900; From de8d4853055c31d43e435a6093a9af00a6c72b24 Mon Sep 17 00:00:00 2001 From: pfg Date: Mon, 10 Oct 2022 21:45:33 -0400 Subject: [PATCH 36/82] Move 'transferCollections' to a shared location --- osu.Game/Beatmaps/BeatmapImporter.cs | 8 +------- osu.Game/Beatmaps/BeatmapInfo.cs | 12 ++++++++++++ osu.Game/Beatmaps/BeatmapManager.cs | 6 +----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 292caa4397..c4378cda5c 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -146,13 +146,7 @@ namespace osu.Game.Beatmaps if (updatedBeatmap == null) continue; - var collections = realm.All().AsEnumerable().Where(c => c.BeatmapMD5Hashes.Contains(originalBeatmap.MD5Hash)); - - foreach (var c in collections) - { - c.BeatmapMD5Hashes.Remove(originalBeatmap.MD5Hash); - c.BeatmapMD5Hashes.Add(updatedBeatmap.MD5Hash); - } + updatedBeatmap.transferCollectionsFrom(realm, originalBeatmap.MD5Hash); } } diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 32b7f0b29b..61431764f0 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -8,6 +8,7 @@ using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.Testing; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Collections; using osu.Game.Database; using osu.Game.Models; using osu.Game.Online.API.Requests.Responses; @@ -213,6 +214,17 @@ namespace osu.Game.Beatmaps return fileHashX == fileHashY; } + public void transferCollectionsFrom(Realm realm, string oldMd5Hash) + { + var collections = realm.All().AsEnumerable().Where(c => c.BeatmapMD5Hashes.Contains(oldMd5Hash)); + + foreach (var c in collections) + { + c.BeatmapMD5Hashes.Remove(oldMd5Hash); + c.BeatmapMD5Hashes.Add(MD5Hash); + } + } + IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata; IBeatmapSetInfo? IBeatmapInfo.BeatmapSet => BeatmapSet; IRulesetInfo IBeatmapInfo.Ruleset => Ruleset; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 71cafd46c0..7db5480128 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -330,11 +330,7 @@ namespace osu.Game.Beatmaps setInfo.CopyChangesToRealm(liveBeatmapSet); - foreach (var collection in r.All()) - { - if (collection.BeatmapMD5Hashes.Remove(oldMd5Hash)) - collection.BeatmapMD5Hashes.Add(beatmapInfo.MD5Hash); - } + beatmapInfo.transferCollectionsFrom(r, oldMd5Hash); ProcessBeatmap?.Invoke((liveBeatmapSet, false)); }); From e619c9c1e6eb1c60302158b21ad0d5b7ff5328af Mon Sep 17 00:00:00 2001 From: pfg Date: Mon, 10 Oct 2022 21:48:41 -0400 Subject: [PATCH 37/82] fix style --- osu.Game/Beatmaps/BeatmapImporter.cs | 2 +- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index c4378cda5c..4f09a73440 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -146,7 +146,7 @@ namespace osu.Game.Beatmaps if (updatedBeatmap == null) continue; - updatedBeatmap.transferCollectionsFrom(realm, originalBeatmap.MD5Hash); + updatedBeatmap.TransferCollectionsFrom(realm, originalBeatmap.MD5Hash); } } diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 61431764f0..42461e863c 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -214,7 +214,7 @@ namespace osu.Game.Beatmaps return fileHashX == fileHashY; } - public void transferCollectionsFrom(Realm realm, string oldMd5Hash) + public void TransferCollectionsFrom(Realm realm, string oldMd5Hash) { var collections = realm.All().AsEnumerable().Where(c => c.BeatmapMD5Hashes.Contains(oldMd5Hash)); diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7db5480128..9224806301 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -330,7 +330,7 @@ namespace osu.Game.Beatmaps setInfo.CopyChangesToRealm(liveBeatmapSet); - beatmapInfo.transferCollectionsFrom(r, oldMd5Hash); + beatmapInfo.TransferCollectionsFrom(r, oldMd5Hash); ProcessBeatmap?.Invoke((liveBeatmapSet, false)); }); From 1a24762f9b75582c0dd0bee7368835c9e04f0730 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 11 Oct 2022 14:11:45 +0900 Subject: [PATCH 38/82] Improve drag box selection logic `AllowDeselectionDuringDrag` is remove. Instead, selected hit objects are not automatically deselected when clock is seeked to a later time (the hit object is dead). Update drag box selection even if mouse is not moved (in case clock is running or scroll wheel is used). --- .../Compose/Components/BlueprintContainer.cs | 23 +++++++++++-------- .../Components/ComposeBlueprintContainer.cs | 20 ++++++++++++++-- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 8aecc75824..b15cecd506 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osuTK; using osuTK.Input; @@ -106,11 +107,6 @@ namespace osu.Game.Screens.Edit.Compose.Components protected virtual DragBox CreateDragBox() => new DragBox(); - /// - /// Whether this component is in a state where items outside a drag selection should be deselected. If false, selection will only be added to. - /// - protected virtual bool AllowDeselectionDuringDrag => true; - protected override bool OnMouseDown(MouseDownEvent e) { bool selectionPerformed = performMouseDownActions(e); @@ -389,12 +385,19 @@ namespace osu.Game.Screens.Edit.Compose.Components foreach (var blueprint in SelectionBlueprints) { - if (blueprint.IsSelected && !AllowDeselectionDuringDrag) - continue; + switch (blueprint.State) + { + case SelectionState.Selected: + // Selection is preserved even after blueprint becomes dead. + if (!quad.Contains(blueprint.ScreenSpaceSelectionPoint)) + blueprint.Deselect(); + break; - bool shouldBeSelected = blueprint.IsAlive && blueprint.IsPresent && quad.Contains(blueprint.ScreenSpaceSelectionPoint); - if (blueprint.IsSelected != shouldBeSelected) - blueprint.ToggleSelection(); + case SelectionState.NotSelected: + if (blueprint.IsAlive && blueprint.IsPresent && quad.Contains(blueprint.ScreenSpaceSelectionPoint)) + blueprint.Select(); + break; + } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 43ead88d54..c8870d46a8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -39,6 +39,8 @@ namespace osu.Game.Screens.Edit.Compose.Components private PlacementBlueprint currentPlacement; private InputManager inputManager; + private DragEvent lastDragEvent; + /// /// Positional input must be received outside the container's bounds, /// in order to handle composer blueprints which are partially offscreen. @@ -83,8 +85,6 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - protected override bool AllowDeselectionDuringDrag => !EditorClock.IsRunning; - protected override void TransferBlueprintFor(HitObject hitObject, DrawableHitObject drawableObject) { base.TransferBlueprintFor(hitObject, drawableObject); @@ -120,6 +120,18 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; } + protected override void OnDrag(DragEvent e) + { + base.OnDrag(e); + lastDragEvent = e; + } + + protected override void OnDragEnd(DragEndEvent e) + { + base.OnDragEnd(e); + lastDragEvent = null; + } + /// /// Move the current selection spatially by the specified delta, in gamefield coordinates (ie. the same coordinates as the blueprints). /// @@ -236,6 +248,10 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.Update(); + // trigger every frame so drags continue to update selection while seeking time. + if (lastDragEvent != null) + OnDrag(lastDragEvent); + if (currentPlacement != null) { switch (currentPlacement.PlacementActive) From 6ab29a62d04b66130928cdb463b7b48424025fb5 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 11 Oct 2022 14:23:17 +0900 Subject: [PATCH 39/82] Anchor drag box on time (catch, mania) Not done for taiko because I cannot figure out how it should work with the overlapping scroll algorithm. --- .../Edit/CatchBlueprintContainer.cs | 3 + .../Edit/ManiaBlueprintContainer.cs | 3 + .../Compose/Components/ScrollingDragBox.cs | 63 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs b/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs index 58f493b4b8..20d432d62e 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs @@ -5,6 +5,7 @@ using osu.Game.Rulesets.Catch.Edit.Blueprints; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -36,5 +37,7 @@ namespace osu.Game.Rulesets.Catch.Edit return base.CreateHitObjectBlueprintFor(hitObject); } + + protected sealed override DragBox CreateDragBox() => new ScrollingDragBox((CatchPlayfield)Composer.Playfield); } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs index ad75afff8e..c3fad1e22b 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -33,5 +34,7 @@ namespace osu.Game.Rulesets.Mania.Edit } protected override SelectionHandler CreateSelectionHandler() => new ManiaSelectionHandler(); + + protected sealed override DragBox CreateDragBox() => new ScrollingDragBox((ManiaPlayfield)Composer.Playfield); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs b/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs new file mode 100644 index 0000000000..2d2c88247b --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs @@ -0,0 +1,63 @@ +// 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.Input.Events; +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Screens.Edit.Compose.Components +{ + /// + /// A that scrolls along with the scrolling playfield. + /// + public class ScrollingDragBox : DragBox + { + public double MinTime { get; private set; } + + public double MaxTime { get; private set; } + + private double? startTime; + + private readonly ScrollingPlayfield playfield; + + public ScrollingDragBox(ScrollingPlayfield playfield) + { + this.playfield = playfield; + } + + public override void HandleDrag(MouseButtonEvent e) + { + base.HandleDrag(e); + + startTime ??= playfield.TimeAtScreenSpacePosition(e.ScreenSpaceMouseDownPosition); + double endTime = playfield.TimeAtScreenSpacePosition(e.ScreenSpaceMousePosition); + + MinTime = Math.Min(startTime.Value, endTime); + MaxTime = Math.Max(startTime.Value, endTime); + + var startPos = ToLocalSpace(playfield.ScreenSpacePositionAtTime(startTime.Value)); + var endPos = ToLocalSpace(playfield.ScreenSpacePositionAtTime(endTime)); + + switch (playfield.ScrollingInfo.Direction.Value) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + Box.Y = Math.Min(startPos.Y, endPos.Y); + Box.Height = Math.Max(startPos.Y, endPos.Y) - Box.Y; + break; + + case ScrollingDirection.Left: + case ScrollingDirection.Right: + Box.X = Math.Min(startPos.X, endPos.X); + Box.Width = Math.Max(startPos.X, endPos.X) - Box.X; + break; + } + } + + public override void Hide() + { + base.Hide(); + startTime = null; + } + } +} From eba3d37a1197e0a4accfac3d69c1330d316f351c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Oct 2022 15:50:02 +0900 Subject: [PATCH 40/82] Add xmldoc and simplify calling --- osu.Game/Beatmaps/BeatmapImporter.cs | 9 +++------ osu.Game/Beatmaps/BeatmapInfo.cs | 12 +++++++++--- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 4f09a73440..bcb1d7f961 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -141,12 +141,9 @@ namespace osu.Game.Beatmaps // Handle collections using permissive difficulty name to track difficulties. foreach (var originalBeatmap in original.Beatmaps) { - var updatedBeatmap = updated.Beatmaps.FirstOrDefault(b => b.DifficultyName == originalBeatmap.DifficultyName); - - if (updatedBeatmap == null) - continue; - - updatedBeatmap.TransferCollectionsFrom(realm, originalBeatmap.MD5Hash); + updated.Beatmaps + .FirstOrDefault(b => b.DifficultyName == originalBeatmap.DifficultyName)? + .TransferCollectionReferences(realm, originalBeatmap.MD5Hash); } } diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 42461e863c..6f9df1ba7f 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -214,13 +214,19 @@ namespace osu.Game.Beatmaps return fileHashX == fileHashY; } - public void TransferCollectionsFrom(Realm realm, string oldMd5Hash) + /// + /// When updating a beatmap, its hashes will change. Collections currently track beatmaps by hash, so they need to be updated. + /// This method will handle updating + /// + /// A realm instance in an active write transaction. + /// The previous MD5 hash of the beatmap before update. + public void TransferCollectionReferences(Realm realm, string previousMD5Hash) { - var collections = realm.All().AsEnumerable().Where(c => c.BeatmapMD5Hashes.Contains(oldMd5Hash)); + var collections = realm.All().AsEnumerable().Where(c => c.BeatmapMD5Hashes.Contains(previousMD5Hash)); foreach (var c in collections) { - c.BeatmapMD5Hashes.Remove(oldMd5Hash); + c.BeatmapMD5Hashes.Remove(previousMD5Hash); c.BeatmapMD5Hashes.Add(MD5Hash); } } diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 9224806301..8ea22e5d67 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -330,7 +330,7 @@ namespace osu.Game.Beatmaps setInfo.CopyChangesToRealm(liveBeatmapSet); - beatmapInfo.TransferCollectionsFrom(r, oldMd5Hash); + beatmapInfo.TransferCollectionReferences(r, oldMd5Hash); ProcessBeatmap?.Invoke((liveBeatmapSet, false)); }); From ece42de408544565821121591a953813a6fba5aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Oct 2022 15:53:48 +0900 Subject: [PATCH 41/82] Fix variable naming in test --- .../Beatmaps/WorkingBeatmapManagerTest.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs b/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs index 006326fd3c..4ef466efbf 100644 --- a/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs +++ b/osu.Game.Tests/Beatmaps/WorkingBeatmapManagerTest.cs @@ -104,15 +104,17 @@ namespace osu.Game.Tests.Beatmaps { var beatmap = Realm.Run(r => r.Find(importedSet.Beatmaps.First().ID).Detach()); - var map = beatmaps.GetWorkingBeatmap(beatmap); + var working = beatmaps.GetWorkingBeatmap(beatmap); - Assert.That(map.BeatmapInfo.BeatmapSet?.Files, Has.Count.GreaterThan(0)); + Assert.That(working.BeatmapInfo.BeatmapSet?.Files, Has.Count.GreaterThan(0)); - string initialHash = map.BeatmapInfo.MD5Hash; + string initialHash = working.BeatmapInfo.MD5Hash; - var preserveCollection = new BeatmapCollection("test save preserves collection"); + var preserveCollection = new BeatmapCollection("test contained"); preserveCollection.BeatmapMD5Hashes.Add(initialHash); - var noNewCollection = new BeatmapCollection("test save does not introduce new collection"); + + var noNewCollection = new BeatmapCollection("test not contained"); + Realm.Write(r => { r.Add(preserveCollection); @@ -122,9 +124,9 @@ namespace osu.Game.Tests.Beatmaps Assert.That(preserveCollection.BeatmapMD5Hashes, Does.Contain(initialHash)); Assert.That(noNewCollection.BeatmapMD5Hashes, Does.Not.Contain(initialHash)); - beatmaps.Save(map.BeatmapInfo, map.GetPlayableBeatmap(new OsuRuleset().RulesetInfo)); + beatmaps.Save(working.BeatmapInfo, working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo)); - string finalHash = map.BeatmapInfo.MD5Hash; + string finalHash = working.BeatmapInfo.MD5Hash; Assert.That(finalHash, Is.Not.SameAs(initialHash)); From 9bab02fab4a4fc9df3c6037394f2a8fba5f1edf3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Oct 2022 16:23:05 +0900 Subject: [PATCH 42/82] Remove unused using statement --- osu.Game/Beatmaps/BeatmapManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 8ea22e5d67..befc56d244 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -17,7 +17,6 @@ using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps.Formats; -using osu.Game.Collections; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO.Archives; From f41b79688f184ab9182ef4ffde6e7ce8bd797bfc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Oct 2022 16:54:41 +0900 Subject: [PATCH 43/82] Avoid casting by accepting all `Playfield`s but throwing on a bad choice --- osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs | 3 +-- osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs | 3 +-- osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs | 5 +++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs b/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs index 20d432d62e..a0a11424d0 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs @@ -5,7 +5,6 @@ using osu.Game.Rulesets.Catch.Edit.Blueprints; using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -38,6 +37,6 @@ namespace osu.Game.Rulesets.Catch.Edit return base.CreateHitObjectBlueprintFor(hitObject); } - protected sealed override DragBox CreateDragBox() => new ScrollingDragBox((CatchPlayfield)Composer.Playfield); + protected sealed override DragBox CreateDragBox() => new ScrollingDragBox(Composer.Playfield); } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs index c3fad1e22b..f438d6497c 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -35,6 +34,6 @@ namespace osu.Game.Rulesets.Mania.Edit protected override SelectionHandler CreateSelectionHandler() => new ManiaSelectionHandler(); - protected sealed override DragBox CreateDragBox() => new ScrollingDragBox((ManiaPlayfield)Composer.Playfield); + protected sealed override DragBox CreateDragBox() => new ScrollingDragBox(Composer.Playfield); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs b/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs index 2d2c88247b..58bfaf56ff 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ScrollingDragBox.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Input.Events; +using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Screens.Edit.Compose.Components @@ -20,9 +21,9 @@ namespace osu.Game.Screens.Edit.Compose.Components private readonly ScrollingPlayfield playfield; - public ScrollingDragBox(ScrollingPlayfield playfield) + public ScrollingDragBox(Playfield playfield) { - this.playfield = playfield; + this.playfield = playfield as ScrollingPlayfield ?? throw new ArgumentException("Playfield must be of type {nameof(ScrollingPlayfield)} to use this class.", nameof(playfield)); } public override void HandleDrag(MouseButtonEvent e) From 5baad52a9ef8ab064633bc4a76f3eced160a246c Mon Sep 17 00:00:00 2001 From: NotGumballer91 <64581009+NotGumballer91@users.noreply.github.com> Date: Tue, 11 Oct 2022 16:15:56 +0800 Subject: [PATCH 44/82] Fix unintended delay on osu!theme --- osu.Game/Screens/Menu/IntroCircles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index 97654a81df..7a4bdb231f 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Menu protected override string BeatmapFile => "circles.osz"; - public const double TRACK_START_DELAY = 1000; + public const double TRACK_START_DELAY = 600; private const double delay_for_menu = 2900; From d18466d7406244f1f76f4c83f5a417c869eb26ce Mon Sep 17 00:00:00 2001 From: NotGumballer91 <64581009+NotGumballer91@users.noreply.github.com> Date: Tue, 11 Oct 2022 16:16:57 +0800 Subject: [PATCH 45/82] Fix delay inconsistency in IntroCircles.cs --- osu.Game/Screens/Menu/IntroScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 42a993ff63..435c02de96 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -278,11 +278,11 @@ namespace osu.Game.Screens.Menu if (!UsingThemedIntro) { - initialBeatmap?.PrepareTrackForPreview(false, 2200); + initialBeatmap?.PrepareTrackForPreview(false, 2600); drawableTrack.VolumeTo(0); drawableTrack.Restart(); - drawableTrack.VolumeTo(1, 2200, Easing.InCubic); + drawableTrack.VolumeTo(1, 2600, Easing.InCubic); } else { From 390ff8b9da93841a0dc78577f50959158d9a5bed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Oct 2022 17:33:44 +0900 Subject: [PATCH 46/82] Reduce the scope of realm transactions during import operations --- .../Database/RealmArchiveModelImporter.cs | 45 ++++++++++++------- osu.Game/Database/RealmFileStore.cs | 6 +-- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/osu.Game/Database/RealmArchiveModelImporter.cs b/osu.Game/Database/RealmArchiveModelImporter.cs index f1bc0bfe0e..0286815569 100644 --- a/osu.Game/Database/RealmArchiveModelImporter.cs +++ b/osu.Game/Database/RealmArchiveModelImporter.cs @@ -294,15 +294,38 @@ namespace osu.Game.Database // Log output here will be missing a valid hash in non-batch imports. LogForModel(item, $@"Beginning import from {archive?.Name ?? "unknown"}..."); + List files = new List(); + + if (archive != null) + { + // Import files to the disk store. + // We intentionally delay adding to realm to avoid blocking on a write during disk operations. + foreach (var filenames in getShortenedFilenames(archive)) + { + using (Stream s = archive.GetStream(filenames.original)) + files.Add(new RealmNamedFileUsage(Files.Add(s, realm, false), filenames.shortened)); + } + } + + using (var transaction = realm.BeginWrite()) + { + // Add all files to realm in one go. + // This is done ahead of the main transaction to ensure we can correctly cleanup the files, even if the import fails. + foreach (var file in files) + { + if (!file.File.IsManaged) + realm.Add(file.File, true); + } + + transaction.Commit(); + } + + item.Files.AddRange(files); + item.Hash = ComputeHash(item); + // TODO: do we want to make the transaction this local? not 100% sure, will need further investigation. using (var transaction = realm.BeginWrite()) { - if (archive != null) - // TODO: look into rollback of file additions (or delayed commit). - item.Files.AddRange(createFileInfos(archive, Files, realm)); - - item.Hash = ComputeHash(item); - // TODO: we may want to run this outside of the transaction. Populate(item, archive, realm, cancellationToken); @@ -425,16 +448,6 @@ namespace osu.Game.Database { var fileInfos = new List(); - // import files to manager - foreach (var filenames in getShortenedFilenames(reader)) - { - using (Stream s = reader.GetStream(filenames.original)) - { - var item = new RealmNamedFileUsage(files.Add(s, realm), filenames.shortened); - fileInfos.Add(item); - } - } - return fileInfos; } diff --git a/osu.Game/Database/RealmFileStore.cs b/osu.Game/Database/RealmFileStore.cs index ecb152c45c..036b15ea17 100644 --- a/osu.Game/Database/RealmFileStore.cs +++ b/osu.Game/Database/RealmFileStore.cs @@ -40,8 +40,8 @@ namespace osu.Game.Database /// /// The file data stream. /// The realm instance to add to. Should already be in a transaction. - /// - public RealmFile Add(Stream data, Realm realm) + /// Whether the should immediately be added to the underlying realm. If false is provided here, the instance must be manually added. + public RealmFile Add(Stream data, Realm realm, bool addToRealm = true) { string hash = data.ComputeSHA2Hash(); @@ -52,7 +52,7 @@ namespace osu.Game.Database if (!checkFileExistsAndMatchesHash(file)) copyToStore(file, data); - if (!file.IsManaged) + if (addToRealm && !file.IsManaged) realm.Add(file); return file; From fcb9e2cc00894cf686a9fb73cbe27fd8af6dc766 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 11 Oct 2022 22:39:53 +0900 Subject: [PATCH 47/82] Refactor blueprint container drag code --- .../Compose/Components/BlueprintContainer.cs | 28 +++++++---- .../Components/ComposeBlueprintContainer.cs | 24 +--------- .../Components/EditorBlueprintContainer.cs | 5 ++ .../Timeline/TimelineBlueprintContainer.cs | 47 ++++++------------- 4 files changed, 38 insertions(+), 66 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index b15cecd506..43ad270c16 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -170,11 +170,15 @@ namespace osu.Game.Screens.Edit.Compose.Components finishSelectionMovement(); } + private MouseButtonEvent lastDragEvent; + protected override bool OnDragStart(DragStartEvent e) { if (e.Button == MouseButton.Right) return false; + lastDragEvent = e; + if (movementBlueprints != null) { isDraggingBlueprint = true; @@ -189,22 +193,14 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void OnDrag(DragEvent e) { - if (e.Button == MouseButton.Right) - return; - - if (DragBox.State == Visibility.Visible) - { - DragBox.HandleDrag(e); - UpdateSelectionFromDragBox(); - } + lastDragEvent = e; moveCurrentSelection(e); } protected override void OnDragEnd(DragEndEvent e) { - if (e.Button == MouseButton.Right) - return; + lastDragEvent = null; if (isDraggingBlueprint) { @@ -215,6 +211,18 @@ namespace osu.Game.Screens.Edit.Compose.Components DragBox.Hide(); } + protected override void Update() + { + base.Update(); + + if (lastDragEvent != null && DragBox.State == Visibility.Visible) + { + lastDragEvent.Target = this; + DragBox.HandleDrag(lastDragEvent); + UpdateSelectionFromDragBox(); + } + } + /// /// Called whenever a drag operation completes, before any change transaction is committed. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index c8870d46a8..ec07da43a0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -12,7 +12,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Audio; using osu.Game.Graphics.UserInterface; @@ -37,9 +36,6 @@ namespace osu.Game.Screens.Edit.Compose.Components protected new EditorSelectionHandler SelectionHandler => (EditorSelectionHandler)base.SelectionHandler; private PlacementBlueprint currentPlacement; - private InputManager inputManager; - - private DragEvent lastDragEvent; /// /// Positional input must be received outside the container's bounds, @@ -68,8 +64,6 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.LoadComplete(); - inputManager = GetContainingInputManager(); - Beatmap.HitObjectAdded += hitObjectAdded; // updates to selected are handled for us by SelectionHandler. @@ -120,18 +114,6 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; } - protected override void OnDrag(DragEvent e) - { - base.OnDrag(e); - lastDragEvent = e; - } - - protected override void OnDragEnd(DragEndEvent e) - { - base.OnDragEnd(e); - lastDragEvent = null; - } - /// /// Move the current selection spatially by the specified delta, in gamefield coordinates (ie. the same coordinates as the blueprints). /// @@ -234,7 +216,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updatePlacementPosition() { - var snapResult = Composer.FindSnappedPositionAndTime(inputManager.CurrentState.Mouse.Position); + var snapResult = Composer.FindSnappedPositionAndTime(InputManager.CurrentState.Mouse.Position); // if no time was found from positional snapping, we should still quantize to the beat. snapResult.Time ??= Beatmap.SnapTime(EditorClock.CurrentTime, null); @@ -248,10 +230,6 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.Update(); - // trigger every frame so drags continue to update selection while seeking time. - if (lastDragEvent != null) - OnDrag(lastDragEvent); - if (currentPlacement != null) { switch (currentPlacement.PlacementActive) diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs index 6adaeb1a83..7423b368b4 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs @@ -8,6 +8,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; @@ -27,6 +28,8 @@ namespace osu.Game.Screens.Edit.Compose.Components private HitObjectUsageEventBuffer usageEventBuffer; + protected InputManager InputManager { get; private set; } + protected EditorBlueprintContainer(HitObjectComposer composer) { Composer = composer; @@ -42,6 +45,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.LoadComplete(); + InputManager = GetContainingInputManager(); + Beatmap.HitObjectAdded += AddBlueprintFor; Beatmap.HitObjectRemoved += RemoveBlueprintFor; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index 31990bfd35..b79c2675c8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -29,10 +29,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [Resolved(CanBeNull = true)] private Timeline timeline { get; set; } - private DragEvent lastDragEvent; private Bindable placement; private SelectionBlueprint placementBlueprint; + private bool hitObjectDragged; + /// /// Positional input must be received outside the container's bounds, /// in order to handle timeline blueprints which are stacked offscreen. @@ -98,24 +99,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline return base.OnDragStart(e); } - protected override void OnDrag(DragEvent e) - { - handleScrollViaDrag(e); - - base.OnDrag(e); - } - - protected override void OnDragEnd(DragEndEvent e) - { - base.OnDragEnd(e); - lastDragEvent = null; - } - protected override void Update() { - // trigger every frame so drags continue to update selection while playback is scrolling the timeline. - if (lastDragEvent != null) - OnDrag(lastDragEvent); + if (IsDragged || hitObjectDragged) + handleScrollViaDrag(); if (Composer != null && timeline != null) { @@ -170,7 +157,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { return new TimelineHitObjectBlueprint(item) { - OnDragHandled = handleScrollViaDrag, + OnDragHandled = e => hitObjectDragged = e != null, }; } @@ -197,24 +184,18 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } - private void handleScrollViaDrag(DragEvent e) + private void handleScrollViaDrag() { - lastDragEvent = e; + if (timeline == null) return; - if (lastDragEvent == null) - return; + var timelineQuad = timeline.ScreenSpaceDrawQuad; + float mouseX = InputManager.CurrentState.Mouse.Position.X; - if (timeline != null) - { - var timelineQuad = timeline.ScreenSpaceDrawQuad; - float mouseX = e.ScreenSpaceMousePosition.X; - - // scroll if in a drag and dragging outside visible extents - if (mouseX > timelineQuad.TopRight.X) - timeline.ScrollBy((float)((mouseX - timelineQuad.TopRight.X) / 10 * Clock.ElapsedFrameTime)); - else if (mouseX < timelineQuad.TopLeft.X) - timeline.ScrollBy((float)((mouseX - timelineQuad.TopLeft.X) / 10 * Clock.ElapsedFrameTime)); - } + // scroll if in a drag and dragging outside visible extents + if (mouseX > timelineQuad.TopRight.X) + timeline.ScrollBy((float)((mouseX - timelineQuad.TopRight.X) / 10 * Clock.ElapsedFrameTime)); + else if (mouseX < timelineQuad.TopLeft.X) + timeline.ScrollBy((float)((mouseX - timelineQuad.TopLeft.X) / 10 * Clock.ElapsedFrameTime)); } private class SelectableAreaBackground : CompositeDrawable From 84fdd2e107dc3045a295eef5668bea8cd58e24cd Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 11 Oct 2022 17:16:57 +0300 Subject: [PATCH 48/82] Improve flashlight display on break periods --- .../Mods/CatchModFlashlight.cs | 6 +-- .../Mods/ManiaModFlashlight.cs | 6 +-- .../Mods/OsuModFlashlight.cs | 6 +-- .../Mods/TaikoModFlashlight.cs | 12 +++--- osu.Game/Rulesets/Mods/ModFlashlight.cs | 38 ++++++++----------- 5 files changed, 31 insertions(+), 37 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs index ff957b9b73..a9e9e8fbd5 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Mods { this.playfield = playfield; - FlashlightSize = new Vector2(0, GetSizeFor(0)); + FlashlightSize = new Vector2(0, GetSize()); FlashlightSmoothness = 1.4f; } @@ -66,9 +66,9 @@ namespace osu.Game.Rulesets.Catch.Mods FlashlightPosition = playfield.CatcherArea.ToSpaceOfOtherDrawable(playfield.Catcher.DrawPosition, this); } - protected override void OnComboChange(ValueChangedEvent e) + protected override void UpdateFlashlightSize(float size) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, GetSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(0, size), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs index 6eaede2112..947915cdf9 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Mania.Mods public ManiaFlashlight(ManiaModFlashlight modFlashlight) : base(modFlashlight) { - FlashlightSize = new Vector2(DrawWidth, GetSizeFor(0)); + FlashlightSize = new Vector2(DrawWidth, GetSize()); AddLayout(flashlightProperties); } @@ -54,9 +54,9 @@ namespace osu.Game.Rulesets.Mania.Mods } } - protected override void OnComboChange(ValueChangedEvent e) + protected override void UpdateFlashlightSize(float size) { - this.TransformTo(nameof(FlashlightSize), new Vector2(DrawWidth, GetSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(DrawWidth, size), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "RectangularFlashlight"; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 66f367c79b..1a86901d9c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Osu.Mods { followDelay = modFlashlight.FollowDelay.Value; - FlashlightSize = new Vector2(0, GetSizeFor(0)); + FlashlightSize = new Vector2(0, GetSize()); FlashlightSmoothness = 1.4f; } @@ -83,9 +83,9 @@ namespace osu.Game.Rulesets.Osu.Mods return base.OnMouseMove(e); } - protected override void OnComboChange(ValueChangedEvent e) + protected override void UpdateFlashlightSize(float size) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, GetSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(0, size), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index fca69e86cc..98f954ad29 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -47,21 +47,21 @@ namespace osu.Game.Rulesets.Taiko.Mods { this.taikoPlayfield = taikoPlayfield; - FlashlightSize = getSizeFor(0); + FlashlightSize = adjustSize(GetSize()); FlashlightSmoothness = 1.4f; AddLayout(flashlightProperties); } - private Vector2 getSizeFor(int combo) + private Vector2 adjustSize(float size) { // Preserve flashlight size through the playfield's aspect adjustment. - return new Vector2(0, GetSizeFor(combo) * taikoPlayfield.DrawHeight / TaikoPlayfield.DEFAULT_HEIGHT); + return new Vector2(0, size * taikoPlayfield.DrawHeight / TaikoPlayfield.DEFAULT_HEIGHT); } - protected override void OnComboChange(ValueChangedEvent e) + protected override void UpdateFlashlightSize(float size) { - this.TransformTo(nameof(FlashlightSize), getSizeFor(e.NewValue), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), adjustSize(size), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Taiko.Mods FlashlightPosition = ToLocalSpace(taikoPlayfield.HitTarget.ScreenSpaceDrawQuad.Centre); ClearTransforms(targetMember: nameof(FlashlightSize)); - FlashlightSize = getSizeFor(Combo.Value); + FlashlightSize = adjustSize(Combo.Value); flashlightProperties.Validate(); } diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 69937a0fba..d58a901154 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -12,7 +11,6 @@ using osu.Framework.Graphics.Rendering.Vertices; using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; -using osu.Game.Beatmaps.Timing; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.OpenGL.Vertices; @@ -20,6 +18,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osuTK; using osuTK.Graphics; @@ -84,8 +83,6 @@ namespace osu.Game.Rulesets.Mods flashlight.Combo.BindTo(Combo); drawableRuleset.KeyBindingInputManager.Add(flashlight); - - flashlight.Breaks = drawableRuleset.Beatmap.Breaks; } protected abstract Flashlight CreateFlashlight(); @@ -100,8 +97,6 @@ namespace osu.Game.Rulesets.Mods public override bool RemoveCompletedTransforms => false; - public List Breaks = new List(); - private readonly float defaultFlashlightSize; private readonly float sizeMultiplier; private readonly bool comboBasedSize; @@ -119,37 +114,36 @@ namespace osu.Game.Rulesets.Mods shader = shaderManager.Load("PositionAndColour", FragmentShader); } + [Resolved] + private Player? player { get; set; } + + private readonly IBindable isBreakTime = new BindableBool(); + protected override void LoadComplete() { base.LoadComplete(); - Combo.ValueChanged += OnComboChange; + Combo.ValueChanged += _ => UpdateFlashlightSize(GetSize()); - using (BeginAbsoluteSequence(0)) + if (player != null) { - foreach (var breakPeriod in Breaks) - { - if (!breakPeriod.HasEffect) - continue; - - if (breakPeriod.Duration < FLASHLIGHT_FADE_DURATION * 2) continue; - - this.Delay(breakPeriod.StartTime + FLASHLIGHT_FADE_DURATION).FadeOutFromOne(FLASHLIGHT_FADE_DURATION); - this.Delay(breakPeriod.EndTime - FLASHLIGHT_FADE_DURATION).FadeInFromZero(FLASHLIGHT_FADE_DURATION); - } + isBreakTime.BindTo(player.IsBreakTime); + isBreakTime.BindValueChanged(_ => UpdateFlashlightSize(GetSize()), true); } } - protected abstract void OnComboChange(ValueChangedEvent e); + protected abstract void UpdateFlashlightSize(float size); protected abstract string FragmentShader { get; } - protected float GetSizeFor(int combo) + protected float GetSize() { float size = defaultFlashlightSize * sizeMultiplier; - if (comboBasedSize) - size *= GetComboScaleFor(combo); + if (isBreakTime.Value) + size *= 2.5f; + else if (comboBasedSize) + size *= GetComboScaleFor(Combo.Value); return size; } From 721bfb5369731496147f4fbe7a278b0a789e8dad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 14:46:35 +0900 Subject: [PATCH 49/82] Rename parameter to read better --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index cf72a611e5..0f0e72b0ac 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -134,6 +134,6 @@ namespace osu.Game.Beatmaps /// /// Reads the correct track restart point from beatmap metadata and sets looping to enabled. /// - void PrepareTrackForPreview(bool looping, int priorToPreview = 0); + void PrepareTrackForPreview(bool looping, double offsetFromPreviewPoint = 0); } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 7eb7852897..d788ae5862 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -110,10 +110,10 @@ namespace osu.Game.Beatmaps public Track LoadTrack() => track = GetBeatmapTrack() ?? GetVirtualTrack(1000); - public void PrepareTrackForPreview(bool looping, int priorToPreview = 0) + public void PrepareTrackForPreview(bool looping, double offsetFromPreviewPoint = 0) { Track.Looping = looping; - Track.RestartPoint = Metadata.PreviewTime - priorToPreview; + Track.RestartPoint = Metadata.PreviewTime - offsetFromPreviewPoint; if (Track.RestartPoint == -1) { From db148d145b4e6d8e5f3484033fbadd867d75fb5b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 14:47:15 +0900 Subject: [PATCH 50/82] Fix incorrect offset logic for beatmaps without a preview point specified --- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 +++- osu.Game/Screens/Menu/IntroScreen.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index d788ae5862..393c4ba892 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -113,7 +113,7 @@ namespace osu.Game.Beatmaps public void PrepareTrackForPreview(bool looping, double offsetFromPreviewPoint = 0) { Track.Looping = looping; - Track.RestartPoint = Metadata.PreviewTime - offsetFromPreviewPoint; + Track.RestartPoint = Metadata.PreviewTime; if (Track.RestartPoint == -1) { @@ -125,6 +125,8 @@ namespace osu.Game.Beatmaps Track.RestartPoint = 0.4f * Track.Length; } + + Track.RestartPoint += offsetFromPreviewPoint; } /// diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 435c02de96..dcead4a3a8 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -278,7 +278,7 @@ namespace osu.Game.Screens.Menu if (!UsingThemedIntro) { - initialBeatmap?.PrepareTrackForPreview(false, 2600); + initialBeatmap?.PrepareTrackForPreview(false, -2600); drawableTrack.VolumeTo(0); drawableTrack.Restart(); From d6998c810c064ed0b26d3718ac62ffef0d709e77 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 14:50:04 +0900 Subject: [PATCH 51/82] Fix incorrect delay for non-theme music on "welcome" intro --- osu.Game/Screens/Menu/IntroWelcome.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroWelcome.cs b/osu.Game/Screens/Menu/IntroWelcome.cs index 9e56a3a0b7..5ae2158172 100644 --- a/osu.Game/Screens/Menu/IntroWelcome.cs +++ b/osu.Game/Screens/Menu/IntroWelcome.cs @@ -78,13 +78,17 @@ namespace osu.Game.Screens.Menu if (reverbChannel != null) intro.LogoVisualisation.AddAmplitudeSource(reverbChannel); - Scheduler.AddDelayed(() => - { + if (!UsingThemedIntro) StartTrack(); - // this classic intro loops forever. + Scheduler.AddDelayed(() => + { if (UsingThemedIntro) + { + StartTrack(); + // this classic intro loops forever. Track.Looping = true; + } const float fade_in_time = 200; From d2d589a15695edab3b1f862b15ef4d27f63808d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 15:11:52 +0900 Subject: [PATCH 52/82] Expose HUD state via `Player` --- osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs | 3 ++- osu.Game/Screens/Play/Player.cs | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs index a923aca2c8..2dc9f5f5cb 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs @@ -11,6 +11,7 @@ using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; using osu.Game.Skinning; using osuTK.Graphics; @@ -41,7 +42,7 @@ namespace osu.Game.Rulesets.Catch.UI } [BackgroundDependencyLoader(true)] - private void load(DrawableRuleset drawableRuleset) + private void load(DrawableRuleset drawableRuleset, HUDOverlay hud) { hudVisibilityMode = config.GetBindable(OsuSetting.HUDVisibilityMode); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7721d5b912..68b623b781 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -94,6 +94,11 @@ namespace osu.Game.Screens.Play public int RestartCount; + /// + /// Whether the is currently visible. + /// + public IBindable ShowingOverlayComponents = new Bindable(); + [Resolved] private ScoreManager scoreManager { get; set; } @@ -1015,6 +1020,8 @@ namespace osu.Game.Screens.Play }); HUDOverlay.IsPlaying.BindTo(localUserPlaying); + ShowingOverlayComponents.BindTo(HUDOverlay.ShowHud); + DimmableStoryboard.IsBreakTime.BindTo(breakTracker.IsBreakTime); DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); From 652bc4ac61568d9a596bee7944248942416aa590 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 15:14:33 +0900 Subject: [PATCH 53/82] Update `CatchComboDisplay` implementation to use newly exposed bindable --- .../UI/CatchComboDisplay.cs | 64 +++---------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs index 2dc9f5f5cb..86d4e73144 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs @@ -6,11 +6,9 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Game.Configuration; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osu.Game.Skinning; using osuTK.Graphics; @@ -27,14 +25,7 @@ namespace osu.Game.Rulesets.Catch.UI [CanBeNull] public ICatchComboCounter ComboCounter => Drawable as ICatchComboCounter; - private Bindable hudVisibilityMode = null!; - - private readonly BindableBool replayLoaded = new BindableBool(); - - private readonly BindableBool showCombo = new BindableBool(); - - [Resolved] - private OsuConfigManager config { get; set; } + private readonly IBindable showCombo = new BindableBool(true); public CatchComboDisplay() : base(new CatchSkinComponent(CatchSkinComponents.CatchComboCounter), _ => Empty()) @@ -42,51 +33,18 @@ namespace osu.Game.Rulesets.Catch.UI } [BackgroundDependencyLoader(true)] - private void load(DrawableRuleset drawableRuleset, HUDOverlay hud) + private void load(Player player) { - hudVisibilityMode = config.GetBindable(OsuSetting.HUDVisibilityMode); - - hudVisibilityMode.BindValueChanged(s => + if (player != null) { - updateVisibilityState(); - }); - - if (drawableRuleset != null) - replayLoaded.BindTo(drawableRuleset.HasReplayLoaded); - - replayLoaded.BindValueChanged(s => - { - updateVisibilityState(); - }); - - showCombo.BindValueChanged(s => - { - if (ComboCounter == null) return; - - if (!s.NewValue) + showCombo.BindTo(player.ShowingOverlayComponents); + showCombo.BindValueChanged(s => { - ComboCounter.Hide(); - } - }); - - updateVisibilityState(); - - void updateVisibilityState() - { - switch (hudVisibilityMode.Value) - { - case HUDVisibilityMode.Never: - showCombo.Value = false; - break; - - case HUDVisibilityMode.HideDuringGameplay: - showCombo.Value = replayLoaded.Value; - break; - - case HUDVisibilityMode.Always: - showCombo.Value = true; - break; - } + if (!s.NewValue) + ComboCounter?.Hide(); + else + ComboCounter?.Show(); + }, true); } } @@ -120,8 +78,6 @@ namespace osu.Game.Rulesets.Catch.UI private void updateCombo(int newCombo, Color4? hitObjectColour) { - if (!showCombo.Value) return; - currentCombo = newCombo; ComboCounter?.UpdateCombo(newCombo, hitObjectColour); } From 2e3e4ac5be0f4e14b2b740a42de9013bcd4a7e4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 15:14:54 +0900 Subject: [PATCH 54/82] Update `CatchComboDisplay` to use NRT --- osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs index 86d4e73144..b2b77b8f11 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs @@ -1,9 +1,6 @@ // 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 JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Catch.Objects.Drawables; @@ -22,8 +19,7 @@ namespace osu.Game.Rulesets.Catch.UI { private int currentCombo; - [CanBeNull] - public ICatchComboCounter ComboCounter => Drawable as ICatchComboCounter; + public ICatchComboCounter? ComboCounter => Drawable as ICatchComboCounter; private readonly IBindable showCombo = new BindableBool(true); @@ -33,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.UI } [BackgroundDependencyLoader(true)] - private void load(Player player) + private void load(Player? player) { if (player != null) { From ea3d08d5a0160f495e98da0ffdd96b76aaa918fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 15:22:46 +0900 Subject: [PATCH 55/82] Fix collision of external hide with internal logic in `LegacyCatchComboCounter` --- osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs index b2b77b8f11..a804caa542 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -34,13 +35,7 @@ namespace osu.Game.Rulesets.Catch.UI if (player != null) { showCombo.BindTo(player.ShowingOverlayComponents); - showCombo.BindValueChanged(s => - { - if (!s.NewValue) - ComboCounter?.Hide(); - else - ComboCounter?.Show(); - }, true); + showCombo.BindValueChanged(s => this.FadeTo(s.NewValue ? 1 : 0, HUDOverlay.FADE_DURATION, HUDOverlay.FADE_EASING), true); } } From f3e85d2302775bf41401d85a1b1292bcfba738c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 15:25:16 +0900 Subject: [PATCH 56/82] Fix initial state being wrong due to `BindValueChanged` call in BDL load --- osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs index a804caa542..a5b7d8d0af 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs @@ -29,9 +29,13 @@ namespace osu.Game.Rulesets.Catch.UI { } - [BackgroundDependencyLoader(true)] - private void load(Player? player) + [Resolved(canBeNull: true)] + private Player? player { get; set; } + + protected override void LoadComplete() { + base.LoadComplete(); + if (player != null) { showCombo.BindTo(player.ShowingOverlayComponents); From 9d0ae3f0ca956bead9d33821f5b8917af18d1bf5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 15:32:24 +0900 Subject: [PATCH 57/82] Update test scene to work with new data source --- .../TestSceneComboCounter.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs index f39af76a2d..f3161f32be 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs @@ -4,14 +4,16 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Utils; -using osu.Game.Configuration; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; using osuTK; using osuTK.Graphics; @@ -19,16 +21,19 @@ namespace osu.Game.Rulesets.Catch.Tests { public class TestSceneComboCounter : CatchSkinnableTestScene { - private OsuConfigManager localConfig = null!; - private ScoreProcessor scoreProcessor = null!; private Color4 judgedObjectColour = Color4.White; + private readonly Bindable showHud = new Bindable(true); + [BackgroundDependencyLoader] private void load() { - Dependencies.Cache(localConfig = new OsuConfigManager(LocalStorage)); + Dependencies.CacheAs(new TestPlayer + { + ShowingOverlayComponents = { BindTarget = showHud }, + }); } [SetUp] @@ -36,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Tests { scoreProcessor = new ScoreProcessor(new CatchRuleset()); - localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always); + showHud.Value = true; SetContents(_ => new CatchComboDisplay { @@ -62,10 +67,10 @@ namespace osu.Game.Rulesets.Catch.Tests ); }); - AddStep("set hud to never show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + AddStep("set hud to never show", () => showHud.Value = false); AddRepeatStep("perform hit", () => performJudgement(HitResult.Great), 5); - AddStep("set hud to show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always)); + AddStep("set hud to show", () => showHud.Value = true); AddRepeatStep("perform hit", () => performJudgement(HitResult.Great), 5); } From e43c8e84b022c31b18d11b08611dc371985b99f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 15:43:05 +0900 Subject: [PATCH 58/82] Use `Show` instead of `Alpha=1` --- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 105618c728..193d15064a 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -362,7 +362,7 @@ namespace osu.Game.Overlays.Comments /// private void makeDeleted() { - deletedLabel.Alpha = 1f; + deletedLabel.Show(); content.FadeColour(OsuColour.Gray(0.5f)); votePill.Hide(); actionsContainer.Expire(); From 00d83980566a2d044255fdbd3da806dd7a74bacc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 15:47:28 +0900 Subject: [PATCH 59/82] Update test scene to allow seeing loading spinner --- .../Visual/Online/TestSceneCommentActions.cs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index 11210db8a9..af6f8ba97c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -78,11 +80,12 @@ namespace osu.Game.Tests.Visual.Online }); } + private ManualResetEventSlim deletionPerformed = new ManualResetEventSlim(); + [Test] public void TestDeletion() { DrawableComment? ourComment = null; - bool delete = false; addTestComments(); AddUntilStep("Comment exists", () => @@ -102,6 +105,8 @@ namespace osu.Game.Tests.Visual.Online }); AddStep("Setup request handling", () => { + deletionPerformed.Reset(); + dummyAPI.HandleRequest = request => { if (!(request is CommentDeleteRequest req)) @@ -130,18 +135,23 @@ namespace osu.Game.Tests.Visual.Online IncludedComments = new List(), PinnedComments = new List(), }; - delete = true; - req.TriggerSuccess(cb); + + Task.Run(() => + { + deletionPerformed.Wait(10000); + req.TriggerSuccess(cb); + }); + return true; }; }); AddStep("Confirm dialog", () => InputManager.Key(Key.Number1)); - AddUntilStep("Deletion requested", () => delete); + AddAssert("Loading spinner shown", () => commentsContainer.ChildrenOfType().Any(d => d.IsPresent)); - AddUntilStep("Comment is deleted locally", () => - { - return this.ChildrenOfType().Single(x => x.Comment.Id == 1).WasDeleted; - }); + + AddStep("Complete request", () => deletionPerformed.Set()); + + AddUntilStep("Comment is deleted locally", () => this.ChildrenOfType().Single(x => x.Comment.Id == 1).WasDeleted); } [Test] From b72c8970ebf9a2f790968822c4462fb1c7aeb1f8 Mon Sep 17 00:00:00 2001 From: Dario Headley Date: Wed, 12 Oct 2022 09:39:57 +0200 Subject: [PATCH 60/82] Max Combo Counter added --- .../TestSceneSkinnableComboCounter.cs | 1 + .../Play/HUD/ComboCounters/ComboCounter.cs | 26 ++++++ .../DefaultComboCounter.cs | 25 ++---- .../HUD/ComboCounters/LongestComboCounter.cs | 85 +++++++++++++++++++ osu.Game/Skinning/ArgonSkin.cs | 1 + osu.Game/Skinning/TrianglesSkin.cs | 1 + 6 files changed, 119 insertions(+), 20 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/ComboCounters/ComboCounter.cs rename osu.Game/Screens/Play/HUD/{ => ComboCounters}/DefaultComboCounter.cs (61%) create mode 100644 osu.Game/Screens/Play/HUD/ComboCounters/LongestComboCounter.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs index ef56f456ea..d234d6b8b7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs @@ -10,6 +10,7 @@ using osu.Framework.Testing; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.Play.HUD.ComboCounters; using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay diff --git a/osu.Game/Screens/Play/HUD/ComboCounters/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounters/ComboCounter.cs new file mode 100644 index 0000000000..9bd08f3930 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ComboCounters/ComboCounter.cs @@ -0,0 +1,26 @@ +// 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 System; +using osu.Game.Graphics.UserInterface; +using osu.Game.Skinning; + +namespace osu.Game.Screens.Play.HUD.ComboCounters +{ + public abstract class ComboCounter : RollingCounter, ISkinnableDrawable + { + public bool UsesFixedAnchor { get; set; } + + protected ComboCounter() + { + Current.Value = DisplayedCount = 0; + } + + protected override double GetProportionalDuration(int currentValue, int newValue) + { + return Math.Abs(currentValue - newValue) * RollingDuration * 100.0f; + } + } +} diff --git a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounters/DefaultComboCounter.cs similarity index 61% rename from osu.Game/Screens/Play/HUD/DefaultComboCounter.cs rename to osu.Game/Screens/Play/HUD/ComboCounters/DefaultComboCounter.cs index 1f14811169..a612f042f5 100644 --- a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounters/DefaultComboCounter.cs @@ -3,27 +3,17 @@ #nullable disable -using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Scoring; -using osu.Game.Skinning; -namespace osu.Game.Screens.Play.HUD +namespace osu.Game.Screens.Play.HUD.ComboCounters { - public class DefaultComboCounter : RollingCounter, ISkinnableDrawable + public class DefaultComboCounter : ComboCounter { - public bool UsesFixedAnchor { get; set; } - - public DefaultComboCounter() - { - Current.Value = DisplayedCount = 0; - } - [BackgroundDependencyLoader] private void load(OsuColour colours, ScoreProcessor scoreProcessor) { @@ -31,17 +21,12 @@ namespace osu.Game.Screens.Play.HUD Current.BindTo(scoreProcessor.Combo); } + protected override OsuSpriteText CreateSpriteText() + => base.CreateSpriteText().With(s => s.Font = s.Font.With(size: 20f)); + protected override LocalisableString FormatCount(int count) { return $@"{count}x"; } - - protected override double GetProportionalDuration(int currentValue, int newValue) - { - return Math.Abs(currentValue - newValue) * RollingDuration * 100.0f; - } - - protected override OsuSpriteText CreateSpriteText() - => base.CreateSpriteText().With(s => s.Font = s.Font.With(size: 20f)); } } diff --git a/osu.Game/Screens/Play/HUD/ComboCounters/LongestComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounters/LongestComboCounter.cs new file mode 100644 index 0000000000..b6be42764a --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ComboCounters/LongestComboCounter.cs @@ -0,0 +1,85 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Scoring; +using osuTK; + +namespace osu.Game.Screens.Play.HUD.ComboCounters +{ + public class LongestComboCounter : ComboCounter + { + [BackgroundDependencyLoader] + private void load(OsuColour colours, ScoreProcessor scoreProcessor) + { + Colour = colours.YellowLighter; + Current.BindTo(scoreProcessor.HighestCombo); + } + + protected override IHasText CreateText() => new TextComponent(); + + private class TextComponent : CompositeDrawable, IHasText + { + public LocalisableString Text + { + get => text.Text; + set => text.Text = $"{value}x"; + } + + private readonly OsuSpriteText text; + + public TextComponent() + { + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(2), + Children = new Drawable[] + { + text = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.Numeric.With(size: 20) + }, + new FillFlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + Font = OsuFont.Numeric.With(size: 8), + Text = @"longest", + }, + new OsuSpriteText + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + Font = OsuFont.Numeric.With(size: 8), + Text = @"combo", + Padding = new MarginPadding { Bottom = 3f } + } + } + } + } + }; + } + } + } +} diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index 010e2175e1..006f6b4e46 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -15,6 +15,7 @@ using osu.Game.Beatmaps.Formats; using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.Play.HUD.ComboCounters; using osu.Game.Screens.Play.HUD.HitErrorMeters; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Skinning/TrianglesSkin.cs b/osu.Game/Skinning/TrianglesSkin.cs index 2c70963524..84b39f2768 100644 --- a/osu.Game/Skinning/TrianglesSkin.cs +++ b/osu.Game/Skinning/TrianglesSkin.cs @@ -16,6 +16,7 @@ using osu.Game.Beatmaps.Formats; using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.Play.HUD.ComboCounters; using osu.Game.Screens.Play.HUD.HitErrorMeters; using osuTK; using osuTK.Graphics; From 1c93551590a6e02bd231b858079570cb7a0c96f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 17:07:13 +0900 Subject: [PATCH 61/82] Remove completely incorrect check before applying ruleset transformer --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 6ad5d64e4b..7267ebd92d 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -41,7 +41,7 @@ namespace osu.Game.Skinning Ruleset = ruleset; Beatmap = beatmap; - InternalChild = new BeatmapSkinProvidingContainer(beatmapSkin is LegacySkin ? GetRulesetTransformedSkin(beatmapSkin) : beatmapSkin) + InternalChild = new BeatmapSkinProvidingContainer(GetRulesetTransformedSkin(beatmapSkin)) { Child = Content = new Container { From fd20515a6d21e501133b32a8170fd7d441abdb89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 17:28:06 +0900 Subject: [PATCH 62/82] Don't throw if `LegacySkin` doesn't have a transformer encapsulating it This allows for more flexibility in lookups. --- osu.Game/Skinning/LegacySkin.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 646746a0f3..eaca0de11a 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -389,18 +389,17 @@ namespace osu.Game.Skinning if (particle != null) return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, particle); - else - return new LegacyJudgementPieceOld(resultComponent.Component, createDrawable); + + return new LegacyJudgementPieceOld(resultComponent.Component, createDrawable); } return null; case SkinnableSprite.SpriteComponent sprite: return this.GetAnimation(sprite.LookupName, false, false); - - default: - throw new UnsupportedSkinComponentException(component); } + + return null; } private Texture? getParticleTexture(HitResult result) From 8bf4ca4b53c28bf8f666877c69fcaa37bad0c2a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 17:47:20 +0900 Subject: [PATCH 63/82] Add legacy skin fallback when beatmap skin is providing resources --- .../Skinning/Legacy/CatchLegacySkinTransformer.cs | 6 +++++- .../Skinning/Legacy/ManiaLegacySkinTransformer.cs | 2 ++ .../Skinning/Legacy/OsuLegacySkinTransformer.cs | 2 ++ .../Skinning/Legacy/TaikoLegacySkinTransformer.cs | 9 +++++++-- .../Skinning/BeatmapSkinProvidingContainer.cs | 15 ++++++++++++++- osu.Game/Skinning/LegacySkinTransformer.cs | 5 +++++ 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs index c06d9f520f..a73b34c9b6 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs @@ -13,6 +13,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy { public class CatchLegacySkinTransformer : LegacySkinTransformer { + public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasPear; + + private bool hasPear => GetTexture("fruit-pear") != null; + /// /// For simplicity, let's use legacy combo font texture existence as a way to identify legacy skins from default. /// @@ -49,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy switch (catchSkinComponent.Component) { case CatchSkinComponents.Fruit: - if (GetTexture("fruit-pear") != null) + if (hasPear) return new LegacyFruitPiece(); return null; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs index 1d39721a2b..a07dbea368 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs @@ -19,6 +19,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class ManiaLegacySkinTransformer : LegacySkinTransformer { + public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasKeyTexture.Value; + /// /// Mapping of to their corresponding /// value. diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index b778bc21d1..856ccb5044 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -13,6 +13,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class OsuLegacySkinTransformer : LegacySkinTransformer { + public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasHitCircle.Value; + private readonly Lazy hasHitCircle; /// diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs index 992316ca53..020cdab4dc 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs @@ -14,8 +14,13 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public class TaikoLegacySkinTransformer : LegacySkinTransformer { + public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasHitCircle || hasBarLeft; + private readonly Lazy hasExplosion; + private bool hasHitCircle => GetTexture("taikohitcircle") != null; + private bool hasBarLeft => GetTexture("taiko-bar-left") != null; + public TaikoLegacySkinTransformer(ISkin skin) : base(skin) { @@ -42,14 +47,14 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy return null; case TaikoSkinComponents.InputDrum: - if (GetTexture("taiko-bar-left") != null) + if (hasBarLeft) return new LegacyInputDrum(); return null; case TaikoSkinComponents.CentreHit: case TaikoSkinComponents.RimHit: - if (GetTexture("taikohitcircle") != null) + if (hasHitCircle) return new LegacyHit(taikoComponent.Component); return null; diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs index abc7b61036..f0caef9fa1 100644 --- a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs +++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs @@ -67,9 +67,12 @@ namespace osu.Game.Skinning return sampleInfo is StoryboardSampleInfo || beatmapHitsounds.Value; } + private readonly ISkin skin; + public BeatmapSkinProvidingContainer(ISkin skin) : base(skin) { + this.skin = skin; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -84,11 +87,21 @@ namespace osu.Game.Skinning } [BackgroundDependencyLoader] - private void load() + private void load(SkinManager skins) { beatmapSkins.BindValueChanged(_ => TriggerSourceChanged()); beatmapColours.BindValueChanged(_ => TriggerSourceChanged()); beatmapHitsounds.BindValueChanged(_ => TriggerSourceChanged()); + + // If the beatmap skin looks to have skinnable resources, add the default classic skin as a fallback opportunity. + if (skin is LegacySkinTransformer legacySkin && legacySkin.IsProvidingLegacyResources) + { + SetSources(new[] + { + skin, + skins.DefaultClassicSkin + }); + } } } } diff --git a/osu.Game/Skinning/LegacySkinTransformer.cs b/osu.Game/Skinning/LegacySkinTransformer.cs index 2de1564a5c..367e5bae01 100644 --- a/osu.Game/Skinning/LegacySkinTransformer.cs +++ b/osu.Game/Skinning/LegacySkinTransformer.cs @@ -13,6 +13,11 @@ namespace osu.Game.Skinning /// public abstract class LegacySkinTransformer : SkinTransformer { + /// + /// Whether the skin being transformed is able to provide legacy resources for the ruleset. + /// + public virtual bool IsProvidingLegacyResources => this.HasFont(LegacyFont.Combo); + protected LegacySkinTransformer(ISkin skin) : base(skin) { From e2c80f09dacc27e16a83f2cf5b0dbed82b75ae26 Mon Sep 17 00:00:00 2001 From: "D.Headley" Date: Wed, 12 Oct 2022 11:05:22 +0200 Subject: [PATCH 64/82] Remove unnecesary directive --- osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs index d234d6b8b7..57d52243ba 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; -using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD.ComboCounters; using osu.Game.Skinning; From 19f3810020f53ebf9ac206fbb562f04a14dcb8ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 18:50:40 +0900 Subject: [PATCH 65/82] Revert namespace change Let's not --- .../Visual/Gameplay/TestSceneSkinnableComboCounter.cs | 2 +- osu.Game/Screens/Play/HUD/{ComboCounters => }/ComboCounter.cs | 4 +--- .../Play/HUD/{ComboCounters => }/DefaultComboCounter.cs | 4 +--- .../Play/HUD/{ComboCounters => }/LongestComboCounter.cs | 4 +--- osu.Game/Skinning/ArgonSkin.cs | 1 - osu.Game/Skinning/TrianglesSkin.cs | 1 - 6 files changed, 4 insertions(+), 12 deletions(-) rename osu.Game/Screens/Play/HUD/{ComboCounters => }/ComboCounter.cs (90%) rename osu.Game/Screens/Play/HUD/{ComboCounters => }/DefaultComboCounter.cs (92%) rename osu.Game/Screens/Play/HUD/{ComboCounters => }/LongestComboCounter.cs (97%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs index 57d52243ba..ef56f456ea 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; -using osu.Game.Screens.Play.HUD.ComboCounters; +using osu.Game.Screens.Play.HUD; using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay diff --git a/osu.Game/Screens/Play/HUD/ComboCounters/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounter.cs similarity index 90% rename from osu.Game/Screens/Play/HUD/ComboCounters/ComboCounter.cs rename to osu.Game/Screens/Play/HUD/ComboCounter.cs index 9bd08f3930..4179d41646 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounters/ComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounter.cs @@ -1,13 +1,11 @@ // 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 System; using osu.Game.Graphics.UserInterface; using osu.Game.Skinning; -namespace osu.Game.Screens.Play.HUD.ComboCounters +namespace osu.Game.Screens.Play.HUD { public abstract class ComboCounter : RollingCounter, ISkinnableDrawable { diff --git a/osu.Game/Screens/Play/HUD/ComboCounters/DefaultComboCounter.cs b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs similarity index 92% rename from osu.Game/Screens/Play/HUD/ComboCounters/DefaultComboCounter.cs rename to osu.Game/Screens/Play/HUD/DefaultComboCounter.cs index a612f042f5..0c9c363280 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounters/DefaultComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs @@ -1,8 +1,6 @@ // 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.Graphics; using osu.Framework.Localisation; @@ -10,7 +8,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Scoring; -namespace osu.Game.Screens.Play.HUD.ComboCounters +namespace osu.Game.Screens.Play.HUD { public class DefaultComboCounter : ComboCounter { diff --git a/osu.Game/Screens/Play/HUD/ComboCounters/LongestComboCounter.cs b/osu.Game/Screens/Play/HUD/LongestComboCounter.cs similarity index 97% rename from osu.Game/Screens/Play/HUD/ComboCounters/LongestComboCounter.cs rename to osu.Game/Screens/Play/HUD/LongestComboCounter.cs index b6be42764a..0e7af69af2 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounters/LongestComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/LongestComboCounter.cs @@ -1,8 +1,6 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +11,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Scoring; using osuTK; -namespace osu.Game.Screens.Play.HUD.ComboCounters +namespace osu.Game.Screens.Play.HUD { public class LongestComboCounter : ComboCounter { diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index 006f6b4e46..010e2175e1 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -15,7 +15,6 @@ using osu.Game.Beatmaps.Formats; using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Screens.Play.HUD; -using osu.Game.Screens.Play.HUD.ComboCounters; using osu.Game.Screens.Play.HUD.HitErrorMeters; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Skinning/TrianglesSkin.cs b/osu.Game/Skinning/TrianglesSkin.cs index 84b39f2768..2c70963524 100644 --- a/osu.Game/Skinning/TrianglesSkin.cs +++ b/osu.Game/Skinning/TrianglesSkin.cs @@ -16,7 +16,6 @@ using osu.Game.Beatmaps.Formats; using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Screens.Play.HUD; -using osu.Game.Screens.Play.HUD.ComboCounters; using osu.Game.Screens.Play.HUD.HitErrorMeters; using osuTK; using osuTK.Graphics; From f1f323ee82a50c02661de12a39e8ddf76899271e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Oct 2022 18:55:50 +0900 Subject: [PATCH 66/82] Add new deserialisation test including longest combo counter --- .../Archives/modified-default-20221012.osk | Bin 0 -> 1209 bytes osu.Game.Tests/Skins/SkinDeserialisationTest.cs | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Resources/Archives/modified-default-20221012.osk diff --git a/osu.Game.Tests/Resources/Archives/modified-default-20221012.osk b/osu.Game.Tests/Resources/Archives/modified-default-20221012.osk new file mode 100644 index 0000000000000000000000000000000000000000..74ff4f31d5c506d9c7e9b6d503d3f8149f6eeb9f GIT binary patch literal 1209 zcmWIWW@Zs#U|`^2STM~ew8mlc^mRa95hF;1fuT4%GfyuwFY|1_A=e=X0oUKQM{h_5 zEM9r!+^KV3+8ZV2dT!cbtvoxjDSh(?k2uHXh)TxY{Qp1x_+ME+MfFWoTa@#Kd*00H zqRECYHZq@CCU|zfVT-hapzxf$1+j9BPfZ@!#hKn@@w>6tTXaQj!od>(d_j*`Ch~If zroY>e_^{>Si*5NyUj=)0E2pRxgdecb`gzM(G;i+Ot6Q4(#<)}$zKfrJ=%MuTBc{(1 zE@#Dsetw!%`KR(DQviyexE)#jnt*;;48*)pKV{~n@K$+}S-7&X zig%igy+7?3HPkoGe$o`pbyw*jXRr-kk;p{sTS+1~H&xeG@bDJVITZ^K%RG^HTFl ziovdaJKfR$wt>j;_kTqK&mS!6n7qcr*5OoG=4`RR2Tc|d-?wfp$o=xh!{ze6-!ij8 zvUV`Ev)mAQ`r!ZO`FpsOje{=}aw zx3mq9mKN>2d2i;ODYqEg9BvN+q$_c2O7rc?NKay2j76C702{_4`5 z=6SDzRu=B)j+4-yEB`iq!|eX+a<$4yf|kpsY}yd2z5W>ILjSk+XFqU1t}x!iw^vxa zNxS0N22=BOi~5!a>zc7;J73e-AFwXpcbam-^{V*S#owpAE40!1V_ERj z%s5ki&%*C5?-lQ>$3AkFH*j0eZIaEBZLj>^qITM&mkvjsUz)2d^@sCc#KtE*j~hQp zzI5N>UBCX%^8aDK-1YtIzU6%oZ_sXzUdJlpmX+SFm33*#kKNOj{SQc-T%Gp)+WG@b zEf-Jc?cVOxzO+Tvu-lqJ-P2`q&)!1Eq)9=?A|}a%`LF$Tsdr=euedq#|Crcre`d~h z^8BWHa?|0t4_!}PdfdO)*ll|~TJ&q~_Tgm#MmrM_^8;~keqMTTYEEi$2{_)n`&bzQ zycwB97;tAVjtxbgk$~6rr^dm~gQtSadVc{fRK6 Zff>Ws0p6@^AO$Qy_z6gF1S(-*007Hu-Ae!f literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs index 1b03f8ef6b..989459632e 100644 --- a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs +++ b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs @@ -38,7 +38,9 @@ namespace osu.Game.Tests.Skins // Covers legacy song progress, UR counter, colour hit error metre. "Archives/modified-classic-20220801.osk", // Covers clicks/s counter - "Archives/modified-default-20220818.osk" + "Archives/modified-default-20220818.osk", + // Covers longest combo counter + "Archives/modified-default-20221012.osk" }; /// From 565de23222bf84972c6ca89389c91bf1926a8174 Mon Sep 17 00:00:00 2001 From: Feodor0090 <53872073+Feodor0090@users.noreply.github.com> Date: Wed, 12 Oct 2022 21:26:33 +0300 Subject: [PATCH 67/82] Fix CQ (non-readonly field) --- osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index af6f8ba97c..bf01d3b0ac 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -80,7 +80,7 @@ namespace osu.Game.Tests.Visual.Online }); } - private ManualResetEventSlim deletionPerformed = new ManualResetEventSlim(); + private readonly ManualResetEventSlim deletionPerformed = new ManualResetEventSlim(); [Test] public void TestDeletion() From 964ed01abb60cf3d21b2691c5bd530abf696d925 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 13 Oct 2022 02:39:37 +0300 Subject: [PATCH 68/82] Add confirmation dialog for updating locally modified beatmaps --- osu.Game/Localisation/PopupDialogStrings.cs | 24 +++++++++++ .../Select/Carousel/UpdateBeatmapSetButton.cs | 42 ++++++++++++++----- .../Carousel/UpdateLocalConfirmationDialog.cs | 21 ++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Localisation/PopupDialogStrings.cs create mode 100644 osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs diff --git a/osu.Game/Localisation/PopupDialogStrings.cs b/osu.Game/Localisation/PopupDialogStrings.cs new file mode 100644 index 0000000000..b2e9673cbe --- /dev/null +++ b/osu.Game/Localisation/PopupDialogStrings.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class PopupDialogStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.PopupDialog"; + + /// + /// "Are you sure you want to update this beatmap?" + /// + public static LocalisableString UpdateLocallyModifiedText => new TranslatableString(getKey(@"update_locally_modified_text"), @"Are you sure you want to update this beatmap?"); + + /// + /// "This will discard all local changes you have on that beatmap." + /// + public static LocalisableString UpdateLocallyModifiedDescription => new TranslatableString(getKey(@"update_locally_modified_description"), @"This will discard all local changes you have on that beatmap."); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs b/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs index 023d3627b0..1bb607bcf3 100644 --- a/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs +++ b/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs @@ -32,9 +32,12 @@ namespace osu.Game.Screens.Select.Carousel [Resolved] private IAPIProvider api { get; set; } = null!; - [Resolved(canBeNull: true)] + [Resolved] private LoginOverlay? loginOverlay { get; set; } + [Resolved] + private IDialogOverlay? dialogOverlay { get; set; } + public UpdateBeatmapSetButton(BeatmapSetInfo beatmapSetInfo) { this.beatmapSetInfo = beatmapSetInfo; @@ -102,17 +105,34 @@ namespace osu.Game.Screens.Select.Carousel }, }); - Action = () => - { - if (!api.IsLoggedIn) - { - loginOverlay?.Show(); - return; - } + Action = updateBeatmap; + } - beatmapDownloader.DownloadAsUpdate(beatmapSetInfo, preferNoVideo.Value); - attachExistingDownload(); - }; + private bool updateConfirmed; + + private void updateBeatmap() + { + if (!api.IsLoggedIn) + { + loginOverlay?.Show(); + return; + } + + if (dialogOverlay != null && beatmapSetInfo.Status == BeatmapOnlineStatus.LocallyModified && !updateConfirmed) + { + dialogOverlay.Push(new UpdateLocalConfirmationDialog(() => + { + updateConfirmed = true; + updateBeatmap(); + })); + + return; + } + + updateConfirmed = false; + + beatmapDownloader.DownloadAsUpdate(beatmapSetInfo, preferNoVideo.Value); + attachExistingDownload(); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs b/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs new file mode 100644 index 0000000000..f5267e905e --- /dev/null +++ b/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs @@ -0,0 +1,21 @@ +// 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.Sprites; +using osu.Game.Overlays.Dialog; +using osu.Game.Localisation; + +namespace osu.Game.Screens.Select.Carousel +{ + public class UpdateLocalConfirmationDialog : DeleteConfirmationDialog + { + public UpdateLocalConfirmationDialog(Action onConfirm) + { + HeaderText = PopupDialogStrings.UpdateLocallyModifiedText; + BodyText = PopupDialogStrings.UpdateLocallyModifiedDescription; + Icon = FontAwesome.Solid.ExclamationTriangle; + DeleteAction = onConfirm; + } + } +} From 7db7bcc283ab94c165c795d04554e597af17ddb7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 13 Oct 2022 02:40:20 +0300 Subject: [PATCH 69/82] Add test coverage --- .../TestSceneUpdateBeatmapSetButton.cs | 70 ++++++++++++++++--- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs index 70786c93e7..f76f050546 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs @@ -10,10 +10,13 @@ using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Online.API; +using osu.Game.Overlays; +using osu.Game.Overlays.Dialog; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Tests.Online; using osu.Game.Tests.Resources; +using osuTK.Input; namespace osu.Game.Tests.Visual.SongSelect { @@ -41,17 +44,7 @@ namespace osu.Game.Tests.Visual.SongSelect [SetUpSteps] public void SetUpSteps() { - AddStep("create carousel", () => - { - Child = carousel = new BeatmapCarousel - { - RelativeSizeAxes = Axes.Both, - BeatmapSets = new List - { - (testBeatmapSetInfo = TestResources.CreateTestBeatmapSetInfo()), - } - }; - }); + AddStep("create carousel", () => Child = createCarousel()); AddUntilStep("wait for load", () => carousel.BeatmapSetsLoaded); @@ -152,5 +145,60 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for button enabled", () => getUpdateButton()?.Enabled.Value == true); } + + [Test] + public void TestUpdateLocalBeatmap() + { + DialogOverlay dialogOverlay = null!; + + AddStep("create carousel with dialog overlay", () => + { + dialogOverlay = new DialogOverlay(); + + Child = new DependencyProvidingContainer + { + RelativeSizeAxes = Axes.Both, + CachedDependencies = new (Type, object)[] { (typeof(IDialogOverlay), dialogOverlay), }, + Children = new Drawable[] + { + createCarousel(), + dialogOverlay, + }, + }; + }); + + AddStep("setup beatmap state", () => + { + testBeatmapSetInfo.Beatmaps.First().OnlineMD5Hash = "different hash"; + testBeatmapSetInfo.Beatmaps.First().LastOnlineUpdate = DateTimeOffset.Now; + testBeatmapSetInfo.Status = BeatmapOnlineStatus.LocallyModified; + + carousel.UpdateBeatmapSet(testBeatmapSetInfo); + }); + + AddStep("click button", () => getUpdateButton()?.TriggerClick()); + + AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is UpdateLocalConfirmationDialog); + AddStep("click confirmation", () => + { + InputManager.MoveMouseTo(dialogOverlay.CurrentDialog.ChildrenOfType().First()); + InputManager.PressButton(MouseButton.Left); + }); + + AddUntilStep("update started", () => beatmapDownloader.GetExistingDownload(testBeatmapSetInfo) != null); + AddStep("release mouse button", () => InputManager.ReleaseButton(MouseButton.Left)); + } + + private BeatmapCarousel createCarousel() + { + return carousel = new BeatmapCarousel + { + RelativeSizeAxes = Axes.Both, + BeatmapSets = new List + { + (testBeatmapSetInfo = TestResources.CreateTestBeatmapSetInfo()), + } + }; + } } } From f6f5d33f53c0f40ce5382bd95677093157e50eca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Oct 2022 15:44:23 +0900 Subject: [PATCH 70/82] Add slight padding to playfield (roughly matches stable) --- osu.Game/Screens/Edit/EditorScreenWithTimeline.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index b3aafb9730..bcb084fd4e 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -106,6 +106,7 @@ namespace osu.Game.Screens.Edit Name = "Main content", RelativeSizeAxes = Axes.Both, Depth = float.MaxValue, + Padding = new MarginPadding(10), Child = spinner = new LoadingSpinner(true) { State = { Value = Visibility.Visible }, From a525b3f9f81d64da3c31f9fb29ac1e9bccf603dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Oct 2022 15:44:33 +0900 Subject: [PATCH 71/82] Reorder and rename toggle checkboxes to fit better --- .../Edit/Compose/Components/Timeline/TimelineArea.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index c2415ce978..58d378154a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -78,16 +78,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline LabelText = "Waveform", Current = { Value = true }, }, - controlPointsCheckbox = new OsuCheckbox - { - LabelText = "Control Points", - Current = { Value = true }, - }, ticksCheckbox = new OsuCheckbox { LabelText = "Ticks", Current = { Value = true }, - } + }, + controlPointsCheckbox = new OsuCheckbox + { + LabelText = "BPM", + Current = { Value = true }, + }, } } } From c3902728f65813f693ed9a5254e01b7eb313b8e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Oct 2022 15:47:54 +0900 Subject: [PATCH 72/82] Reorganise beatmap snap control to work better in compact mode --- .../Compose/Components/BeatDivisorControl.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 40403e08ad..19ea2162a3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -123,16 +123,6 @@ namespace osu.Game.Screens.Edit.Compose.Components } }, new Drawable[] - { - new TextFlowContainer(s => s.Font = s.Font.With(size: 14)) - { - Padding = new MarginPadding { Horizontal = 15 }, - Text = "beat snap", - RelativeSizeAxes = Axes.X, - TextAnchor = Anchor.TopCentre - }, - }, - new Drawable[] { new Container { @@ -173,6 +163,16 @@ namespace osu.Game.Screens.Edit.Compose.Components } } }, + new Drawable[] + { + new TextFlowContainer(s => s.Font = s.Font.With(size: 14)) + { + Padding = new MarginPadding { Horizontal = 15, Vertical = 8 }, + Text = "beat snap", + RelativeSizeAxes = Axes.X, + TextAnchor = Anchor.TopCentre, + }, + }, }, RowDimensions = new[] { From 0f4a2a605941a53772e6318450906b866310ff98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Oct 2022 16:04:38 +0900 Subject: [PATCH 73/82] Improve feel of settings toolbox group --- .../TestSceneSettingsToolboxGroup.cs | 8 +++ osu.Game/Overlays/SettingsToolboxGroup.cs | 69 ++++++++++--------- osu.Game/Screens/Play/PlayerLoader.cs | 3 + 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs index 50e506f82b..9fb0905a4f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs @@ -5,12 +5,14 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; using osu.Game.Overlays.Settings; +using osuTK; using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface @@ -20,11 +22,17 @@ namespace osu.Game.Tests.Visual.UserInterface { private SettingsToolboxGroup group; + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + [SetUp] public void SetUp() => Schedule(() => { Child = group = new SettingsToolboxGroup("example") { + Scale = new Vector2(3), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Children = new Drawable[] { new RoundedButton diff --git a/osu.Game/Overlays/SettingsToolboxGroup.cs b/osu.Game/Overlays/SettingsToolboxGroup.cs index 548d75c9a9..2f47019272 100644 --- a/osu.Game/Overlays/SettingsToolboxGroup.cs +++ b/osu.Game/Overlays/SettingsToolboxGroup.cs @@ -1,8 +1,7 @@ // 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.Bindables; using osu.Framework.Caching; using osu.Framework.Extensions.EnumExtensions; @@ -23,25 +22,40 @@ namespace osu.Game.Overlays { public class SettingsToolboxGroup : Container, IExpandable { + private readonly string title; public const int CONTAINER_WIDTH = 270; private const float transition_duration = 250; - private const int border_thickness = 2; private const int header_height = 30; private const int corner_radius = 5; - private const float fade_duration = 800; - private const float inactive_alpha = 0.5f; - private readonly Cached headerTextVisibilityCache = new Cached(); - private readonly FillFlowContainer content; + protected override Container Content => content; + + private readonly FillFlowContainer content = new FillFlowContainer + { + Name = @"Content", + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.X, + AutoSizeDuration = transition_duration, + AutoSizeEasing = Easing.OutQuint, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = 10, Top = 5, Bottom = 10 }, + Spacing = new Vector2(0, 15), + }; public BindableBool Expanded { get; } = new BindableBool(true); - private readonly OsuSpriteText headerText; + private OsuSpriteText headerText = null!; - private readonly Container headerContent; + private Container headerContent = null!; + + private Box background = null!; + + private IconButton expandButton = null!; /// /// Create a new instance. @@ -49,20 +63,24 @@ namespace osu.Game.Overlays /// The title to be displayed in the header of this group. public SettingsToolboxGroup(string title) { + this.title = title; + AutoSizeAxes = Axes.Y; Width = CONTAINER_WIDTH; Masking = true; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { CornerRadius = corner_radius; - BorderColour = Color4.Black; - BorderThickness = border_thickness; InternalChildren = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.5f, + Colour = colourProvider.Background5, }, new FillFlowContainer { @@ -88,7 +106,7 @@ namespace osu.Game.Overlays Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), Padding = new MarginPadding { Left = 10, Right = 30 }, }, - new IconButton + expandButton = new IconButton { Origin = Anchor.Centre, Anchor = Anchor.CentreRight, @@ -99,19 +117,7 @@ namespace osu.Game.Overlays }, } }, - content = new FillFlowContainer - { - Name = @"Content", - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Direction = FillDirection.Vertical, - RelativeSizeAxes = Axes.X, - AutoSizeDuration = transition_duration, - AutoSizeEasing = Easing.OutQuint, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding(15), - Spacing = new Vector2(0, 15), - } + content } }, }; @@ -175,9 +181,10 @@ namespace osu.Game.Overlays private void updateFadeState() { - this.FadeTo(IsHovered ? 1 : inactive_alpha, fade_duration, Easing.OutQuint); - } + const float fade_duration = 500; - protected override Container Content => content; + background.FadeTo(IsHovered ? 1 : 0, fade_duration, Easing.OutQuint); + expandButton.FadeTo(IsHovered ? 1 : 0, fade_duration, Easing.OutQuint); + } } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index e32d3d90be..2d096f1c38 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -71,6 +71,9 @@ namespace osu.Game.Screens.Play private AudioFilter lowPassFilter = null!; private AudioFilter highPassFilter = null!; + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + protected bool BackgroundBrightnessReduction { set From 4d99c7002be11fa31e5d22c91227cb7cceb80084 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Oct 2022 16:33:01 +0900 Subject: [PATCH 74/82] Add background behind editor toolbox groups --- .../Edit/DistancedHitObjectComposer.cs | 31 ++++++++++---- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 40 +++++++++++++------ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index 4726211666..5f1f7a1fbf 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -8,6 +8,8 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Localisation; @@ -52,20 +54,33 @@ namespace osu.Game.Rulesets.Edit } [BackgroundDependencyLoader] - private void load() + private void load(OverlayColourProvider colourProvider) { - AddInternal(RightSideToolboxContainer = new ExpandingToolboxContainer(130, 250) + AddInternal(new Container { - Padding = new MarginPadding(10), - Alpha = DistanceSpacingMultiplier.Disabled ? 0 : 1, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Child = new EditorToolboxGroup("snapping") + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] { - Child = distanceSpacingSlider = new ExpandableSlider> + new Box { - Current = { BindTarget = DistanceSpacingMultiplier }, - KeyboardStep = adjust_step, + Colour = colourProvider.Background5, + RelativeSizeAxes = Axes.Both, + }, + RightSideToolboxContainer = new ExpandingToolboxContainer(130, 250) + { + Padding = new MarginPadding(10), + Alpha = DistanceSpacingMultiplier.Disabled ? 0 : 1, + Child = new EditorToolboxGroup("snapping") + { + Child = distanceSpacingSlider = new ExpandableSlider> + { + Current = { BindTarget = DistanceSpacingMultiplier }, + KeyboardStep = adjust_step, + } + } } } }); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 37c66037eb..63f0c64c80 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -12,10 +12,12 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Game.Beatmaps; +using osu.Game.Overlays; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mods; @@ -80,7 +82,7 @@ namespace osu.Game.Rulesets.Edit dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); [BackgroundDependencyLoader] - private void load() + private void load(OverlayColourProvider colourProvider) { Config = Dependencies.Get().GetConfigFor(Ruleset); @@ -116,25 +118,37 @@ namespace osu.Game.Rulesets.Edit .WithChild(BlueprintContainer = CreateBlueprintContainer()) } }, - new ExpandingToolboxContainer(90, 200) + new Container { - Padding = new MarginPadding(10), + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, Children = new Drawable[] { - new EditorToolboxGroup("toolbox (1-9)") + new Box { - Child = toolboxCollection = new EditorRadioButtonCollection { RelativeSizeAxes = Axes.X } + Colour = colourProvider.Background5, + RelativeSizeAxes = Axes.Both, }, - new EditorToolboxGroup("toggles (Q~P)") + new ExpandingToolboxContainer(60, 200) { - Child = togglesCollection = new FillFlowContainer + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - }, - } + new EditorToolboxGroup("toolbox (1-9)") + { + Child = toolboxCollection = new EditorRadioButtonCollection { RelativeSizeAxes = Axes.X } + }, + new EditorToolboxGroup("toggles (Q~P)") + { + Child = togglesCollection = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + }, + } + } + }, } }, }; From 15f9697c9f0d69ff3a09587761b3b72a9e15f7a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Oct 2022 16:33:09 +0900 Subject: [PATCH 75/82] Roughly update design of editor buttons --- .../RadioButtons/EditorRadioButton.cs | 26 ++++++---------- .../TernaryButtons/DrawableTernaryButton.cs | 30 +++++++------------ 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs index 82e94dc862..071bb9fdcb 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs @@ -8,13 +8,12 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; -using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osuTK; using osuTK.Graphics; @@ -30,9 +29,9 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons public readonly RadioButton Button; private Color4 defaultBackgroundColour; - private Color4 defaultBubbleColour; + private Color4 defaultIconColour; private Color4 selectedBackgroundColour; - private Color4 selectedBubbleColour; + private Color4 selectedIconColour; private Drawable icon; @@ -50,20 +49,13 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OverlayColourProvider colourProvider) { - defaultBackgroundColour = colours.Gray3; - defaultBubbleColour = defaultBackgroundColour.Darken(0.5f); - selectedBackgroundColour = colours.BlueDark; - selectedBubbleColour = selectedBackgroundColour.Lighten(0.5f); + defaultBackgroundColour = colourProvider.Background3; + selectedBackgroundColour = colourProvider.Background1; - Content.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Radius = 2, - Offset = new Vector2(0, 1), - Colour = Color4.Black.Opacity(0.5f) - }; + defaultIconColour = defaultBackgroundColour.Darken(0.5f); + selectedIconColour = selectedBackgroundColour.Lighten(0.5f); Add(icon = (Button.CreateIcon?.Invoke() ?? new Circle()).With(b => { @@ -98,7 +90,7 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons return; BackgroundColour = Button.Selected.Value ? selectedBackgroundColour : defaultBackgroundColour; - icon.Colour = Button.Selected.Value ? selectedBubbleColour : defaultBubbleColour; + icon.Colour = Button.Selected.Value ? selectedIconColour : defaultIconColour; } protected override SpriteText CreateText() => new OsuSpriteText diff --git a/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs b/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs index 55302833c1..1fb5c0285d 100644 --- a/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs +++ b/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs @@ -6,12 +6,11 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osuTK; using osuTK.Graphics; @@ -20,9 +19,9 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons internal class DrawableTernaryButton : OsuButton { private Color4 defaultBackgroundColour; - private Color4 defaultBubbleColour; + private Color4 defaultIconColour; private Color4 selectedBackgroundColour; - private Color4 selectedBubbleColour; + private Color4 selectedIconColour; private Drawable icon; @@ -38,20 +37,13 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OverlayColourProvider colourProvider) { - defaultBackgroundColour = colours.Gray3; - defaultBubbleColour = defaultBackgroundColour.Darken(0.5f); - selectedBackgroundColour = colours.BlueDark; - selectedBubbleColour = selectedBackgroundColour.Lighten(0.5f); + defaultBackgroundColour = colourProvider.Background3; + selectedBackgroundColour = colourProvider.Background1; - Content.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Radius = 2, - Offset = new Vector2(0, 1), - Colour = Color4.Black.Opacity(0.5f) - }; + defaultIconColour = defaultBackgroundColour.Darken(0.5f); + selectedIconColour = selectedBackgroundColour.Lighten(0.5f); Add(icon = (Button.CreateIcon?.Invoke() ?? new Circle()).With(b => { @@ -85,17 +77,17 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons switch (Button.Bindable.Value) { case TernaryState.Indeterminate: - icon.Colour = selectedBubbleColour.Darken(0.5f); + icon.Colour = selectedIconColour.Darken(0.5f); BackgroundColour = selectedBackgroundColour.Darken(0.5f); break; case TernaryState.False: - icon.Colour = defaultBubbleColour; + icon.Colour = defaultIconColour; BackgroundColour = defaultBackgroundColour; break; case TernaryState.True: - icon.Colour = selectedBubbleColour; + icon.Colour = selectedIconColour; BackgroundColour = selectedBackgroundColour; break; } From 6608ada925cc9f12987723b419e10132ee1bab37 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Oct 2022 16:57:37 +0900 Subject: [PATCH 76/82] Fix test failures due to missing colour provider dependency --- .../Editor/TestSceneOsuDistanceSnapGrid.cs | 4 ++++ .../Visual/Editing/TestSceneEditorComposeRadioButtons.cs | 5 +++++ osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs | 4 ---- osu.Game/Overlays/SettingsToolboxGroup.cs | 6 +++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs index c102678e00..dc74d38cdc 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Utils; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Edit; @@ -33,6 +34,9 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [Cached(typeof(IBeatSnapProvider))] private readonly EditorBeatmap editorBeatmap; + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + [Cached] private readonly EditorClock editorClock; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs index 56435c69a4..6a69347651 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs @@ -4,8 +4,10 @@ #nullable disable using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Overlays; using osu.Game.Screens.Edit.Components.RadioButtons; namespace osu.Game.Tests.Visual.Editing @@ -13,6 +15,9 @@ namespace osu.Game.Tests.Visual.Editing [TestFixture] public class TestSceneEditorComposeRadioButtons : OsuTestScene { + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + public TestSceneEditorComposeRadioButtons() { EditorRadioButtonCollection collection; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs index adb495f3d3..58b5b41702 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs @@ -148,10 +148,6 @@ namespace osu.Game.Tests.Visual.Editing }); AddAssert("no circles placed", () => editorBeatmap.HitObjects.Count == 0); - - AddStep("place circle", () => InputManager.Click(MouseButton.Left)); - - AddAssert("circle placed", () => editorBeatmap.HitObjects.Count == 1); } [Test] diff --git a/osu.Game/Overlays/SettingsToolboxGroup.cs b/osu.Game/Overlays/SettingsToolboxGroup.cs index 2f47019272..008479b8e0 100644 --- a/osu.Game/Overlays/SettingsToolboxGroup.cs +++ b/osu.Game/Overlays/SettingsToolboxGroup.cs @@ -70,8 +70,8 @@ namespace osu.Game.Overlays Masking = true; } - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + [BackgroundDependencyLoader(true)] + private void load(OverlayColourProvider? colourProvider) { CornerRadius = corner_radius; @@ -80,7 +80,7 @@ namespace osu.Game.Overlays background = new Box { RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background5, + Colour = colourProvider?.Background5 ?? Color4.Black, }, new FillFlowContainer { From a93c350ca85944d38b09744801a7ac8f6b361411 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Oct 2022 17:11:56 +0900 Subject: [PATCH 77/82] Start settings panels without background visible --- osu.Game/Overlays/SettingsToolboxGroup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/SettingsToolboxGroup.cs b/osu.Game/Overlays/SettingsToolboxGroup.cs index 008479b8e0..37c8ec749d 100644 --- a/osu.Game/Overlays/SettingsToolboxGroup.cs +++ b/osu.Game/Overlays/SettingsToolboxGroup.cs @@ -80,6 +80,7 @@ namespace osu.Game.Overlays background = new Box { RelativeSizeAxes = Axes.Both, + Alpha = 0, Colour = colourProvider?.Background5 ?? Color4.Black, }, new FillFlowContainer From df66a0c2e9ce41e5b180cf33f9e82c0864838fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 13 Oct 2022 21:03:52 +0200 Subject: [PATCH 78/82] Fix flaky update beatmap set test It is generally not possible to click a button that's not yet there, and it turns out that when the test in question is ran headless, it may not necessarily be there immediately. --- .../Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs index f76f050546..96cfbe4dd1 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; @@ -150,6 +151,7 @@ namespace osu.Game.Tests.Visual.SongSelect public void TestUpdateLocalBeatmap() { DialogOverlay dialogOverlay = null!; + UpdateBeatmapSetButton? updateButton = null; AddStep("create carousel with dialog overlay", () => { @@ -176,7 +178,8 @@ namespace osu.Game.Tests.Visual.SongSelect carousel.UpdateBeatmapSet(testBeatmapSetInfo); }); - AddStep("click button", () => getUpdateButton()?.TriggerClick()); + AddUntilStep("wait for update button", () => (updateButton = getUpdateButton()) != null); + AddStep("click button", () => updateButton.AsNonNull().TriggerClick()); AddAssert("dialog displayed", () => dialogOverlay.CurrentDialog is UpdateLocalConfirmationDialog); AddStep("click confirmation", () => From 516e99df7264b59fe4097bfffb358bf3c88e1e44 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 14 Oct 2022 02:38:43 +0300 Subject: [PATCH 79/82] Add test coverage for flashlight mod --- .../Mods/TestSceneCatchModFlashlight.cs | 23 +++++++++++++++++ .../Mods/TestSceneManiaModFlashlight.cs | 23 +++++++++++++++++ .../Mods/TestSceneOsuModFlashlight.cs | 25 +++++++++++++++++++ .../TestSceneOsuFlashlight.cs | 21 ---------------- .../Mods/TestSceneTaikoModFlashlight.cs | 20 +++++++++++++++ 5 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModFlashlight.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFlashlight.cs create mode 100644 osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs delete mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs create mode 100644 osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModFlashlight.cs diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModFlashlight.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModFlashlight.cs new file mode 100644 index 0000000000..538fc7fac6 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModFlashlight.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Catch.Mods; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Catch.Tests.Mods +{ + public class TestSceneCatchModFlashlight : ModTestScene + { + protected override Ruleset CreatePlayerRuleset() => new CatchRuleset(); + + [TestCase(1f)] + [TestCase(0.5f)] + [TestCase(1.25f)] + [TestCase(1.5f)] + public void TestSizeMultiplier(float sizeMultiplier) => CreateModTest(new ModTestData { Mod = new CatchModFlashlight { SizeMultiplier = { Value = sizeMultiplier } }, PassCondition = () => true }); + + [Test] + public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new CatchModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true }); + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFlashlight.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFlashlight.cs new file mode 100644 index 0000000000..0e222fea89 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFlashlight.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Mania.Tests.Mods +{ + public class TestSceneManiaModFlashlight : ModTestScene + { + protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); + + [TestCase(1f)] + [TestCase(0.5f)] + [TestCase(1.5f)] + [TestCase(3f)] + public void TestSizeMultiplier(float sizeMultiplier) => CreateModTest(new ModTestData { Mod = new ManiaModFlashlight { SizeMultiplier = { Value = sizeMultiplier } }, PassCondition = () => true }); + + [Test] + public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new ManiaModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true }); + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs new file mode 100644 index 0000000000..704a548c61 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Osu.Mods; + +namespace osu.Game.Rulesets.Osu.Tests.Mods +{ + public class TestSceneOsuModFlashlight : OsuModTestScene + { + [TestCase(600)] + [TestCase(120)] + [TestCase(1200)] + public void TestFollowDelay(double followDelay) => CreateModTest(new ModTestData { Mod = new OsuModFlashlight { FollowDelay = { Value = followDelay } }, PassCondition = () => true }); + + [TestCase(1f)] + [TestCase(0.5f)] + [TestCase(1.5f)] + [TestCase(2f)] + public void TestSizeMultiplier(float sizeMultiplier) => CreateModTest(new ModTestData { Mod = new OsuModFlashlight { SizeMultiplier = { Value = sizeMultiplier } }, PassCondition = () => true }); + + [Test] + public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new OsuModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true }); + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs deleted file mode 100644 index e0d1646cb0..0000000000 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs +++ /dev/null @@ -1,21 +0,0 @@ -// 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.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Tests.Visual; - -namespace osu.Game.Rulesets.Osu.Tests -{ - public class TestSceneOsuFlashlight : TestSceneOsuPlayer - { - protected override TestPlayer CreatePlayer(Ruleset ruleset) - { - SelectedMods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), }; - - return base.CreatePlayer(ruleset); - } - } -} diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModFlashlight.cs new file mode 100644 index 0000000000..417b59f5d2 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModFlashlight.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Taiko.Mods; + +namespace osu.Game.Rulesets.Taiko.Tests.Mods +{ + public class TestSceneTaikoModFlashlight : TaikoModTestScene + { + [TestCase(1f)] + [TestCase(0.5f)] + [TestCase(1.25f)] + [TestCase(1.5f)] + public void TestSizeMultiplier(float sizeMultiplier) => CreateModTest(new ModTestData { Mod = new TaikoModFlashlight { SizeMultiplier = { Value = sizeMultiplier } }, PassCondition = () => true }); + + [Test] + public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new TaikoModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true }); + } +} From 525f98c1581540116a8633b76076ec67362bd396 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 14 Oct 2022 18:01:54 +0900 Subject: [PATCH 80/82] Fix max combo missing from playlists results screen --- osu.Game/Online/Rooms/MultiplayerScore.cs | 4 +++- .../Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Rooms/MultiplayerScore.cs b/osu.Game/Online/Rooms/MultiplayerScore.cs index 6f597e5b10..d5e0c7a970 100644 --- a/osu.Game/Online/Rooms/MultiplayerScore.cs +++ b/osu.Game/Online/Rooms/MultiplayerScore.cs @@ -65,7 +65,7 @@ namespace osu.Game.Online.Rooms [CanBeNull] public MultiplayerScoresAround ScoresAround { get; set; } - public ScoreInfo CreateScoreInfo(RulesetStore rulesets, PlaylistItem playlistItem, [NotNull] BeatmapInfo beatmap) + public ScoreInfo CreateScoreInfo(ScoreManager scoreManager, RulesetStore rulesets, PlaylistItem playlistItem, [NotNull] BeatmapInfo beatmap) { var ruleset = rulesets.GetRuleset(playlistItem.RulesetID); if (ruleset == null) @@ -90,6 +90,8 @@ namespace osu.Game.Online.Rooms Position = Position, }; + scoreManager.PopulateMaximumStatistics(scoreInfo); + return scoreInfo; } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs index 41633c34ce..27193d3cb6 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs @@ -182,7 +182,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists /// An optional pivot around which the scores were retrieved. private void performSuccessCallback([NotNull] Action> callback, [NotNull] List scores, [CanBeNull] MultiplayerScores pivot = null) => Schedule(() => { - var scoreInfos = scoreManager.OrderByTotalScore(scores.Select(s => s.CreateScoreInfo(rulesets, playlistItem, Beatmap.Value.BeatmapInfo))).ToArray(); + var scoreInfos = scoreManager.OrderByTotalScore(scores.Select(s => s.CreateScoreInfo(scoreManager, rulesets, playlistItem, Beatmap.Value.BeatmapInfo))).ToArray(); // Select a score if we don't already have one selected. // Note: This is done before the callback so that the panel list centres on the selected score before panels are added (eliminating initial scroll). From 2404bb42b9d2fc6980d5cffa305b63a4be733944 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Oct 2022 19:33:49 +0900 Subject: [PATCH 81/82] Use 10% alpha rather than 0% when toolbox is not hovered --- osu.Game/Overlays/SettingsToolboxGroup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SettingsToolboxGroup.cs b/osu.Game/Overlays/SettingsToolboxGroup.cs index 37c8ec749d..27f727c9e3 100644 --- a/osu.Game/Overlays/SettingsToolboxGroup.cs +++ b/osu.Game/Overlays/SettingsToolboxGroup.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays background = new Box { RelativeSizeAxes = Axes.Both, - Alpha = 0, + Alpha = 0.1f, Colour = colourProvider?.Background5 ?? Color4.Black, }, new FillFlowContainer @@ -184,7 +184,7 @@ namespace osu.Game.Overlays { const float fade_duration = 500; - background.FadeTo(IsHovered ? 1 : 0, fade_duration, Easing.OutQuint); + background.FadeTo(IsHovered ? 1 : 0.1f, fade_duration, Easing.OutQuint); expandButton.FadeTo(IsHovered ? 1 : 0, fade_duration, Easing.OutQuint); } } From 32c3e35762eeb42f8088717f99097594278504b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Oct 2022 19:38:27 +0900 Subject: [PATCH 82/82] Change background colour to a lighter tint to avoid clash with slider bars --- osu.Game/Overlays/SettingsToolboxGroup.cs | 2 +- osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SettingsToolboxGroup.cs b/osu.Game/Overlays/SettingsToolboxGroup.cs index 27f727c9e3..04c9a626b5 100644 --- a/osu.Game/Overlays/SettingsToolboxGroup.cs +++ b/osu.Game/Overlays/SettingsToolboxGroup.cs @@ -81,7 +81,7 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, Alpha = 0.1f, - Colour = colourProvider?.Background5 ?? Color4.Black, + Colour = colourProvider?.Background4 ?? Color4.Black, }, new FillFlowContainer { diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index 5f1f7a1fbf..667a3cb409 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -71,7 +71,6 @@ namespace osu.Game.Rulesets.Edit }, RightSideToolboxContainer = new ExpandingToolboxContainer(130, 250) { - Padding = new MarginPadding(10), Alpha = DistanceSpacingMultiplier.Disabled ? 0 : 1, Child = new EditorToolboxGroup("snapping") {